Load Raw Public EC Key using hazmat library

Viewed 397

I have the following private and public keys generated w/ JS:

priv: auLHORUBmv5n48jUDA1TskAmJWFi4TFEmjE1GjgjEB8
pub : BFvn-Qk8HWPwgI5ZgCiWxJV5SYdTXbkVz66sgoEslLxotftRGLEOeIPXVcnQD95eETqW9zM7ejB1MqCc0tvR-0g

Code to generate (JavaScript):

const pair = generateKeyPairSync('ec', { namedCurve: 'prime256v1' })
const privateKeyDer = pair.privateKey.export({ format: 'der', type: 'pkcs8' })
const privateRaw = privateKeyDer.slice(36, 68)
const publicRaw = privateKeyDer.slice(73)
console.log(`priv: ${webSafe64(privateRaw)}`)
console.log(`pub : ${webSafe64(publicRaw)}`)

Now, I have Python project that need to load public key using cryptography.hazmat.primitives.serialization.load_der_public_key()

load_der_public_key(base64.b64decode(publicRaw))

I can't seem to figure out how to do that. Keep getting error:

Could not deserialize key data. The data may be in an incorrect format or it may be encrypted with an unsupported algorithm.

Tried to convert that string to bytes, and convert base64 to bytes without any luck.

1 Answers

You are confusing two formats, one is the raw public key, the other is the DER encoded public key in X.509/SPKI format.

The posted public key:

BFvn-Qk8HWPwgI5ZgCiWxJV5SYdTXbkVz66sgoEslLxotftRGLEOeIPXVcnQD95eETqW9zM7ejB1MqCc0tvR-0g

is the Base64url encoded raw public key. Hex encoded it has the format 0x04 + x + y and is 65 bytes in size for secp256r1 (aka prime256v1):

045be7f9093c1d63f0808e59802896c495794987535db915cfaeac82812c94bc68b5fb5118b10e7883d755c9d00fde5e113a96f7333b7a307532a09cd2dbd1fb48

In Python, the raw public key can be imported with from_encoded_point() of the Cryptography library, e.g.:

from cryptography.hazmat.primitives.asymmetric import ec
import base64

curve = ec.SECP256R1()
publicKeyRaw = base64.urlsafe_b64decode('BFvn-Qk8HWPwgI5ZgCiWxJV5SYdTXbkVz66sgoEslLxotftRGLEOeIPXVcnQD95eETqW9zM7ejB1MqCc0tvR-0g=');
publicKey = ec.EllipticCurvePublicKey.from_encoded_point(curve, publicKeyRaw);

For an import with load_der_public_key(), however, the key would have to be exported in X.509/SPKI format and DER encoded in the NodeJS code. This can be achieved e.g. with

var publicKeyDer = pair.publicKey.export({ format: 'der', type: 'spki' })

Of course, it is also possible to convert between both formats. But since the Cryptography library supports the import of both formats, this is actually not necessary.

Related