错误信息
Incorrect password, could not decrypt key
也可能输出为
- ValueError: Incorrect password, could not decrypt key
- Bad decrypt. Incorrect password?
各版本的措辞(均已逐一核实):45.0 及更高版本为“Incorrect password, could not decrypt key”;43~44 版本把密码错误报告为“Could not deserialize key data… the provided password may be incorrect…”;42 及更早版本为“Bad decrypt. Incorrect password?”。
Python cryptography — ValueError from load_pem_private_key / load_der_private_key / pkcs12.load_key_and_certificates
含义
密钥是加密的,cryptography 尝试用你提供的密码解密,但解密失败了。加密的私钥不带任何“密码提示”——唯一的信号是解密出的字节不是有效的密钥——因此这个错误总是意味着你传入的字节不是加密时使用的密码短语。
原因
末尾的换行符成了密码的一部分
常见用 `echo secret > file` 保存、存放在从文件创建的 Kubernetes Secret 中,或写在 `.env` 文件里的密码短语,末尾常常带有 `\n`。原样读取文件会多传入一个字节。
密码短语属于另一把密钥
常见同一个机密存储中有多把密钥和多个密码短语,或者密钥在轮换时被重新加密,而应用程序仍在使用旧的密码短语。
非 ASCII 密码短语的编码方式不同
偶见加密该密钥的工具可能用 Latin-1 或 UTF-16 编码含有非 ASCII 字符的密码短语,而你的代码用的是 UTF-8 编码。字符相同,字节却不同。
旧工具生成的 PKCS#12 文件
偶见一些旧式 `.p12` 导出文件对空密码的处理方式不同(没有密码与空字符串)。有针对性地分别尝试 `None` 和 `b""`,而不是去猜其他值。
修复方法
- 1.
按字节精确读取密码短语
只去掉行尾换行符,切勿去掉其他空白字符;从来源到加载函数,密码短语始终保持为 bytes。
python from pathlib import Path passphrase = Path("/run/secrets/key_passphrase").read_bytes().rstrip(b"\r\n") key = serialization.load_pem_private_key(pem, password=passphrase) - 2.
在代码之外确认密码短语
如果手动输入密码短语时 OpenSSL 能接受,而你的代码失败,差别就在于代码读取密码短语的方式(换行符、编码)。如果 OpenSSL 也失败,那就是密码短语本身错了。
bash # Prompts for the passphrase; "bad decrypt" means the passphrase is wrong, not the file openssl pkey -in encrypted.pem -noout && echo "passphrase OK" printf '%s' "$KEY_PASSPHRASE" | wc -c # length without a trailing newline