JS 中使用 SJCL 以及 Ruby 中使用 OpenSSL 的椭圆曲线加密

2023-11-25

我正在开发一个 Web 应用程序,它必须能够在服务器端使用 ECC 加密数据并在浏览器中解密。我发现在 JS 中唯一能够实现此功能的库是 SJCL。然而,由于 SJCL 中的 ECC 支持目前似乎有点被放弃,所以我使用了fork,它具有密钥序列化支持和demo为了更容易理解。

首先,我在 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 和 y 坐标,2*48 字节),而 OpenSSL 输出的是共享密钥(点的 x 坐标,由 ECDH 指定)。

我的问题是,我不知道 OpenSSL 中是否有对 ECMQV 的支持(如果我是正确的,有一些专利问题)。即使有,Ruby 绑定似乎也不支持它。

所以我的实际问题是:

  • 上面记录的我的发现正确吗?
  • 如果是,有谁知道我可以使用其他支持 ECMQV 的 ruby​​ 库来代替 OpenSSL 吗?

看起来你正在使用ElGamal在你的 JavaScript 代码中。我真的找不到 ruby​​ 的任何实现,替代方案正在使用Crypto++ or 库加密并编写一些粘合代码。

PS:代替那个kstr =线,你可以简单地写kstr = ar.pack 'N*'

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JS 中使用 SJCL 以及 Ruby 中使用 OpenSSL 的椭圆曲线加密 的相关文章

随机推荐