I want to be able to format the public key of Elliptic Curve Diffie-Hellman in OpenSSL - Ruby into something like this online example (link), as I have been using that JS library.
My code below generates an OpenSSL::PKey::EC public and private keys
#Ruby
ec = OpenSSL::PKey::EC.new('secp128r1')
ec.generate_key
ec.private_key
#--> 205607153615223513963863936713567041725
ec.public_key.to_bn
#--> 499599043529551953518354858381998373780459818901085313561109939106744612770290
Try copying the private key above 205607153615223513963863936713567041725
and pasting it on the online (link) as Alices' Private value. But click the secp1284r1
button first to have same curve parameters, and then click Compute Public
button.
That will generate a public key from the inputted private key. However, the Ruby OpenSSL documentation isn't really helpful, and I am stuck on figuring out how to convert the generated public key above:
499599043529551953518354858381998373780459818901085313561109939106744612770290
Into something like this (as seen from the online site):
x: 107060165679262225845922473865530329196
y: 109296969851421346147544217212275741170
I've assumed that by properly converting one, it can somehow become equal to the other since they have same curve parameters. Or am I wrong? (And also because the default format of point_conversion_form
is :uncompressed
, as I just have tested) Please help.
P.S. You might wonder why I need to convert the public key into the other. No, I don't really have to. I just want to learn how to convert it as I'll be using that method to convert something similar. And this is the simplified question for your testing-convenience.
Finally! I somehow managed to convert it properly but it's somehow weird.
#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"
Finally, key_x_int
and key_y_int
now matches the result from the online link