错误信息
KeyRejected("InvalidEncoding")
也可能输出为
- KeyRejected("WrongAlgorithm")
- called `Result::unwrap()` on an `Err` value: KeyRejected("InvalidEncoding")
原因字符串各不相同:`InvalidEncoding`、`WrongAlgorithm`、`InconsistentComponents`、`TooSmall`……`Display` 只打印原因,例如 `InvalidEncoding`。
ring (Rust crate) — ring::error::KeyRejected from EcdsaKeyPair::from_pkcs8 / Ed25519KeyPair::from_pkcs8
含义
ring 拒绝了这些私钥字节。ring 对每种密钥类型只接受一种编码——ECDSA 和 Ed25519 为 DER 编码的 PKCS#8(v1 或 v2),RSA 还可以通过 `from_der` 使用 PKCS#1 DER——并且只报告一个简短的原因:字节不是该结构时为 `InvalidEncoding`,字节是针对其他算法或曲线的合法 PKCS#8 文档时为 `WrongAlgorithm`。ring 本身从不解析 PEM。
原因
把 PEM 文本当作字节传入
常见`include_bytes!("key.pem")` 或 `fs::read("key.pem")` 得到的是 PEM 文本。ring 需要的是其中经过 base64 解码的 DER。
使用了 SEC 1 或 PKCS#1,而不是 PKCS#8
常见`EC PRIVATE KEY` 和 `RSA PRIVATE KEY` 文件是另外的结构。ring 中的 ECDSA 和 Ed25519 密钥对只能加载 PKCS#8。
其他算法或曲线的密钥
偶见用 P-256 签名算法加载 P-384 密钥,或者把 ECDSA 密钥交给 `Ed25519KeyPair`,都会得到 `WrongAlgorithm`。
修复方法
- 1.
解码 PEM 并检查其标签
使用 PEM 解析器,只接受 `PRIVATE KEY` 标签,并把解码后的内容传给 ring。
rust // Cargo.toml: pem = "3" let pem = pem::parse(std::fs::read_to_string("key.pem")?)?; anyhow::ensure!(pem.tag() == "PRIVATE KEY", "expected PKCS#8, got {}", pem.tag()); let key_pair = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, pem.contents(), &rng) .map_err(|e| anyhow::anyhow!("key rejected: {e}"))?; - 2.
将旧格式的密钥文件转换为 PKCS#8 DER
OpenSSL 可以把 SEC 1 和 PKCS#1 私钥转换为 PKCS#8;`-outform DER` 写出的正是 ring 要求的字节。
bash openssl pkcs8 -topk8 -nocrypt -in ec-sec1.pem -outform DER -out key.pk8 # SEC 1 -> PKCS#8 DER