如何使用Elliptic Curves Diffie-Hellman和JS中的SJCL以及Ruby中的OpenSSL

使用Elliptic-Curves Diffie-Hellman,我想在客户端上连接SLCL – JS (文档) ,在服务器上连接OpenSSL – Ruby (文档) 。

我在这里发现了一个类似的问题,但它没有得到真正的回答,而且它也不是我真正想要的,因为它使用的是sjcl.ecc.elGamal.generateKeys(384, 10)而我希望使用sjcl.ecc.curves['c384'] < – NIST

尽管如此,我仍然使用和修改他的代码进行测试,因为我在使用sjcl.ecc.curves['c384']生成单个公共点密钥时遇到了问题,这就是我想出来的。

 //Javascript keypair = sjcl.ecc.elGamal.generateKeys(384, 10); console.log(keypair.pub._point.toBits()); //Changed from his serialize() 

这输出到

 [-1992414123, 638637875, 1917312913, 73389700, -425224557, 743777818, 970253455, 723842951, -1751664279, 982132367, -1949786746, 1067402923, -869929568, 157928816, 1651634060, 1968161300, -216192372, -1858642177, -1345910998, -2128793177, -1325754797, 143080818, 1868787479, -484135391] 

使用输出ruby:

 #Ruby pointArr = [-1992414123, 638637875, 1917312913, 73389700, -425224557, 743777818, 970253455, 723842951, -1751664279, 982132367, -1949786746, 1067402923, -869929568, 157928816, 1651634060, 1968161300, -216192372, -1858642177, -1345910998, -2128793177, -1325754797, 143080818, 1868787479, -484135391] # ugly bit magic to somehow convert the above array into a proper byte array (in form of a string) pointStr = [(pointArr.map { |i| (i>=0)?('0'*(8-i.to_s(16).length)+i.to_s(16)):("%08X" % (2**32-1+i+1)) }*'').upcase].pack("H*") #My modified code pointInt = pointStr.unpack('B*').first.to_i(2) #Convert BitStr to integer pointBN = OpenSSL::BN.new(pointInt.to_s, 10) #Int to BigNumber (to be used as param below) group = OpenSSL::PKey::EC::Group.new('secp384r1') #EC Group to be used client_pub_point = OpenSSL::PKey::EC::Point.new(group, pointBN) # ^ # ^ ABOVE'S MY PROBLEM -> OpenSSL::PKey::EC::Point::Error: invalid encoding # ^ #Server EC: code taken and modified from https://www.ruby-forum.com/topic/3966195 ec = OpenSSL::PKey::EC.new(group) ec.generate_key pub = OpenSSL::PKey::EC.new(group) pub.public_key = client_pub_point #Compute Shared Key shared_key = ec.dh_compute_key(pub.public_key) puts shared_key.unpack('I>*') 

