使用Python Cryptography转换JWK时无法生成匹配公钥的问题
问题分析与修复方案
核心错误点
- 曲线不匹配:JWK中指定的曲线是
secp256k1,但代码里误用了ec.SECP256R1()(NIST P-256曲线),这会导致生成的公钥与原JWK公钥完全不符。 - 测试代码变量错误:测试代码里
base64.urlsafe_b64encode(number_bytes)中的number_bytes未定义,实际应为x_bytes。 - Base64编码处理差异:JWK中的
x/y是不带填充字符=的URL安全Base64编码,而base64.urlsafe_b64encode会保留填充,需手动去除。
修正后的代码
1. JWK转PEM私钥的正确代码
from cryptography.hazmat.primitives import serialization, hashes from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.backends import default_backend import base64 # 原JWK密钥 key = { "kty": "EC", "d": "MXrxKTl_o9yIQlExYy9c1LcWZX_OwX3aw-oGP0flUdo", "use": "sig", "crv": "secp256k1", "kid": "Im53aoD8zJoHzOXmfIAUkncONCIeR1pgy_nhvQrwN3s", "x": "hHXNLbjBY_SFeP-tOPoyoGGYjISm-m3aVJLpc3suka0", "y": "yYIjrvo_lqrsdxq-oMQQxBG8eyIUKmF9XazdwdGTwSY", "alg": "ES256" } # 使用正确的secp256k1曲线 curve = ec.SECP256K1() # 处理私钥d的Base64编码(补全填充) padding_factor = (4 - len(key['d']) % 4) % 4 padded_secret = key['d'] + '=' * padding_factor secret_bytes = base64.urlsafe_b64decode(padded_secret) secret_int = int.from_bytes(secret_bytes, 'big') # 生成私钥 priv_key = ec.derive_private_key(secret_int, curve, default_backend()) # 导出PEM格式私钥 pem_priv = priv_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() )
2. 修正后的测试代码
# 从私钥对象获取公钥(原代码误用字节串调用public_key()) pub_key = priv_key.public_key() pub_numbers = pub_key.public_numbers() # 处理公钥x坐标的编码,去除填充字符= x_bytes = pub_numbers.x.to_bytes(32, byteorder="big") x_encoded = base64.urlsafe_b64encode(x_bytes).decode().rstrip('=') # 验证与原JWK的x是否一致 assert key["x"] == x_encoded, "公钥x坐标不匹配" # 同理验证y坐标 y_bytes = pub_numbers.y.to_bytes(32, byteorder="big") y_encoded = base64.urlsafe_b64encode(y_bytes).decode().rstrip('=') assert key["y"] == y_encoded, "公钥y坐标不匹配"
额外说明
secp256k1是加密货币领域常用曲线,SECP256R1是通用NIST标准曲线,两者不可混用。- JWK的Base64URL编码要求去除填充
=,因此编码后必须用rstrip('=')处理。 - 原测试代码中
pem_priv.public_key()错误,因为pem_priv是字节串,需从priv_key对象直接获取公钥,或先将字节串反序列化为私钥对象再操作。
内容的提问来源于stack exchange,提问作者T. Rossi
相关产品推荐
相关产品推荐

