简体   繁体   English

使用JS中的SJCL和Ruby中的OpenSSL进行椭圆曲线加密

[英]Elliptic curve cryptography with SJCL in JS and OpenSSL in Ruby

I am working on a web application which must be able to encrypt data with ECC on the server side and decrypt it in the browser. 我正在开发一个Web应用程序,它必须能够在服务器端使用ECC加密数据并在浏览器中解密。 The only library I have found that is capable of this in JS is SJCL. 我发现在JS中唯一可以使用的库是SJCL。 However, since ECC support in SJCL seems a bit abandoned at the moment, I have used a fork , which has key serialization support and a demo for easier understanding. 但是,由于目前SJCL中的ECC支持似乎有点放弃,我使用了fork ,它具有密钥序列化支持和演示 ,以便于理解。

First, I generate an ECC key pair in JS: 首先,我在JS中生成一个ECC密钥对:

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

This outputs something like: 这输出如下:

{"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}

Then I have tried to convert this public key to a format understandable by OpenSSL. 然后我尝试将此公钥转换为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)

Until this point, my code works fine. 在此之前,我的代码工作正常。 That is, it does not produce any exceptions. 也就是说,它不会产生任何例外。

However, when generating a shared secret with both libraries, I found that SJCL generated a 'tag' that was 96 bytes long, while OpenSSL emitted 48 bytes. 但是,当与两个库生成共享密钥时,我发现SJCL生成了一个96字节长的“标签”,而OpenSSL发出了48个字节。

Turns out my problem is that SJCL does not use plain ECDH. 原来我的问题是SJCL不使用普通的ECDH。 It uses something that seems to be ECMQV based on a quick google search. 它使用基于快速谷歌搜索的似乎是ECMQV的东西。 Therefore, the 'tag' SJCL output was a point on the curve (x and y coordinates of a point, 2*48 bytes), while what OpenSSL output was a shared secret (x coordinate of a point, as dictated by ECDH). 因此,'标签'SJCL输出是曲线上的一个点(一个点的x和y坐标,2 * 48个字节),而OpenSSL输出是一个共享秘密(一个点的x坐标,由ECDH指示)。

My problem is that I don't know if there is any support for ECMQV in OpenSSL (there are some patent problems, if I'm correct). 我的问题是我不知道OpenSSL中是否有对ECMQV的支持(如果我是正确的,有一些专利问题)。 Even if there was, the ruby binding does not seem to support it. 即使有,红宝石绑定似乎也不支持它。

So my actual questions: 所以我的实际问题:

  • are my findings documented above correct? 我的发现是否记录在上面?
  • if yes, does anyone know any other ruby library which I could use instead of OpenSSL, that supports ECMQV? 如果是的话,有没有人知道我可以使用的任何其他ruby库而不是支持ECMQV的OpenSSL?

It looks like you're using ElGamal in your javascript code. 看起来你在javascript代码中使用了ElGamal I couldn't really find any implementation for ruby, alternatives are using Crypto++ or libgcrypt and writing some glue code. 我真的找不到ruby的任何实现,替代方案是使用Crypto ++libgcrypt并编写一些粘合代码。

Ps: instead of that kstr = line, you can simply write kstr = ar.pack 'N*' Ps:而不是kstr = line,你可以简单地写kstr = ar.pack 'N*'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM