椭圆曲线密码与红宝石SJCL在JS和OpenSSL(Elliptic curve cryptogra

2019-06-25 16:03发布

我的工作,必须能够将数据与ECC服务器端加密并在浏览器解密它的Web应用程序。 我发现,能够在这个JS的唯一库是SJCL。 然而,由于SJCL ECC支持似乎有点此刻抛弃了,我使用了一个叉 ,其关键序列化支持和演示更容易理解。

首先,我产生一个JS ECC密钥对:

keypair = sjcl.ecc.elGamal.generateKeys(384, 10);
document.writeln(JSON.stringify(keypair.pub.serialize()));

这个输出是这样的:

{"point":[1110230655,241884220,775655552,-849225963,-883815628,-1984298210,-736346431,1387519594,-1810604283,-1235638489,1333314084,-1219216530,614640565,-1148742381,1038670260,1013716131,758346573,1162278003,1232401864,-1948620456,533899535,-1478577959,1853846180,-1553049184],"curve":384}

然后我试图此公钥转换成由OpenSSL的理解的格式。

ar = [1110230655,241884220,775655552,-849225963,-883815628,-1984298210,-736346431,1387519594,-1810604283,-1235638489,1333314084,-1219216530,614640565,-1148742381,1038670260,1013716131,758346573,1162278003,1232401864,-1948620456,533899535,-1478577959,1853846180,-1553049184]

# ugly bit magic to somehow convert the above array into a proper byte array (in form of a string)
kstr = [(ar.map { |i| (i>=0)?('0'*(8-i.to_s(16).length)+i.to_s(16)):("%08X" % (2**32-1+i+1)) }*'').upcase].pack("H*")

# opening a public key generated with the openssl cli tool showed a structure like this:
algokey = OpenSSL::ASN1::ObjectId 'id-ecPublicKey'
algovalue = OpenSSL::ASN1::ObjectId 'secp384r1'
algo = OpenSSL::ASN1::Sequence.new [algokey,algovalue]
# for some reason OpenSSL seems to prepend 0x04 to all public keys
key = OpenSSL::ASN1::BitString.new "\x04#{kstr}"
root = OpenSSL::ASN1::Sequence.new [algo,key]

pub = OpenSSL::PKey.read(root.to_der)

直到此时,我的代码工作正常。 也就是说,它不会产生任何异常。

然而,产生与这两个库的共享秘密的情况下,我发现SJCL产生的“标签”,这是96个字节长,而OpenSSL的发射48个字节。

结果我发现我的问题是,SJCL不使用纯ECDH。 它使用的东西,似乎是基于一个快速谷歌搜索中ECMQV。 因此,“标签” SJCL输出是曲线(X和A点的y坐标,2×48个字节)上的点,而什么OpenSSL的输出是一个共享秘密(X的点的坐标,通过ECDH所指示)。

我的问题是,我不知道是否有在OpenSSL,以便ECMQV任何支持(也有一些专利问题,如果我是正确的)。 即使有,红宝石结合似乎并不支持它。

所以我实际的问题:

  • 是我的发现上面记录正确?
  • 如果是的话,没有人知道任何其他的Ruby库,我可以使用,而不是OpenSSL的,支持ECMQV?

Answer 1:

它看起来像你使用的ElGamal在JavaScript代码。 我真的无法找到任何的Ruby实现,替代方案是使用加密+或libgcrypt并编写一些胶水代码。

PS:不是说kstr =行,你可以简单的写kstr = ar.pack 'N*'



文章来源: Elliptic curve cryptography with SJCL in JS and OpenSSL in Ruby