首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何格式化OpenSSL键以匹配联机示例(JSBN)

如何格式化OpenSSL键以匹配联机示例(JSBN)
EN

Stack Overflow用户
提问于 2014-03-14 16:31:17
回答 3查看 684关注 0票数 2

我希望能够将OpenSSL - Ruby中椭圆曲线Diffie-Hellman的公钥格式化为类似于(链接)的在线示例,因为我一直在使用JS库。

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

代码语言:javascript
复制
#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文档并没有真正的帮助,我一直在研究如何转换上面生成的公钥:

代码语言:javascript
复制
499599043529551953518354858381998373780459818901085313561109939106744612770290

像这样的东西(从在线网站上看到):

代码语言:javascript
复制
x: 107060165679262225845922473865530329196
y: 109296969851421346147544217212275741170

我假设,通过适当地转换其中一个,它可以变得与另一个相等,因为它们有相同的曲线参数。还是我错了?(也因为point_conversion_form的默认格式是:uncompressed,正如我刚刚测试的那样)请帮助。

你可能想知道我为什么要把公钥转换成另一个。不我没必要这么做。我只想学习如何转换它,因为我将使用这种方法来转换类似的东西。这是一个简化的测试问题--方便。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-03-16 12:25:51

终于来了!我设法正确地转换了它,但这有点奇怪。

代码语言:javascript
复制
#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现在匹配在线链接的结果。

票数 0
EN

Stack Overflow用户

发布于 2015-01-04 04:48:09

杰伊-阿尔,

您不应该觉得您的解决方案很奇怪,因为我认为对ec.public_key.to_bn的调用可能是坚持rfc5480第2.2节 re:Subject Public Keys,其中声明:

2.2。主题公钥

  • 八进制字符串的第一个八进制指示键是压缩的还是未压缩的。未压缩表单由0x04表示,压缩形式由0x02或0x03表示(参见SEC1中的2.3.3 )。如果第一个八进制中包含任何其他值,则必须拒绝公钥。

假设是这样的,并且由于您声明格式是:uncompressed,,您自己的回答对我来说完全是有意义的。(谢谢你张贴!:)

票数 2
EN

Stack Overflow用户

发布于 2014-03-14 16:44:13

代码语言:javascript
复制
ec.public_key.to_bn
#--> 499599043529551953518354858381998373780459818901085313561109939106744612770290

最好用十六进制打印出来。

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

代码语言:javascript
复制
x = 499599043529551953518354858381998373780
y = 459818901085313561109939106744612770290

公钥是一个点,因为它是从基点G派生出来的,它也是一个点。G有时被扩展为(g_x, g_y)。私有指数是a (或b),它是标量或整数。所以公钥是A=G^aA=(g_x, g_y)^a,这是一个点。

也是因为point_conversion_form的默认格式是:未压缩的,正如我刚才测试的那样

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

你可能会想我为什么要把公钥转换成另一个..。

否:)

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22410765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档