Toby
Toby

Reputation: 8792

Creating a new OpenSSL EC Point using prime256v1 and a known public key

I'm trying to turn a known public key into an instance of OpenSSL::PKey::EC::Point with the following code:

require 'base64'
require 'openssl'

public = 'MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgAD5tgZhw82GpGYJYkWNgeDp/0OzT4y/YLS+tMpZeJ2VEQ='

decoded_public = Base64.encode64(public)
hex_string = decoded_public.each_byte.map { |b| b.to_s(16) }.join()

ec_group = OpenSSL::PKey::EC::Group.new('prime256v1')
key = OpenSSL::PKey::EC.new(ec_group)
bn = OpenSSL::BN.new(hex_string, 16)
point = OpenSSL::PKey::EC::Point.new(ec_group, bn)

The error occurs on the last line, throwing:

`initialize': invalid encoding (OpenSSL::PKey::EC::Point::Error)

I run Base64.encode64 and then turn each byte into a hex representation because from reading around it seems like hex strings are a common way of creating a new BigNum.

I'm guessing it is something I'm doing wrong with the public key information, because the ec_group gets created without complaint.

Upvotes: 2

Views: 1159

Answers (1)

matt
matt

Reputation: 79743

First of all, that string is already base64 encoded, so you need to decode it, not encode it:

decoded_public = Base64.decode64(public)

The result you get is a DER encoded structure containing the key, so trying to look at the bytes directly isn’t going to get you anywhere (you can see what it contains using OpenSSL::ASN1.decode(decoded_public)).

You can however use OpenSSL::PKey::read directly on decoded_public, which will give you an OpenSSL::PKey::EC object (with the correct group). To get the associated point you can just call public_key:

key = OpenSSL::PKey.read decoded_public
point = key.public_key

The result is an OpenSSL::PKey::EC::Point object.

Upvotes: 1

Related Questions