Setting up Ruby OpenSSL with a known public key

2.3k Views Asked by At

I have the content of a public key which I'm getting passed as an input to my system:

public_key = 'MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgAC/Bu9nyAtG1DQe7t7jszLb+dZ1GbXoR8G0rIXoak67NM='

I need to feed this into OpenSSL so it can take part in some ECDH decryption.

I can't seem to find a way to make OpenSSL accept the above input.

I've tried the following:

  • OpenSSL::PKey::RSA.new public_key
  • OpenSSL::PKey::RSA.new "-----BEGIN PUBLIC KEY-----\n#{public_key}\n-----END PUBLIC KEY-----\n"

Both of these return:

OpenSSL::PKey::RSAError: Neither PUB key nor PRIV key: nested asn1 error

I can do:

  • OpenSSL::PKey.read "-----BEGIN PUBLIC KEY-----\n#{public_key}\n-----END PUBLIC KEY-----\n"

This doesn't return an error, however I can't then see a way to set the group as secp128r2 without throwing an error.

Doing c = OpenSSL::PKey::EC.new("secp128r2") and trying to set the key after with c.public_key = OpenSSL::PKey.read("-----BEGIN PUBLIC KEY-----\n#{public_key}\n-----END PUBLIC KEY-----\n").public_key throws the error:

OpenSSL::PKey::ECError: EC_KEY_set_public_key: incompatible objects
1

There are 1 best solutions below

0
On BEST ANSWER

There’s a couple of things wrong here. First, this is an elliptic curve key, so trying to create an RSA key isn’t going to work. You need to create an EC key.

The EC key initializer accepts a number of ways to pass in the key. Unfortunately none of them match exactly what you have here. You can pass in the PEM form or the DER form though. The PEM form is just what you have with the BEGIN PUBLIC KEY and END PUBLIC KEY lines added, so this will work (similiar to what you’ve tried, only using the correct key type):

key = OpenSSL::PKey::EC.new "-----BEGIN PUBLIC KEY-----\n#{public_key}\n-----END PUBLIC KEY-----\n"

The DER form is what you have but base 64 decoded, so this will also work and might be more convenient:

key = OpenSSL::PKey::EC.new(Base64.decode64(public_key))

When you’ve done that you can call key.group.curve_name and you will see the second problem. This is a prime256v1 key, not a secp128r2 key. It doesn’t represent a point on the secp128r2 curve and so is causing the incompatible objects error you are getting. Make sure you’re using matching key types.