在JavaScript中计算ECDH共享密钥

时间:2014-10-27 19:12:07

标签: javascript cryptography

我需要使用ECC密钥和ECDH在JavaScript中计算共享密钥。我看到两个可能的项目可能会这样做,但我不确定哪个可以追求:

  1. https://code.google.com/p/end-to-end
  2. https://github.com/bitwiseshiftleft/sjcl
  3. 1)是Chrome扩展,所以我认为这意味着它不会在其他浏览器中运行。 2)有人对SJCL有疑问,说他们认为这是使用ECMQV而不是简单的ECDH(Can't bridge Elliptic Curve Diffie-Hellman with javascript)。

    有人可以为我的实施建议一个好的行动方案吗?选项3(首选方案):我有一种预感可能是直接在这里包含共享秘密实现:https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/src/ecdsa.js

    这是用于在服务器上创建共享密钥的C ++代码:

    void * ecies_key_derivation(const void *input, size_t ilen, void *output, size_t *olen) 
        {
            *olen = SHA512_DIGEST_LENGTH;
            return (void*)SHA512((const unsigned char*)input, ilen, (unsigned char*)output);
        }
    ...
    fc::sha512 shared_secret;
    ECDH_compute_key( (unsigned char*)&shared_secret, sizeof(shared_secret), EC_KEY_get0_public_key(recipient.my->_key), my->_key, ecies_key_derivation );  
    

1 个答案:

答案 0 :(得分:2)

显然这需要巩固,但它至少有效!

选项1是特定于铬的: https://bugzilla.mozilla.org/show_bug.cgi?id=1022106 "粗略地看一下代码(git clone-able来自git clone https://code.google.com/p/end-to-end/),它似乎非常适合作为仅限Chrome的附加组件"

选项2的工作原理如此,使用bitcore(bitcore在幕后使用sjcl):

    # npm install bitcore
    ECIES = require '../node_modules/bitcore/lib/ECIES'
    ot_pubkey = new Buffer(onetime_public_key, 'hex')
    my_privkey = new Buffer(d_receiver_hex, 'hex')
    ecies = new ECIES.encryptObj ot_pubkey, new Buffer(''), my_privkey
    S = ecies.getSfromPubkey()
    console.log 'bitcore sharedsecret\t',S.toString 'hex'
    S_kdf_buf = ECIES.kdf(S)

    console.log 'bitcore sharedsecret kdf\t',S_kdf_buf.toString 'hex'

此外,elliptic.js使用它自己的代码,包括bn.js用于大数字(同一作者):

    # git clone https://github.com/indutny/elliptic.git
    elliptic = require('../elliptic/lib/elliptic.js')

    # npm install bn.js
    bn = require('bn.js')

    #Providing ecies_key_derivation https://github.com/indutny/elliptic/issues/9
    ec = new elliptic.ec('secp256k1')

    s0 = ec.keyPair(onetime_private_key, 'hex')

    # ../testnet/config/genesis_private_keys.txt

    s1 = ec.keyPair(d_receiver_hex, "hex")

    sh0 = s0.derive(s1.getPublic())
    sh1 = s1.derive(s0.getPublic())    
    assert.equal sh0.toString(16), sh1.toString(16), "shared secret did not match"

    shared_secret = "0"+sh0.toString(16) #### only works for this shared secret (bn.js::toString(16))

此时,我得到了这些库以正确生成共享机密。为了解密,我最终使用了crypto-js。

    # https://code.google.com/p/crypto-js/#Custom_Key_and_IV
    # see wallet_records.cpp master_key::decrypt_key
    CryptoJS.AES.decrypt(
      ciphertext: cipher
      salt: null
    , @key,
      iv: @iv
    )

对于解密,我需要一个256位的IV(初始化向量)来完成任务,这样就可以将SJCL保留到更新状态(https://github.com/bitwiseshiftleft/sjcl/issues/197)。另外,虽然我不确定这是不是我的错误,但我没有太多运气用elliptic.js解密。