【问题标题】:How to Format OpenSSL Keys to Match Online Sample (JSBN-ECC)如何格式化 OpenSSL 密钥以匹配在线示例 (JSBN-ECC)
【发布时间】:2014-03-14 16:31:17
【问题描述】:

我希望能够将 OpenSSL - Ruby 中 Elliptic Curve Diffie-Hellman 的公钥格式化为类似于此在线示例 (link) 的内容,因为我一直在使用该 JS 库。

我下面的代码生成一个 OpenSSL::PKey::EC 公钥和私钥

#Ruby
ec = OpenSSL::PKey::EC.new('secp128r1')
ec.generate_key

ec.private_key
#--> 205607153615223513963863936713567041725

ec.public_key.to_bn
#--> 499599043529551953518354858381998373780459818901085313561109939106744612770290

尝试复制205607153615223513963863936713567041725上方的私钥并将其粘贴到在线(link)作为Alices的私有值。但是要先点击secp1284r1按钮获得相同的曲线参数,再点击Compute Public按钮。

这将从输入的私钥生成一个公钥。但是,Ruby OpenSSL 文档并没有真正的帮助,我一直在弄清楚如何转换上面生成的公钥:

499599043529551953518354858381998373780459818901085313561109939106744612770290

变成这样(从在线网站上看到):

x: 107060165679262225845922473865530329196
y: 109296969851421346147544217212275741170

我假设通过正确转换一个,它可以以某种方式变得等于另一个,因为它们具有相同的曲线参数。还是我错了? (也因为point_conversion_form的默认格式是:uncompressed,正如我刚刚测试过的)请帮忙。

附:您可能想知道为什么我需要将公钥转换为另一个。不,我真的不需要。我只想学习如何转换它,因为我将使用该方法来转换类似的东西。这是为了方便您的测试而简化的问题。

【问题讨论】:

    标签: javascript ruby openssl elliptic-curve diffie-hellman


    【解决方案1】:

    杰-阿,

    你不应该觉得你的解决方案很奇怪,因为我认为对 ec.public_key.to_bn 的调用可能遵守rfc5480 section 2.2 re: Subject Public Keys 声明:

    2.2。主题公钥

    • OCTET STRING 的第一个八位字节表示密钥是否为 压缩或未压缩。显示未压缩的形式 由 0x04 表示,压缩形式由 0x02 或 0x03(参见 [SEC1] 中的 2.3.3)。公钥必须被拒绝,如果 任何其他值都包含在第一个八位字节中。

    假设是这种情况,并且由于您声明格式为 :uncompressed,您自己的回答对我来说完全有意义。感谢您发布它! :)

    【讨论】:

      【解决方案2】:
      ec.public_key.to_bn
      #--> 499599043529551953518354858381998373780459818901085313561109939106744612770290
      

      最好用十六进制打印。

      公钥是曲线上的一个点。也就是说,它是一个(x,y) 坐标。因此该值可能需要拆分(因此以十六进制打印的原因)。猜一猜:

      x = 499599043529551953518354858381998373780
      y = 459818901085313561109939106744612770290
      

      公钥是一个点,因为它源自基点G,这也是一个点。 G 有时会扩展为 (g_x, g_y)。私有指数是a(或b),它是一个标量或整数。所以公钥是A=G^a或者A=(g_x, g_y)^a,就是一个点。


      还因为 point_conversion_form 的默认格式是 :uncompressed,正如我刚刚测试过的那样

      点转换/压缩只是表示层优化技巧。它省略了坐标的y 部分,因为您可以在给定x 的情况下解决它。因为它是一条曲线,所以有时您需要发送+1-1 来指定y 坐标所在的象限。但同样,它只是一种优化,只对互操作很重要。将点读入库后,xy 均可用。


      您可能想知道为什么我需要将公钥转换为另一个...

      没有:)

      但您可能需要注意的一件事是 OpenSSL 的“命名曲线”标志。如果要将EC 密钥加载到基于 OpenSSL 的服务器中,则需要确保私钥和生成的证书具有 OPENSSL_EC_NAMED_CURVE 标志。否则,在尝试连接到服务器时,您会收到诸如“没有共享密码”之类的奇怪错误。有关详细信息,请参阅 OpenSSL wiki 上的 ECDH and Named Curves

      【讨论】:

      • 感谢您的回复。是的。我尝试将其转换为十六进制,然后将字符串分成两半,然后尝试将两半中的每一半转换为整数值,但不幸的是它与网站中的值不匹配。你知道ec.public_key.to_bn的格式是什么吗?
      • 对不起,我不知道,因为我不了解 Ruby(我是 OpenSSL 人)。这可能会有所帮助:Ruby openssl ECC help plz.
      • 谢谢,不过我已经阅读了这篇文章,并在互联网上搜索了任何与这个 Ruby OpenSSL 相关的东西。我真的很想知道如何转换它,因为文档并没有真正说明什么。不过谢谢你的回答,我之前问了两个类似的问题,但一个答案都没有:)
      【解决方案3】:

      终于!我以某种方式设法正确转换它,但它有点奇怪。

      #From above code
      c.public_key.to_bn
      #--> 499599043529551953518354858381998373780459818901085313561109939106744612770290
      
      #irb:
      require 'openssl'
      
      key_int = '499599043529551953518354858381998373780459818901085313561109939106744612770290'
      key_bn = OpenSSL::BN.new(key_int, 10) #Convert to OpenSSL::BN (Big Number, with 10=Decimal as base)
      key_hex = key_bn.to_s(16) #Convert to Hex String (16=Hexadecimal)
      #--> "04508B09B35FA8C21820BE19C16B38486C5239D4A932D081DD56B90F91120551F2"
      
      #I don't really know why, but removing '04' above will finally convert it properly
      key_hex = key_hex[2..-1] #Remove first 2 chars: '04'
      #--> "508B09B35FA8C21820BE19C16B38486C5239D4A932D081DD56B90F91120551F2"
      
      #Split key_hex into halves
      key_hexarr = key_hex.chars.each_slice( (key_hex.length/2.0).round ).map(&:join)
      #--> ["508B09B35FA8C21820BE19C16B38486C", "5239D4A932D081DD56B90F91120551F2"]
      
      #Convert first value into BN (input: 16=hexadecimal), then convert to string(output: 10=decimal)
      key_x_int = OpenSSL::BN.new(key_hexarr[0], 16).to_s(10)
      #--> "107060165679262225845922473865530329196"
      
      #Convert second value into BN (input: 16=hexadecimal), then convert to string(output: 10=decimal)
      key_y_int = OpenSSL::BN.new(key_hexarr[1], 16).to_s(10)
      #--> "109296969851421346147544217212275741170"
      

      最后,key_x_intkey_y_int 现在匹配来自在线链接的结果

      【讨论】:

        猜你喜欢
        • 2015-06-13
        • 2017-01-14
        • 2020-03-15
        • 1970-01-01
        • 1970-01-01
        • 2016-07-31
        • 1970-01-01
        • 2017-03-12
        • 1970-01-01
        相关资源
        最近更新 更多