当使用上面[(link)]( https://www.ruby-forum.com/topic/3966195 )的原始代码时,这会“放置”如下所示

 3747233514 2683763564 475565567 1087119841 857380668 2490387914 3548975947 2348082236 2093543365 1477205987 4289120093 3330807042 

那应该是它,但以防万一这是我的考验

 irb(main):113:0> ec = OpenSSL::PKey::EC.new(group) => # irb(main):114:0> ec.generate_key => # irb(main):115:0> pub = OpenSSL::PKey::EC.new(group) => # irb(main):116:0> pub.public_key = ec.public_key => # irb(main):117:0> pub.public_key.to_bn => 7699789176960498967958014210931326569901199635665512831714857096185925821659134057981449113945854620725216613989823482205311316333140754760317456176281271361802541262755346331375041208726203461213190230560617504850860621520632944763 irb(main):119:0> OpenSSL::PKey::EC::Point.new(group, pub.public_key.to_bn) => # #The ABOVE FORMAT works, unlike the error I got like the following irb(main):122:0> pointBN => 832312614609895991150696681555479456971598284480953722479085426901428295415600048953528780331647571635767075686130334170313461289491500162782258792834115040597490936949579748064005380309022482780162833924377801386781542770068991521 irb(main):123:0> OpenSSL::PKey::EC::Point.new(group, pointBN) OpenSSL::PKey::EC::Point::Error: invalid encoding 

但是比较上面的工作和不工作,似乎总的十进制数字是相同的,所以我认为我有点走上正轨,但我真的无法解决它。

对于那些可能遇到这类问题的人,这些是我的参考代码(1) (2) (3) (4) (5)

我现在已经坚持了两天,网上似乎没有太多关于此的文章,我找不到任何其他支持椭圆曲线的JS库。 任何帮助将非常感激。

#Server EC:代码摘自https://www.ruby-forum.com/topic/3966195 ec = OpenSSL :: PKey :: EC.new(group)ec.generate_key …

通常,我们只使用众所周知的曲线的NID调用EC_KEY_new_by_curve_name 。 NID将包括:

  • NID_secp160k1
  • NID_secp192k1
  • NID_secp224k1
  • NID_secp256k1
  • NID_secp384r1
  • NID_secp521r1
  • 其他主要场曲线
  • 其他二元场曲线

我认为它们的完整列表可以在OpenSSL源代码中找到, obj_mac.h

 #define SN_secp112r1 "secp112r1" #define NID_secp112r1 704 #define OBJ_secp112r1 OBJ_secg_ellipticCurve,6L #define SN_secp112r2 "secp112r2" #define NID_secp112r2 705 #define OBJ_secp112r2 OBJ_secg_ellipticCurve,7L #define SN_secp128r1 "secp128r1" #define NID_secp128r1 706 #define OBJ_secp128r1 OBJ_secg_ellipticCurve,28L #define SN_secp128r2 "secp128r2" #define NID_secp128r2 707 #define OBJ_secp128r2 OBJ_secg_ellipticCurve,29L #define SN_secp160k1 "secp160k1" #define NID_secp160k1 708 #define OBJ_secp160k1 OBJ_secg_ellipticCurve,9L #define SN_secp160r1 "secp160r1" #define NID_secp160r1 709 #define OBJ_secp160r1 OBJ_secg_ellipticCurve,8L #define SN_secp160r2 "secp160r2" #define NID_secp160r2 710 #define OBJ_secp160r2 OBJ_secg_ellipticCurve,30L #define SN_secp192k1 "secp192k1" #define NID_secp192k1 711 #define OBJ_secp192k1 OBJ_secg_ellipticCurve,31L #define SN_secp224k1 "secp224k1" #define NID_secp224k1 712 #define OBJ_secp224k1 OBJ_secg_ellipticCurve,32L #define SN_secp224r1 "secp224r1" #define NID_secp224r1 713 #define OBJ_secp224r1 OBJ_secg_ellipticCurve,33L #define SN_secp256k1 "secp256k1" #define NID_secp256k1 714 #define OBJ_secp256k1 OBJ_secg_ellipticCurve,10L #define SN_secp384r1 "secp384r1" #define NID_secp384r1 715 #define OBJ_secp384r1 OBJ_secg_ellipticCurve,34L #define SN_secp521r1 "secp521r1" #define NID_secp521r1 716 #define OBJ_secp521r1 OBJ_secg_ellipticCurve,35L #define SN_sect113r1 "sect113r1" #define NID_sect113r1 717 #define OBJ_sect113r1 OBJ_secg_ellipticCurve,4L #define SN_sect113r2 "sect113r2" #define NID_sect113r2 718 #define OBJ_sect113r2 OBJ_secg_ellipticCurve,5L #define SN_sect131r1 "sect131r1" #define NID_sect131r1 719 #define OBJ_sect131r1 OBJ_secg_ellipticCurve,22L #define SN_sect131r2 "sect131r2" #define NID_sect131r2 720 #define OBJ_sect131r2 OBJ_secg_ellipticCurve,23L #define SN_sect163k1 "sect163k1" #define NID_sect163k1 721 #define OBJ_sect163k1 OBJ_secg_ellipticCurve,1L #define SN_sect163r1 "sect163r1" #define NID_sect163r1 722 #define OBJ_sect163r1 OBJ_secg_ellipticCurve,2L #define SN_sect163r2 "sect163r2" #define NID_sect163r2 723 #define OBJ_sect163r2 OBJ_secg_ellipticCurve,15L #define SN_sect193r1 "sect193r1" #define NID_sect193r1 724 #define OBJ_sect193r1 OBJ_secg_ellipticCurve,24L #define SN_sect193r2 "sect193r2" #define NID_sect193r2 725 #define OBJ_sect193r2 OBJ_secg_ellipticCurve,25L #define SN_sect233k1 "sect233k1" #define NID_sect233k1 726 #define OBJ_sect233k1 OBJ_secg_ellipticCurve,26L #define SN_sect233r1 "sect233r1" #define NID_sect233r1 727 #define OBJ_sect233r1 OBJ_secg_ellipticCurve,27L #define SN_sect239k1 "sect239k1" #define NID_sect239k1 728 #define OBJ_sect239k1 OBJ_secg_ellipticCurve,3L #define SN_sect283k1 "sect283k1" #define NID_sect283k1 729 #define OBJ_sect283k1 OBJ_secg_ellipticCurve,16L #define SN_sect283r1 "sect283r1" #define NID_sect283r1 730 #define OBJ_sect283r1 OBJ_secg_ellipticCurve,17L #define SN_sect409k1 "sect409k1" #define NID_sect409k1 731 #define OBJ_sect409k1 OBJ_secg_ellipticCurve,36L #define SN_sect409r1 "sect409r1" #define NID_sect409r1 732 #define OBJ_sect409r1 OBJ_secg_ellipticCurve,37L #define SN_sect571k1 "sect571k1" #define NID_sect571k1 733 #define OBJ_sect571k1 OBJ_secg_ellipticCurve,38L #define SN_sect571r1 "sect571r1" #define NID_sect571r1 734 #define OBJ_sect571r1 OBJ_secg_ellipticCurve,39L ... 

#Compute Shared Key shared_key = ec.dh_compute_key(pub.public_key)

在OpenSSL wiki上有一个ECDH的例子。 我相信Matt Caswell提供了它。 您可以在Elliptic Curve Diffie Hellman找到它。

我认为OpenSSL wiki示例也在这里复制/粘贴一次: BouncyCastle Java API和OpenSSL生成的ECDH秘密是不同的 。

我不知道SJCL或Ruby,所以我无法帮助你。


sjcl.ecc.curves [‘c384’] < - NIST

我相信你会想要NID_secp384r1 ,但我不知道Ruby,所以把它NID_secp384r1面值。 有关NID的命名曲线列表,请参阅OpenSSL:openssl / CHANGES openssl / apps / ecparam.c openssl / crypto ….


如果要将密钥保存到磁盘并可能稍后在证书中使用(例如,ECDSA签名),则需要设置OPENSSL_EC_NAMED_CURVE标志。 该标志只是按名称保存组参数(例如, ASN1 OID: prime256v1 ),而不是列出ASN1对象中的所有域参数(字段类型,主要或二进制字段,基点等)。

你这样做:

 EC_KEY_set_asn1_flag(key, OPENSSL_EC_NAMED_CURVE); 

如果您没有设置标志,那么在协商套件时您将遇到“无共享密码”错误。 以下是客户端和服务器上的症状:

  • 客户端(s_client):

    • 139925962778272:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1256:SSL alert number 40
    • 139925962778272:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:596:
  • 服务器(s_server):

    • 140339533272744:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher:s3_srvr.c:1353:

我终于解决了这个问题! 🙂

我使用了不同的Javascript库。 如果你正在寻找解决类似这样的问题,请参考我的另一个问题(链接)