错误信息
Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).
也可能输出为
- ValueError: Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters). Details: ASN.1 parsing error: short data (needed at least 48 additional bytes)
- Could not deserialize key data. The data may be in an incorrect format, the provided password may be incorrect, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).
- ValueError: ('Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).', [<OpenSSLError(code=503841036, lib=60, reason=524556, reason_text=unsupported)>
已在各版本上逐一核实:cryptography 45.0 及更高版本会附加“Details: …”(例如“ASN.1 parsing error: short data”)。43~44 版本把这段文本连同 OpenSSL 错误对象以元组形式抛出,并在句中加上“the provided password may be incorrect”(密码错误时也报这条消息);36~42 版本抛出元组形式,但没有这句话。
Python cryptography — ValueError from load_pem_private_key / load_der_private_key / load_der_public_key
含义
cryptography 找到了密钥数据,但无法把它转换成密钥对象。对于 PEM 输入,首尾的封装行没有问题(否则你会看到“Unable to load PEM file”),所以问题出在其中的 DER 上:它被截断了,它的结构与加载函数预期的不同,或者它描述的是 cryptography 拒绝加载的密钥——带有显式曲线参数的 EC 密钥,或用它不支持的算法加密的密钥。较新的版本会附加“Details: …”,给出底层的 ASN.1 原因。
原因
base64 正文不完整或被改动
常见从终端或机密管理器复制密钥时丢了一行,密钥被有长度限制的字段截断,或者字符被编辑器改动了。头部行和尾部行都还在,因此 PEM 解析成功,而 DER 解析失败。
加载函数与密钥结构不匹配
常见把公钥传给了 `load_der_private_key`,把证书传给了密钥加载函数,或者把 OpenSSH 格式的密钥(`-----BEGIN OPENSSH PRIVATE KEY-----`)传给了 `load_pem_private_key`,而不是 `load_ssh_private_key`。
带有显式曲线参数的 EC 密钥
偶见一些旧工具生成的密钥或从 HSM 导出的密钥会逐一写出曲线的素数、系数和生成元,而不是通过 OID 指明曲线。cryptography 有意拒绝这类密钥(RFC 5480 要求 PKIX 使用命名曲线)。
用 cryptography 不支持的算法加密
偶见用旧式 PBE 方案(例如 PBE-SHA1-RC2 或各种 DES 变体)加密的 PKCS#8 文件,当前的构建版本无法解密。用 AES 重新加密这些文件(`openssl pkcs8 -topk8 -v2 aes-256-cbc`)。
修复方法
- 1.
先用 OpenSSL 检查密钥
如果 `openssl asn1parse` 就已经失败,说明文件已损坏——重新获取一份副本。如果 OpenSSL 能加载而 cryptography 不能,就检查曲线编码或加密算法。
bash openssl asn1parse -in key.pem | head -20 # does the DER parse at all? openssl pkey -in key.pem -noout -text | head # private key: type, curve, size openssl pkey -pubin -in pub.pem -noout -text # public key - 2.
使用与密钥匹配的加载函数
根据数据本身在 PEM、DER 和 OpenSSH 加载函数之间选择,并对公钥使用公钥加载函数。
python from cryptography.hazmat.primitives import serialization def load_any_private_key(data: bytes, password: bytes | None = None): if data.lstrip().startswith(b"-----BEGIN OPENSSH PRIVATE KEY-----"): return serialization.load_ssh_private_key(data, password) if data.lstrip().startswith(b"-----BEGIN"): return serialization.load_pem_private_key(data, password) return serialization.load_der_private_key(data, password) - 3.
把显式参数转换为命名曲线
OpenSSL 3 默认以命名曲线写出 EC 密钥,因此只要把密钥重新导出一次,带显式参数的密钥在所有库中的问题就都解决了。
bash # Re-encode an EC key with a named curve instead of explicit parameters openssl pkey -in explicit.pem -out named.pem openssl ec -in named.pem -param_out -noout -text | grep "ASN1 OID" # e.g. prime256v1
相关错误
Unable to load PEM file. See https://cryptography.io/en/latest/faq/#why-can-t-i…Python cryptographyValid PEM but no BEGIN PUBLIC KEY/END PUBLIC KEY delimiters. Are you sure this…Python cryptographyPassword was given but private key is not encrypted.Python cryptographyerror:0680009B:asn1 encoding routines:ASN1_get_object:too longOpenSSL 3.x CLI (asn1parse, d2i loaders)