我希望能够将OpenSSL - Ruby中椭圆曲线Diffie-Hellman的公钥格式化为类似于(链接)的在线示例,因为我一直在使用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上面的私钥,并将其粘贴到联机(链接)上,作为Alices的私有值。但是,首先单击secp1284r1按钮具有相同的曲线参数,然后单击Compute Public按钮。
它将从输入的私钥生成公钥。然而,Ruby文档并没有真正的帮助,我一直在研究如何转换上面生成的公钥:
499599043529551953518354858381998373780459818901085313561109939106744612770290像这样的东西(从在线网站上看到):
x: 107060165679262225845922473865530329196
y: 109296969851421346147544217212275741170我假设,通过适当地转换其中一个,它可以变得与另一个相等,因为它们有相同的曲线参数。还是我错了?(也因为point_conversion_form的默认格式是:uncompressed,正如我刚刚测试的那样)请帮助。
你可能想知道我为什么要把公钥转换成另一个。不我没必要这么做。我只想学习如何转换它,因为我将使用这种方法来转换类似的东西。这是一个简化的测试问题--方便。
发布于 2014-03-16 12:25:51
终于来了!我设法正确地转换了它,但这有点奇怪。
#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_int和key_y_int现在匹配在线链接的结果。
发布于 2015-01-04 04:48:09
杰伊-阿尔,
您不应该觉得您的解决方案很奇怪,因为我认为对ec.public_key.to_bn的调用可能是坚持rfc5480第2.2节 re:Subject Public Keys,其中声明:
2.2。主题公钥
假设是这样的,并且由于您声明格式是:uncompressed,,您自己的回答对我来说完全是有意义的。(谢谢你张贴!:)
发布于 2014-03-14 16:44:13
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的默认格式是:未压缩的,正如我刚才测试的那样
点转换/压缩只是表示层优化技巧。它省略了坐标的y部分,因为您可以为它求解给定的x。因为这是一条曲线,有时需要发送+1或-1来指定y坐标所在的象限。但同样,这只是一个优化,只有互操作的问题。将点读入库后,x和y都是可用的。
你可能会想我为什么要把公钥转换成另一个..。
否:)
但是您可能需要注意的一件事是OpenSSL的“命名曲线”标志。如果要将EC密钥加载到基于OpenSSL的服务器中,则需要确保私钥和由此产生的证书具有OPENSSL_EC_NAMED_CURVE标志。否则,在试图连接到服务器时,会出现一些奇怪的错误,比如“没有共享密码”。有关详细信息,请参阅ECDH和命名曲线上的OpenSSL wiki。
https://stackoverflow.com/questions/22410765
复制相似问题