跳到主要内容
ecdsa.com
Python cryptographyPython cryptography 库

错误信息

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 原因。

原因

修复方法

  1. 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. 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. 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

相关错误

浏览完整的签名错误库