From fc4212b43841a23240358124e1f50338881c61f1 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 3 Apr 2026 14:11:40 -0600 Subject: [PATCH] spki: enable workspace-level lint config (#2231) Applies the workspace-level `clippy` and other lints added in #2231 for the `spki` crate, then fixes the lint failures. --- spki/Cargo.toml | 4 +++- spki/README.md | 2 +- spki/src/algorithm.rs | 17 +++++++++++++-- spki/src/digest.rs | 1 + spki/src/error.rs | 2 +- spki/src/lib.rs | 9 +------- spki/src/spki.rs | 14 +++++++++---- spki/src/traits.rs | 49 ++++++++++++++++++++++++++++++++++++------- spki/tests/traits.rs | 1 + 9 files changed, 74 insertions(+), 25 deletions(-) diff --git a/spki/Cargo.toml b/spki/Cargo.toml index 468528afa..48a0e24af 100644 --- a/spki/Cargo.toml +++ b/spki/Cargo.toml @@ -37,6 +37,8 @@ base64 = ["dep:base64ct"] fingerprint = ["digest", "sha2"] pem = ["alloc", "der/pem"] +[lints] +workspace = true + [package.metadata.docs.rs] all-features = true -rustdoc-args = ["--cfg", "docsrs"] diff --git a/spki/README.md b/spki/README.md index a3a06e56a..97977fc49 100644 --- a/spki/README.md +++ b/spki/README.md @@ -8,7 +8,7 @@ [![Project Chat][chat-image]][chat-link] [X.509] Subject Public Key Info types describing public keys as well as their -associated AlgorithmIdentifiers (i.e. OIDs). +associated `AlgorithmIdentifier`s (i.e. OIDs). Specified in [RFC 5280 § 4.1]. diff --git a/spki/src/algorithm.rs b/spki/src/algorithm.rs index 94241fb54..717d9f7ce 100644 --- a/spki/src/algorithm.rs +++ b/spki/src/algorithm.rs @@ -100,6 +100,9 @@ pub type AlgorithmIdentifierOwned = AlgorithmIdentifier; impl AlgorithmIdentifier { /// Assert the `algorithm` OID is an expected value. + /// + /// # Errors + /// Returns [`Error::OidUnknown`] if `self` does not match `expected_oid`. pub fn assert_algorithm_oid(&self, expected_oid: ObjectIdentifier) -> Result { if self.oid == expected_oid { Ok(expected_oid) @@ -111,6 +114,9 @@ impl AlgorithmIdentifier { impl<'a> AlgorithmIdentifierRef<'a> { /// Assert `parameters` is an OID and has the expected value. + /// + /// # Errors + /// Returns [`Error::OidUnknown`] if `self.parameters_oid()` doesn't match `expected_oid`. pub fn assert_parameters_oid( &self, expected_oid: ObjectIdentifier, @@ -125,6 +131,9 @@ impl<'a> AlgorithmIdentifierRef<'a> { } /// Assert the values of the `algorithm` and `parameters` OIDs. + /// + /// # Errors + /// Returns [`Error::OidUnknown`] if `algorithm` and/or `parameters` aren't the expected values. pub fn assert_oids( &self, algorithm: ObjectIdentifier, @@ -137,14 +146,17 @@ impl<'a> AlgorithmIdentifierRef<'a> { /// Get the `parameters` field as an [`AnyRef`]. /// - /// Returns an error if `parameters` are `None`. + /// # Errors + /// Returns [`Error::AlgorithmParametersMissing`] error if `self.parameters` are `None`. pub fn parameters_any(&self) -> Result> { self.parameters.ok_or(Error::AlgorithmParametersMissing) } /// Get the `parameters` field as an [`ObjectIdentifier`]. /// - /// Returns an error if it is absent or not an OID. + /// # Errors + /// - Returns [`Error::AlgorithmParametersMissing`] error if `self.parameters` are `None`. + /// - Returns [`Error::Asn1`] if `self.parameters` is not an OID. pub fn parameters_oid(&self) -> Result { Ok(ObjectIdentifier::try_from(self.parameters_any()?)?) } @@ -155,6 +167,7 @@ impl<'a> AlgorithmIdentifierRef<'a> { /// particular that `NULL` parameters are treated the same as missing /// parameters. /// + /// # Errors /// Returns an error if parameters are present but not an OID. pub fn oids(&self) -> der::Result<(ObjectIdentifier, Option)> { Ok(( diff --git a/spki/src/digest.rs b/spki/src/digest.rs index fd9d3169c..bf005bea1 100644 --- a/spki/src/digest.rs +++ b/spki/src/digest.rs @@ -2,6 +2,7 @@ use der::{Result, Writer}; use digest::Digest; /// Adapter object to write to a digest backend +#[derive(Debug)] pub struct DigestWriter<'d, D>(pub &'d mut D); impl Writer for DigestWriter<'_, D> diff --git a/spki/src/error.rs b/spki/src/error.rs index 0daa35cb4..bdfdc1dc1 100644 --- a/spki/src/error.rs +++ b/spki/src/error.rs @@ -33,7 +33,7 @@ pub enum Error { } impl core::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { match self { Error::Asn1(err) => Some(err), _ => None, diff --git a/spki/src/lib.rs b/spki/src/lib.rs index 956df49df..e9acaee2d 100644 --- a/spki/src/lib.rs +++ b/spki/src/lib.rs @@ -6,14 +6,7 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] #![forbid(unsafe_code)] -#![warn( - clippy::mod_module_files, - clippy::unwrap_used, - missing_docs, - rust_2018_idioms, - unused_lifetimes, - unused_qualifications -)] + //! # Usage //! The following example demonstrates how to use an OID as the `parameters` //! of an [`AlgorithmIdentifier`]. diff --git a/spki/src/spki.rs b/spki/src/spki.rs index f322a2e28..f49a2843a 100644 --- a/spki/src/spki.rs +++ b/spki/src/spki.rs @@ -69,6 +69,9 @@ where /// /// See [RFC7469 § 2.1.1] for more information. /// + /// # Errors + /// Propagates errors that occur during encoding. + /// /// [RFC7469 § 2.1.1]: https://datatracker.ietf.org/doc/html/rfc7469#section-2.1.1 #[cfg(all(feature = "fingerprint", feature = "alloc", feature = "base64"))] pub fn fingerprint_base64(&self) -> Result { @@ -81,6 +84,9 @@ where /// /// See [RFC7469 § 2.1.1] for more information. /// + /// # Errors + /// Propagates errors that occur during encoding. + /// /// [RFC7469 § 2.1.1]: https://datatracker.ietf.org/doc/html/rfc7469#section-2.1.1 #[cfg(feature = "fingerprint")] pub fn fingerprint_bytes(&self) -> Result { @@ -215,10 +221,10 @@ mod allocating { impl SubjectPublicKeyInfoOwned { /// Create a [`SubjectPublicKeyInfoOwned`] from any object that implements /// [`EncodePublicKey`]. - pub fn from_key(source: &T) -> Result - where - T: EncodePublicKey, - { + /// + /// # Errors + /// Propagates encoding and decoding errors. + pub fn from_key(source: &T) -> Result { Ok(source.to_public_key_der()?.decode_msg::()?) } } diff --git a/spki/src/traits.rs b/spki/src/traits.rs index 726974a1f..8d767196c 100644 --- a/spki/src/traits.rs +++ b/spki/src/traits.rs @@ -25,6 +25,9 @@ use crate::SubjectPublicKeyInfo; pub trait DecodePublicKey: Sized { /// Deserialize object from ASN.1 DER-encoded [`SubjectPublicKeyInfo`] /// (binary format). + /// + /// # Errors + /// Returns decoding errors specific to the concrete type which impls this trait. fn from_public_key_der(bytes: &[u8]) -> Result; /// Deserialize PEM-encoded [`SubjectPublicKeyInfo`]. @@ -34,6 +37,9 @@ pub trait DecodePublicKey: Sized { /// ```text /// -----BEGIN PUBLIC KEY----- /// ``` + /// + /// # Errors + /// Returns decoding errors specific to the concrete type which impls this trait. #[cfg(feature = "pem")] fn from_public_key_pem(s: &str) -> Result { let (label, doc) = Document::from_pem(s)?; @@ -43,6 +49,9 @@ pub trait DecodePublicKey: Sized { /// Load public key object from an ASN.1 DER-encoded file on the local /// filesystem (binary format). + /// + /// # Errors + /// Returns decoding errors specific to the concrete type which impls this trait. #[cfg(feature = "std")] fn read_public_key_der_file(path: impl AsRef) -> Result { let doc = Document::read_der_file(path)?; @@ -50,6 +59,9 @@ pub trait DecodePublicKey: Sized { } /// Load public key object from a PEM-encoded file on the local filesystem. + /// + /// # Errors + /// Returns decoding errors specific to the concrete type which impls this trait. #[cfg(all(feature = "pem", feature = "std"))] fn read_public_key_pem_file(path: impl AsRef) -> Result { let (label, doc) = Document::read_pem_file(path)?; @@ -71,22 +83,34 @@ where #[cfg(feature = "alloc")] pub trait EncodePublicKey { /// Serialize a [`Document`] containing a SPKI-encoded public key. + /// + /// # Errors + /// Returns encoding errors specific to the concrete type which impls this trait. fn to_public_key_der(&self) -> Result; /// Serialize this public key as PEM-encoded SPKI with the given [`LineEnding`]. + /// + /// # Errors + /// Returns encoding errors specific to the concrete type which impls this trait. #[cfg(feature = "pem")] fn to_public_key_pem(&self, line_ending: LineEnding) -> Result { let doc = self.to_public_key_der()?; Ok(doc.to_pem(SubjectPublicKeyInfoRef::PEM_LABEL, line_ending)?) } - /// Write ASN.1 DER-encoded public key to the given path + /// Write ASN.1 DER-encoded public key to the given path. + /// + /// # Errors + /// Returns encoding errors specific to the concrete type which impls this trait. #[cfg(feature = "std")] fn write_public_key_der_file(&self, path: impl AsRef) -> Result<()> { Ok(self.to_public_key_der()?.write_der_file(path)?) } - /// Write ASN.1 PEM-encoded public key to the given path + /// Write ASN.1 PEM-encoded public key to the given path. + /// + /// # Errors + /// Returns encoding errors specific to the concrete type which impls this trait. #[cfg(all(feature = "pem", feature = "std"))] fn write_public_key_pem_file( &self, @@ -115,6 +139,9 @@ pub trait AssociatedAlgorithmIdentifier { #[cfg(feature = "alloc")] pub trait DynAssociatedAlgorithmIdentifier { /// `AlgorithmIdentifier` for this structure. + /// + /// # Errors + /// Returns errors specific to the concrete type which impls this trait. fn algorithm_identifier(&self) -> Result; } @@ -135,9 +162,9 @@ where } } -/// Returns `AlgorithmIdentifier` associated with the signature system. +/// Returns [`AlgorithmIdentifier`] associated with the signature system. /// -/// Unlike AssociatedAlgorithmIdentifier this is intended to be implemented for public and/or +/// Unlike [`AssociatedAlgorithmIdentifier`] this is intended to be implemented for public and/or /// private keys. pub trait SignatureAlgorithmIdentifier { /// Algorithm parameters. @@ -147,13 +174,16 @@ pub trait SignatureAlgorithmIdentifier { const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifier; } -/// Returns `AlgorithmIdentifier` associated with the signature system. +/// Returns [`AlgorithmIdentifierOwned`] associated with the signature system. /// -/// Unlike AssociatedAlgorithmIdentifier this is intended to be implemented for public and/or +/// Unlike [`AssociatedAlgorithmIdentifier`] this is intended to be implemented for public and/or /// private keys. #[cfg(feature = "alloc")] pub trait DynSignatureAlgorithmIdentifier { /// `AlgorithmIdentifier` for the corresponding signature system. + /// + /// # Errors + /// Returns errors specific to the concrete type which impls this trait. fn signature_algorithm_identifier(&self) -> Result; } @@ -174,11 +204,14 @@ where } } -/// Returns the `BitString` encoding of the signature. +/// Returns the [`BitString`] encoding of the signature. /// -/// X.509 and CSR structures require signatures to be BitString encoded. +/// X.509 and CSR structures require signatures to be `BitString` encoded. #[cfg(feature = "alloc")] pub trait SignatureBitStringEncoding { /// `BitString` encoding for this signature. + /// + /// # Errors + /// Returns errors specific to the concrete type which impls this trait. fn to_bitstring(&self) -> der::Result; } diff --git a/spki/tests/traits.rs b/spki/tests/traits.rs index 111433343..f2505c246 100644 --- a/spki/tests/traits.rs +++ b/spki/tests/traits.rs @@ -22,6 +22,7 @@ const ED25519_DER_EXAMPLE: &[u8] = include_bytes!("examples/ed25519-pub.der"); const ED25519_PEM_EXAMPLE: &str = include_str!("examples/ed25519-pub.pem"); /// Mock key type for testing trait impls against. +#[derive(Debug)] pub struct MockKey(Vec); impl AsRef<[u8]> for MockKey {