From 241075e56ef31054d21505845e993a6beb6f8cfa Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 25 Apr 2026 09:32:58 -0600 Subject: [PATCH] pkcs8: add `KeyError` enum Adds an enum to be carried along with `pkcs8::Error::KeyMalformed` that can give more specific details about what is wrong with the key, e.g. is it being rejected because it's too short or too long. This has been requested by people who say the existing variant doesn't give enough detail to diagnose the problem. --- Cargo.lock | 3 +-- Cargo.toml | 2 ++ pkcs8/src/error.rs | 39 ++++++++++++++++++++++++++++++++++++--- pkcs8/src/lib.rs | 2 +- 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9cd06c353..520d43fe4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1306,8 +1306,7 @@ dependencies = [ [[package]] name = "rsa" version = "0.10.0-rc.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ed3e93fc7e473e464b9726f4759659e72bc8665e4b8ea227547024f416d905" +source = "git+https://github.com/RustCrypto/RSA?branch=pkcs8%2Fadd-keyerror#3405044e4163049bc1c420f1f93913bda4882240" dependencies = [ "const-oid", "crypto-bigint", diff --git a/Cargo.toml b/Cargo.toml index 76339a17c..132f97910 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,8 @@ x509-tsp = { path = "./x509-tsp" } x509-cert = { path = "./x509-cert" } x509-ocsp = { path = "./x509-ocsp" } +rsa = { git = "https://github.com/RustCrypto/RSA", branch = "pkcs8/add-keyerror" } + [workspace.lints.clippy] borrow_as_ptr = "warn" cast_lossless = "warn" diff --git a/pkcs8/src/error.rs b/pkcs8/src/error.rs index eb7e5366f..c7ddaf557 100644 --- a/pkcs8/src/error.rs +++ b/pkcs8/src/error.rs @@ -24,7 +24,7 @@ pub enum Error { /// This is intended for relaying errors related to the raw data contained /// within [`PrivateKeyInfo::private_key`][`crate::PrivateKeyInfo::private_key`] /// or [`SubjectPublicKeyInfo::subject_public_key`][`crate::SubjectPublicKeyInfo::subject_public_key`]. - KeyMalformed, + KeyMalformed(KeyError), /// [`AlgorithmIdentifier::parameters`][`crate::AlgorithmIdentifierRef::parameters`] /// is malformed or otherwise encoded in an unexpected manner. @@ -40,8 +40,8 @@ impl fmt::Display for Error { Error::Asn1(err) => write!(f, "PKCS#8 ASN.1 error: {err}"), #[cfg(feature = "pkcs5")] Error::EncryptedPrivateKey(err) => write!(f, "{err}"), - Error::KeyMalformed => f.write_str("PKCS#8 cryptographic key data malformed"), - Error::ParametersMalformed => f.write_str("PKCS#8 algorithm parameters malformed"), + Error::KeyMalformed(err) => write!(f, "PKCS#8 key malformed: {err}"), + Error::ParametersMalformed => write!(f, "PKCS#8 algorithm parameters malformed"), Error::PublicKey(err) => write!(f, "public key error: {err}"), } } @@ -53,12 +53,19 @@ impl core::error::Error for Error { Error::Asn1(err) => Some(err), #[cfg(feature = "pkcs5")] Error::EncryptedPrivateKey(err) => Some(err), + Error::KeyMalformed(err) => Some(err), Error::PublicKey(err) => Some(err), _ => None, } } } +impl From for Error { + fn from(err: KeyError) -> Error { + Error::KeyMalformed(err) + } +} + impl From for Error { fn from(err: der::Error) -> Error { Error::Asn1(err) @@ -100,3 +107,29 @@ impl From for spki::Error { } } } + +/// Key-related errors. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[non_exhaustive] +pub enum KeyError { + /// Key is not valid for this algorithm. + Invalid, + + /// Key is too short. + TooShort, + + /// Key is too long. + TooLong, +} + +impl fmt::Display for KeyError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + KeyError::Invalid => f.write_str("key invalid"), + KeyError::TooShort => f.write_str("key too short"), + KeyError::TooLong => f.write_str("key too long"), + } + } +} + +impl core::error::Error for KeyError {} diff --git a/pkcs8/src/lib.rs b/pkcs8/src/lib.rs index 0ebde2cd0..33726dc8b 100644 --- a/pkcs8/src/lib.rs +++ b/pkcs8/src/lib.rs @@ -77,7 +77,7 @@ mod version; pub(crate) mod encrypted_private_key_info; pub use crate::{ - error::{Error, Result}, + error::{Error, KeyError, Result}, private_key_info::{PrivateKeyInfo, PrivateKeyInfoRef}, traits::DecodePrivateKey, version::Version,