使用危险品库加载原始 Public EC 密钥

Load Raw Public EC Key using hazmat library

我使用 JS 生成了以下私钥和 public 密钥:

priv: auLHORUBmv5n48jUDA1TskAmJWFi4TFEmjE1GjgjEB8
pub : BFvn-Qk8HWPwgI5ZgCiWxJV5SYdTXbkVz66sgoEslLxotftRGLEOeIPXVcnQD95eETqW9zM7ejB1MqCc0tvR-0g

要生成的代码 (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)}`)

现在,我有 Python 个项目需要使用 cryptography.hazmat.primitives.serialization.load_der_public_key()

加载 public 密钥
load_der_public_key(base64.b64decode(publicRaw))

我似乎不知道该怎么做。不断出现错误:

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

尝试将该字符串转换为字节,并将 base64 转换为字节,但没有成功。

您混淆了两种格式,一种是 raw public 密钥,另一种是 中 DER 编码的 public 密钥X.509/SPKI 格式。

发布的public键:

BFvn-Qk8HWPwgI5ZgCiWxJV5SYdTXbkVz66sgoEslLxotftRGLEOeIPXVcnQD95eETqW9zM7ejB1MqCc0tvR-0g

是 Base64url 编码的原始 public 密钥。十六进制编码,格式为 0x04 + x + y,secp256r1(又名 prime256v1)的大小为 65 字节:

045be7f9093c1d63f0808e59802896c495794987535db915cfaeac82812c94bc68b5fb5118b10e7883d755c9d00fde5e113a96f7333b7a307532a09cd2dbd1fb48

在 Python 中,可以使用 Cryptography 库的 from_encoded_point() 导入原始 public 密钥,例如:

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);

然而,对于使用 load_der_public_key() 的导入,密钥必须以 X.509/SPKI 格式导出,并在 NodeJS 代码中进行 DER 编码。这可以实现,例如与

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

当然,也可以在两种格式之间进行转换。但是由于 Cryptography 库支持两种格式的导入,所以实际上没有必要。