From b2a345853d72cdccf58ff1f18eee622d835b7438 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 18 Oct 2026 16:17:51 -0700 Subject: [PATCH] Lint configs Adds our standard Cargo.toml-based lint configs, with ample TODOs where we need to add more documentation --- Cargo.toml | 38 +++++++++++++++++++++++++++++++ benches/key.rs | 2 ++ src/algorithms/generate.rs | 2 ++ src/algorithms/oaep.rs | 2 ++ src/algorithms/pkcs1v15.rs | 9 +++++++- src/algorithms/pss.rs | 2 ++ src/algorithms/rsa.rs | 15 ++++++++++--- src/encoding.rs | 2 +- src/hazmat.rs | 4 +++- src/key.rs | 41 ++++++++++++++++++++++++++++------ src/lib.rs | 2 -- src/oaep.rs | 2 ++ src/oaep/decrypting_key.rs | 1 + src/oaep/encrypting_key.rs | 1 + src/pkcs1v15.rs | 17 ++++++-------- src/pkcs1v15/decrypting_key.rs | 1 + src/pkcs1v15/encrypting_key.rs | 1 + src/pkcs1v15/signature.rs | 8 +++---- src/pkcs1v15/signing_key.rs | 8 +++++-- src/pkcs1v15/verifying_key.rs | 8 ++++--- src/pss.rs | 6 +++++ src/pss/blinded_signing_key.rs | 5 +++++ src/pss/signature.rs | 8 +++---- src/pss/signing_key.rs | 9 ++++++-- src/pss/verifying_key.rs | 10 ++++++--- src/traits/encryption.rs | 3 +++ src/traits/padding.rs | 7 ++++-- tests/pkcs1v15.rs | 3 ++- tests/wycheproof.rs | 2 +- 29 files changed, 172 insertions(+), 47 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2fa9fbb4..6d1d0ad0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,6 +60,44 @@ getrandom = ["crypto-bigint/getrandom", "crypto-common"] serde = ["encoding", "dep:serde", "dep:serdect", "crypto-bigint/serde"] pkcs5 = ["pkcs8/encryption"] +[lints.clippy] +borrow_as_ptr = "warn" +cast_lossless = "warn" +cast_possible_truncation = "warn" +cast_possible_wrap = "warn" +cast_precision_loss = "warn" +cast_sign_loss = "warn" +checked_conversions = "warn" +implicit_saturating_sub = "warn" +manual_assert = "warn" +map_unwrap_or = "warn" +missing_errors_doc = "warn" +missing_panics_doc = "warn" +mod_module_files = "warn" +must_use_candidate = "warn" +needless_range_loop = "allow" +ptr_as_ptr = "warn" +redundant_closure_for_method_calls = "warn" +ref_as_ptr = "warn" +return_self_not_must_use = "warn" +semicolon_if_nothing_returned = "warn" +trivially_copy_pass_by_ref = "warn" +std_instead_of_alloc = "warn" +std_instead_of_core = "warn" +undocumented_unsafe_blocks = "warn" +unnecessary_safety_comment = "warn" +unwrap_in_result = "warn" +unwrap_used = "warn" + +[lints.rust] +missing_copy_implementations = "warn" +missing_debug_implementations = "warn" +missing_docs = "warn" +trivial_casts = "warn" +trivial_numeric_casts = "warn" +unused_lifetimes = "warn" +unused_qualifications = "warn" + [package.metadata.docs.rs] features = ["std", "serde", "hazmat", "sha2"] diff --git a/benches/key.rs b/benches/key.rs index eb7f123b..5e59f560 100644 --- a/benches/key.rs +++ b/benches/key.rs @@ -1,3 +1,5 @@ +//! Key generation benchmark. + #![feature(test)] extern crate test; diff --git a/src/algorithms/generate.rs b/src/algorithms/generate.rs index 0f24e223..ec713d33 100644 --- a/src/algorithms/generate.rs +++ b/src/algorithms/generate.rs @@ -41,6 +41,7 @@ pub(crate) fn generate_multi_prime_key_with_exp( return Err(Error::NprimesTooSmall); } + #[allow(clippy::cast_precision_loss, reason = "TODO")] if bit_size < 64 { let prime_limit = (1u64 << (bit_size / nprimes) as u64) as f64; @@ -81,6 +82,7 @@ pub(crate) fn generate_multi_prime_key_with_exp( todo += (nprimes - 2) / 5; } + #[allow(clippy::cast_possible_truncation, reason = "TODO")] for (i, prime) in primes.iter_mut().enumerate() { let bits = (todo / (nprimes - i)) as u32; *prime = generate_prime_with_rng(rng, bits); diff --git a/src/algorithms/oaep.rs b/src/algorithms/oaep.rs index 0b9693c5..60d65d84 100644 --- a/src/algorithms/oaep.rs +++ b/src/algorithms/oaep.rs @@ -246,6 +246,7 @@ fn decrypt_inner( let mut index = 0u32; let mut nonzero_before_one = Choice::FALSE; + #[allow(clippy::cast_possible_truncation, reason = "TODO")] for (i, el) in db.iter().skip(h_size).enumerate() { let equals0 = el.ct_eq(&0u8); let equals1 = el.ct_eq(&1u8); @@ -256,5 +257,6 @@ fn decrypt_inner( let valid = first_byte_is_zero & hash_are_equal & !nonzero_before_one & !looking_for_index; + #[allow(clippy::cast_possible_truncation, reason = "TODO")] Ok(CtOption::new(index + 2 + (h_size * 2) as u32, valid)) } diff --git a/src/algorithms/pkcs1v15.rs b/src/algorithms/pkcs1v15.rs index a08357f2..2d5befdb 100644 --- a/src/algorithms/pkcs1v15.rs +++ b/src/algorithms/pkcs1v15.rs @@ -82,6 +82,12 @@ pub(crate) fn pkcs1v15_encrypt_unpad(em: &[u8], k: usize) -> Result> { /// in order to maintain constant memory access patterns. If the plaintext was /// valid then index contains the index of the original message in em. #[inline] +#[allow( + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_sign_loss, + reason = "TODO" +)] fn decrypt_inner(em: &[u8], k: usize) -> Result<(u8, u32)> { if k < 11 || em.len() != k { return Err(Error::Decryption); @@ -147,7 +153,7 @@ pub(crate) fn pkcs1v15_sign_unpad(prefix: &[u8], hashed: &[u8], em: &[u8], k: us ok &= em[k - t_len - 1].ct_eq(&0u8); for el in em.iter().skip(2).take(k - t_len - 3) { - ok &= el.ct_eq(&0xff) + ok &= el.ct_eq(&0xff); } // TODO(tarcieri): avoid branching here by e.g. using a pseudorandom rejection symbol @@ -160,6 +166,7 @@ pub(crate) fn pkcs1v15_sign_unpad(prefix: &[u8], hashed: &[u8], em: &[u8], k: us /// prefix = 0x30 0x30 0x06 oid 0x05 0x00 0x04 #[inline] +#[allow(clippy::cast_possible_truncation, reason = "TODO")] pub(crate) fn pkcs1v15_generate_prefix() -> Vec where D: Digest + AssociatedOid, diff --git a/src/algorithms/pss.rs b/src/algorithms/pss.rs index a524e527..5058542b 100644 --- a/src/algorithms/pss.rs +++ b/src/algorithms/pss.rs @@ -207,6 +207,7 @@ fn emsa_pss_verify_pre<'a>( // 6. If the leftmost 8 * em_len - em_bits bits of the leftmost octet in // maskedDB are not all equal to zero, output "inconsistent" and // stop. + #[allow(clippy::cast_possible_truncation, reason = "TODO")] if db[0] & (0xFF_u8 .checked_shl(8 - (8 * em_len - em_bits) as u32) @@ -232,6 +233,7 @@ fn emsa_pss_verify_salt(db: &[u8], em_len: usize, s_len: usize, h_len: usize) -> /// Detect salt length by scanning DB for the 0x01 separator byte. /// Returns (s_len, valid) where s_len is 0 on failure. +#[allow(clippy::cast_possible_truncation, reason = "TODO")] fn emsa_pss_get_salt_len(db: &[u8], em_len: usize, h_len: usize) -> (usize, Choice) { let em_len = em_len as u32; let h_len = h_len as u32; diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 125fcbe9..10911363 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -22,11 +22,14 @@ use crate::traits::keys::{PrivateKeyParts, PublicKeyParts}; /// The caller must check that the representative is less than `n` to implement either primitive; /// this function reduces out-of-range inputs modulo `n`. /// -/// # ☢️️ WARNING: HAZARDOUS API ☢️ +///
+/// ☢️️ WARNING: HAZARDOUS API ☢️ /// /// Use this function with great care! Raw RSA should never be used without an appropriate padding /// or signature scheme. See the [module-level documentation][crate::hazmat] for more information. +///
#[inline] +#[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn rsa_encrypt(key: &K, m: &BoxedUint) -> Result { let e = key.e(); let res = pow_mod_params_vartime_exp_bits(m, e, e.bits(), key.n_params()); @@ -40,11 +43,14 @@ pub fn rsa_encrypt(key: &K, m: &BoxedUint) -> Result +/// ☢️️ WARNING: HAZARDOUS API ☢️ /// /// Use this function with great care! Raw RSA should never be used without an appropriate padding /// or signature scheme. See the [module-level documentation][crate::hazmat] for more information. +/// #[inline] +#[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn rsa_decrypt( rng: Option<&mut R>, priv_key: &impl PrivateKeyParts, @@ -160,11 +166,14 @@ pub fn rsa_decrypt( /// /// `c` must have the same `bits_precision` as the RSA key modulus. /// -/// # ☢️️ WARNING: HAZARDOUS API ☢️ +///
+/// ☢️️ WARNING: HAZARDOUS API ☢️ /// /// Use this function with great care! Raw RSA should never be used without an appropriate padding /// or signature scheme. See the [module-level documentation][crate::hazmat] for more information. +///
#[inline] +#[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn rsa_decrypt_and_check( priv_key: &impl PrivateKeyParts, rng: Option<&mut R>, diff --git a/src/encoding.rs b/src/encoding.rs index 8a32acec..c4c6cac4 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -55,7 +55,7 @@ impl TryFrom> for RsaPrivateKey { let n = uint_from_slice(pkcs1_key.modulus.as_uint_ref().as_bytes(), bits)?; let bits_e = u32::try_from(pkcs1_key.public_exponent.as_uint_ref().as_bytes().len()) - .map_err(|_| pkcs1::Error::KeyMalformed)? + .map_err(|_| KeyMalformed)? * 8; let e = uint_from_slice(pkcs1_key.public_exponent.as_uint_ref().as_bytes(), bits_e)?; let e = Option::from(e).ok_or(KeyMalformed)?; diff --git a/src/hazmat.rs b/src/hazmat.rs index 0a5f13c2..08a70e6c 100644 --- a/src/hazmat.rs +++ b/src/hazmat.rs @@ -1,6 +1,7 @@ //! ⚠️ Low-level "hazmat" RSA functions. //! -//! # ☢️️ WARNING: HAZARDOUS API ☢️ +//!
+//! ☢️️ WARNING: HAZARDOUS API ☢️ //! //! This module holds functions that apply RSA's core encryption and decryption //! primitives to raw data without adding or removing appropriate padding. A @@ -10,5 +11,6 @@ //! //! We do NOT recommend using it to implement any algorithm which has not //! received extensive peer review by cryptographers. +//!
pub use crate::algorithms::rsa::{rsa_decrypt, rsa_decrypt_and_check, rsa_encrypt}; diff --git a/src/key.rs b/src/key.rs index d96b16a7..28d7701a 100644 --- a/src/key.rs +++ b/src/key.rs @@ -192,6 +192,7 @@ impl PublicKeyParts for RsaPublicKey { impl RsaPublicKey { /// Encrypt the given message. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn encrypt( &self, rng: &mut R, @@ -207,6 +208,7 @@ impl RsaPublicKey { /// passed in through `hash`. /// /// If the message is valid `Ok(())` is returned, otherwise an `Err` indicating failure. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn verify(&self, scheme: S, hashed: &[u8], sig: &[u8]) -> Result<()> { scheme.verify(self, hashed, sig) } @@ -230,7 +232,7 @@ impl RsaPublicKey { /// If for some reason you have a legitimate reason to use keys with public exponents larger /// than this value, use the special APIs: /// - /// - [`RsaPublicKey::new_with_large_exp`] + /// - [`RsaPublicKey::new_with_max_size`] /// - [`RsaPrivateKey::from_components_with_large_exponent`] pub const MAX_PUB_EXPONENT: u64 = (1 << 33) - 1; @@ -241,11 +243,13 @@ impl RsaPublicKey { /// /// This function accepts public keys with a modulus size up to 8192-bits, /// i.e. [`RsaPublicKey::MAX_SIZE`]. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn new(n: BoxedUint, e: BoxedUint) -> Result { Self::new_with_max_size(n, e, Self::MAX_SIZE) } /// Create a new public key from its components. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn new_with_max_size(n: BoxedUint, e: BoxedUint, max_size: usize) -> Result { check_public_with_max_size(&n, &e, Some(max_size))?; @@ -264,6 +268,7 @@ impl RsaPublicKey { /// This method is not recommended, and only intended for unusual use cases. /// Most applications should use [`RsaPublicKey::new`] or /// [`RsaPublicKey::new_with_max_size`] instead. + #[must_use] pub fn new_unchecked(n: BoxedUint, e: BoxedUint) -> Self { let n_odd = Odd::new(n.clone()).expect("n must be odd"); let n_params = BoxedMontyParams::new(n_odd); @@ -304,10 +309,13 @@ impl RsaPrivateKey { /// Generate a new RSA key pair of the given bit size. /// - /// #⚠️Warning: Hazmat! + ///
+ /// ⚠️Warning: Hazmat! /// This version does not apply minimum key size checks, and as such may generate keys /// which are insecure! + ///
#[cfg(feature = "hazmat")] + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn new_unchecked(rng: &mut R, bit_size: usize) -> Result { Self::new_with_exp_unchecked(rng, bit_size, Self::EXP.into()) } @@ -316,6 +324,7 @@ impl RsaPrivateKey { /// using the passed in `rng`. /// /// Unless you have specific needs, you should use [`RsaPrivateKey::new`] instead. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn new_with_exp( rng: &mut R, bit_size: usize, @@ -339,10 +348,13 @@ impl RsaPrivateKey { /// /// Unless you have specific needs, you should use [`RsaPrivateKey::new`] instead. /// - /// #⚠️Warning: Hazmat! + ///
+ /// ⚠️Warning: Hazmat! /// This version does not apply minimum key size checks, and as such may generate keys /// which are insecure! + ///
#[cfg(feature = "hazmat")] + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn new_with_exp_unchecked( rng: &mut R, bit_size: usize, @@ -435,19 +447,22 @@ impl RsaPrivateKey { /// /// See [`RsaPrivateKey::from_components`] for an explanation on the parameters. /// - /// # ⚠️ Warning: Hazmat! + ///
+ /// ⚠️ Warning: Hazmat! /// /// This method accepts public exponents outside the standard bounds (2 ≤ e ≤ 2^33-1), /// but still performs full cryptographic validation to ensure the key is mathematically /// correct (i.e., verifies that de ≡ 1 mod λ(n)). /// /// **Note:** This method is dangerous as it can be used as a DOS vector if used with - /// untrusted input https://www.imperialviolet.org/2012/03/17/rsados.html + /// untrusted input: /// /// This is intended for interoperating with systems that use non-standard exponents /// or loading legacy keys. Use [`RsaPrivateKey::from_components`] for standard key /// construction. + ///
#[cfg(feature = "hazmat")] + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn from_components_with_large_exponent( n: BoxedUint, e: BoxedUint, @@ -478,6 +493,7 @@ impl RsaPrivateKey { /// is between 2^16 and 2^256. /// /// [NIST SP 800-56B Revision 2]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn from_components( n: BoxedUint, e: BoxedUint, @@ -501,6 +517,7 @@ impl RsaPrivateKey { /// /// Private exponent will be rebuilt using the method defined in /// [NIST 800-56B Section 6.2.1](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf#page=47). + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn from_p_q( p: BoxedUint, q: BoxedUint, @@ -520,6 +537,7 @@ impl RsaPrivateKey { /// Constructs an RSA key pair from its primes. /// /// This will rebuild the private exponent and the modulus. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn from_primes( primes: Vec, public_exponent: BoxedUint, @@ -546,6 +564,7 @@ impl RsaPrivateKey { /// Get the public key from the private key. /// /// Specific alternative to [`AsRef::as_ref`]. + #[must_use] pub fn as_public_key(&self) -> &RsaPublicKey { &self.pubkey_components } @@ -554,11 +573,13 @@ impl RsaPrivateKey { /// /// Generally this is not needed since `RsaPrivateKey` implements the `PublicKey` trait, /// but it can occasionally be useful to discard the private information entirely. + #[must_use] pub fn to_public_key(&self) -> RsaPublicKey { self.pubkey_components.clone() } /// Performs some calculations to speed up private key operations. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn precompute(&mut self) -> Result<()> { if self.precomputed.is_some() { return Ok(()); @@ -624,6 +645,7 @@ impl RsaPrivateKey { } /// Compute CRT coefficient: `(1/q) mod p`. + #[must_use] pub fn crt_coefficient(&self) -> Option { let p = &self.primes[0]; let q = &self.primes[1]; @@ -633,6 +655,7 @@ impl RsaPrivateKey { /// Performs basic sanity checks on the key. /// Returns `Ok(())` if everything is good, otherwise an appropriate error. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn validate(&self) -> Result<()> { check_public(self)?; validate_private_key_parts(self)?; @@ -640,6 +663,7 @@ impl RsaPrivateKey { } /// Decrypt the given message. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn decrypt(&self, padding: P, ciphertext: &[u8]) -> Result> { padding.decrypt(Option::<&mut DummyRng>::None, self, ciphertext) } @@ -647,6 +671,7 @@ impl RsaPrivateKey { /// Decrypt the given message. /// /// Uses `rng` to blind the decryption process. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn decrypt_blinded( &self, rng: &mut R, @@ -657,6 +682,7 @@ impl RsaPrivateKey { } /// Sign the given digest. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn sign(&self, padding: S, digest_in: &[u8]) -> Result> { padding.sign(Option::<&mut DummyRng>::None, self, digest_in) } @@ -671,6 +697,7 @@ impl RsaPrivateKey { /// [`Pss::new`][`crate::Pss::new`] for a standard RSASSA-PSS signature, or /// [`Pss::new_blinded`][`crate::Pss::new_blinded`] for RSA-BSSA blind /// signatures. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn sign_with_rng( &self, rng: &mut R, @@ -817,7 +844,7 @@ fn validate_skip_exponent_size(key: &RsaPrivateKey) -> Result<()> { impl Serialize for RsaPublicKey { fn serialize(&self, serializer: S) -> core::prelude::v1::Result where - S: serdect::serde::Serializer, + S: serde::Serializer, { let der = self.to_public_key_der().map_err(ser::Error::custom)?; serdect::slice::serialize_hex_lower_or_bin(&der, serializer) @@ -828,7 +855,7 @@ impl Serialize for RsaPublicKey { impl<'de> Deserialize<'de> for RsaPublicKey { fn deserialize(deserializer: D) -> core::prelude::v1::Result where - D: serdect::serde::Deserializer<'de>, + D: serde::Deserializer<'de>, { let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; Self::from_public_key_der(&der_bytes).map_err(de::Error::custom) diff --git a/src/lib.rs b/src/lib.rs index a9ad34ab..b28757c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,8 +2,6 @@ #![cfg_attr(docsrs, feature(doc_cfg))] #![doc = include_str!("../README.md")] #![doc(html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")] -#![warn(missing_docs)] -#![cfg_attr(not(test), deny(clippy::unwrap_used))] //! # Supported algorithms //! diff --git a/src/oaep.rs b/src/oaep.rs index 73f51e18..3772db76 100644 --- a/src/oaep.rs +++ b/src/oaep.rs @@ -78,6 +78,7 @@ where /// let padding = Oaep::::new(); /// let encrypted_data = key.encrypt(&mut rng, padding, b"secret").unwrap(); /// ``` + #[must_use] pub fn new() -> Self { Self { digest: D::new(), @@ -122,6 +123,7 @@ where /// let padding = Oaep::::new_with_mgf_hash(); /// let encrypted_data = key.encrypt(&mut rng, padding, b"secret").unwrap(); /// ``` + #[must_use] pub fn new_with_mgf_hash() -> Self { Self { digest: D::new(), diff --git a/src/oaep/decrypting_key.rs b/src/oaep/decrypting_key.rs index 95064a1f..660d15ad 100644 --- a/src/oaep/decrypting_key.rs +++ b/src/oaep/decrypting_key.rs @@ -34,6 +34,7 @@ where MGD: Digest + FixedOutputReset, { /// Create a new verifying key from an RSA public key. + #[must_use] pub fn new(key: RsaPrivateKey) -> Self { Self { inner: key, diff --git a/src/oaep/encrypting_key.rs b/src/oaep/encrypting_key.rs index a577901f..2d10b8e3 100644 --- a/src/oaep/encrypting_key.rs +++ b/src/oaep/encrypting_key.rs @@ -29,6 +29,7 @@ where MGD: Digest + FixedOutputReset, { /// Create a new verifying key from an RSA public key. + #[must_use] pub fn new(key: RsaPublicKey) -> Self { Self { inner: key, diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index 85f95621..21d0f98c 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -91,6 +91,7 @@ impl Pkcs1v15Sign { /// /// The digest must have an [`AssociatedOid`]. Make sure to enable the `oid` /// feature of the relevant digest crate. + #[must_use] pub fn new() -> Self where D: Digest + AssociatedOid, @@ -104,6 +105,7 @@ impl Pkcs1v15Sign { /// Create new PKCS#1 v1.5 padding for computing an unprefixed signature. /// /// This sets `hash_len` to `None` and uses an empty `prefix`. + #[must_use] pub fn new_unprefixed() -> Self { Self { hash_len: None, @@ -242,32 +244,27 @@ mod oid { #[cfg(feature = "sha1")] impl RsaSignatureAssociatedOid for sha1::Sha1 { - const OID: ObjectIdentifier = - const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.5"); + const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.5"); } #[cfg(feature = "sha2")] impl RsaSignatureAssociatedOid for sha2::Sha224 { - const OID: ObjectIdentifier = - const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.14"); + const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.14"); } #[cfg(feature = "sha2")] impl RsaSignatureAssociatedOid for sha2::Sha256 { - const OID: ObjectIdentifier = - const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.11"); + const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.11"); } #[cfg(feature = "sha2")] impl RsaSignatureAssociatedOid for sha2::Sha384 { - const OID: ObjectIdentifier = - const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.12"); + const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.12"); } #[cfg(feature = "sha2")] impl RsaSignatureAssociatedOid for sha2::Sha512 { - const OID: ObjectIdentifier = - const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.13"); + const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.13"); } } diff --git a/src/pkcs1v15/decrypting_key.rs b/src/pkcs1v15/decrypting_key.rs index d3ae9ee3..a9a4a2d9 100644 --- a/src/pkcs1v15/decrypting_key.rs +++ b/src/pkcs1v15/decrypting_key.rs @@ -21,6 +21,7 @@ pub struct DecryptingKey { impl DecryptingKey { /// Create a new verifying key from an RSA public key. + #[must_use] pub fn new(key: RsaPrivateKey) -> Self { Self { inner: key } } diff --git a/src/pkcs1v15/encrypting_key.rs b/src/pkcs1v15/encrypting_key.rs index bf851d5b..1004aa7a 100644 --- a/src/pkcs1v15/encrypting_key.rs +++ b/src/pkcs1v15/encrypting_key.rs @@ -16,6 +16,7 @@ pub struct EncryptingKey { impl EncryptingKey { /// Create a new verifying key from an RSA public key. + #[must_use] pub fn new(key: RsaPublicKey) -> Self { Self { inner: key } } diff --git a/src/pkcs1v15/signature.rs b/src/pkcs1v15/signature.rs index 47e8049b..957f9b57 100644 --- a/src/pkcs1v15/signature.rs +++ b/src/pkcs1v15/signature.rs @@ -74,9 +74,9 @@ impl Display for Signature { #[cfg(feature = "serde")] impl Serialize for Signature { - fn serialize(&self, serializer: S) -> core::result::Result + fn serialize(&self, serializer: S) -> Result where - S: serdect::serde::Serializer, + S: serde::Serializer, { serdect::slice::serialize_hex_lower_or_bin(&self.to_bytes(), serializer) } @@ -84,9 +84,9 @@ impl Serialize for Signature { #[cfg(feature = "serde")] impl<'de> Deserialize<'de> for Signature { - fn deserialize(deserializer: D) -> core::result::Result + fn deserialize(deserializer: D) -> Result where - D: serdect::serde::Deserializer<'de>, + D: serde::Deserializer<'de>, { serdect::slice::deserialize_hex_or_bin_vec(deserializer)? .as_slice() diff --git a/src/pkcs1v15/signing_key.rs b/src/pkcs1v15/signing_key.rs index eff44c9a..9fd52c7a 100644 --- a/src/pkcs1v15/signing_key.rs +++ b/src/pkcs1v15/signing_key.rs @@ -44,6 +44,7 @@ where D: Digest + AssociatedOid, { /// Create a new signing key with a prefix for the digest `D`. + #[must_use] pub fn new(key: RsaPrivateKey) -> Self { Self { inner: key, @@ -53,6 +54,7 @@ where } /// Generate a new signing key with a prefix for the digest `D`. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn random(rng: &mut R, bit_size: usize) -> Result { Ok(Self { inner: RsaPrivateKey::new(rng, bit_size)?, @@ -71,6 +73,7 @@ where /// ## Note: unprefixed signatures are uncommon /// /// In most cases you'll want to use [`SigningKey::new`]. + #[must_use] pub fn new_unprefixed(key: RsaPrivateKey) -> Self { Self { inner: key, @@ -80,6 +83,7 @@ where } /// Generate a new signing key with an empty prefix. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn random_unprefixed(rng: &mut R, bit_size: usize) -> Result { Ok(Self { inner: RsaPrivateKey::new(rng, bit_size)?, @@ -310,7 +314,7 @@ where { fn serialize(&self, serializer: S) -> core::result::Result where - S: serdect::serde::Serializer, + S: serde::Serializer, { let der = self.to_pkcs8_der().map_err(ser::Error::custom)?; serdect::slice::serialize_hex_lower_or_bin(&der.as_bytes(), serializer) @@ -324,7 +328,7 @@ where { fn deserialize(deserializer: De) -> core::result::Result where - De: serdect::serde::Deserializer<'de>, + De: serde::Deserializer<'de>, { let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; Self::from_pkcs8_der(&der_bytes).map_err(de::Error::custom) diff --git a/src/pkcs1v15/verifying_key.rs b/src/pkcs1v15/verifying_key.rs index 5eb9d632..8c2e99ac 100644 --- a/src/pkcs1v15/verifying_key.rs +++ b/src/pkcs1v15/verifying_key.rs @@ -38,6 +38,7 @@ where D: Digest + AssociatedOid, { /// Create a new verifying key with a prefix for the digest `D`. + #[must_use] pub fn new(key: RsaPublicKey) -> Self { Self { inner: key, @@ -56,6 +57,7 @@ where /// ## Note: unprefixed signatures are uncommon /// /// In most cases you'll want to use [`VerifyingKey::new`] instead. + #[must_use] pub fn new_unprefixed(key: RsaPublicKey) -> Self { Self { inner: key, @@ -86,7 +88,7 @@ where &digest.finalize_fixed(), &signature.inner, ) - .map_err(|e| e.into()) + .map_err(Into::into) } } @@ -95,7 +97,7 @@ where D: Digest, { fn verify_prehash(&self, prehash: &[u8], signature: &Signature) -> signature::Result<()> { - verify(&self.inner, &self.prefix, prehash, &signature.inner).map_err(|e| e.into()) + verify(&self.inner, &self.prefix, prehash, &signature.inner).map_err(Into::into) } } @@ -110,7 +112,7 @@ where &D::digest(msg), &signature.inner, ) - .map_err(|e| e.into()) + .map_err(Into::into) } } diff --git a/src/pss.rs b/src/pss.rs index c20158b0..99df8c08 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -72,11 +72,13 @@ where { /// New PSS padding for the given digest. /// Digest output size is used as a salt length. + #[must_use] pub fn new() -> Self { Self::new_with_salt(::output_size()) } /// New PSS padding for the given digest with a salt value of the given length. + #[must_use] pub fn new_with_salt(len: usize) -> Self { Self { blinded: false, @@ -87,12 +89,14 @@ where /// New PSS padding for blinded signatures (RSA-BSSA) for the given digest. /// Digest output size is used as a salt length. + #[must_use] pub fn new_blinded() -> Self { Self::new_blinded_with_salt(::output_size()) } /// New PSS padding for blinded signatures (RSA-BSSA) for the given digest /// with a salt value of the given length. + #[must_use] pub fn new_blinded_with_salt(len: usize) -> Self { Self { blinded: true, @@ -106,6 +110,7 @@ impl SignatureScheme for Pss where D: Digest + FixedOutputReset, { + #[allow(clippy::unwrap_in_result, reason = "TODO")] fn sign( mut self, rng: Option<&mut Rng>, @@ -279,6 +284,7 @@ where /// Returns the [`AlgorithmIdentifierOwned`] associated with PSS signature using a given digest. #[cfg(feature = "encoding")] +#[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn get_default_pss_signature_algo_id() -> spki::Result where D: Digest + AssociatedOid, diff --git a/src/pss/blinded_signing_key.rs b/src/pss/blinded_signing_key.rs index d260122a..be26eebd 100644 --- a/src/pss/blinded_signing_key.rs +++ b/src/pss/blinded_signing_key.rs @@ -44,12 +44,14 @@ where /// Create a new RSASSA-PSS signing key which produces "blinded" /// signatures. /// Digest output size is used as a salt length. + #[must_use] pub fn new(key: RsaPrivateKey) -> Self { Self::new_with_salt_len(key, ::output_size()) } /// Create a new RSASSA-PSS signing key which produces "blinded" /// signatures with a salt of the given length. + #[must_use] pub fn new_with_salt_len(key: RsaPrivateKey, salt_len: usize) -> Self { Self { inner: key, @@ -61,12 +63,14 @@ where /// Create a new random RSASSA-PSS signing key which produces "blinded" /// signatures. /// Digest output size is used as a salt length. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn random(rng: &mut R, bit_size: usize) -> Result { Self::random_with_salt_len(rng, bit_size, ::output_size()) } /// Create a new random RSASSA-PSS signing key which produces "blinded" /// signatures with a salt of the given length. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn random_with_salt_len( rng: &mut R, bit_size: usize, @@ -80,6 +84,7 @@ where } /// Return specified salt length for this key + #[must_use] pub fn salt_len(&self) -> usize { self.salt_len } diff --git a/src/pss/signature.rs b/src/pss/signature.rs index 08fede4f..990479ee 100644 --- a/src/pss/signature.rs +++ b/src/pss/signature.rs @@ -74,9 +74,9 @@ impl Display for Signature { #[cfg(feature = "serde")] impl Serialize for Signature { - fn serialize(&self, serializer: S) -> core::result::Result + fn serialize(&self, serializer: S) -> Result where - S: serdect::serde::Serializer, + S: serde::Serializer, { serdect::slice::serialize_hex_lower_or_bin(&self.to_bytes(), serializer) } @@ -84,9 +84,9 @@ impl Serialize for Signature { #[cfg(feature = "serde")] impl<'de> Deserialize<'de> for Signature { - fn deserialize(deserializer: D) -> core::result::Result + fn deserialize(deserializer: D) -> Result where - D: serdect::serde::Deserializer<'de>, + D: serde::Deserializer<'de>, { serdect::slice::deserialize_hex_or_bin_vec(deserializer)? .as_slice() diff --git a/src/pss/signing_key.rs b/src/pss/signing_key.rs index d723bb66..2ede836e 100644 --- a/src/pss/signing_key.rs +++ b/src/pss/signing_key.rs @@ -52,11 +52,13 @@ where { /// Create a new RSASSA-PSS signing key. /// Digest output size is used as a salt length. + #[must_use] pub fn new(key: RsaPrivateKey) -> Self { Self::new_with_salt_len(key, ::output_size()) } /// Create a new RSASSA-PSS signing key with a salt of the given length. + #[must_use] pub fn new_with_salt_len(key: RsaPrivateKey, salt_len: usize) -> Self { Self { inner: key, @@ -67,11 +69,13 @@ where /// Generate a new random RSASSA-PSS signing key. /// Digest output size is used as a salt length. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn random(rng: &mut R, bit_size: usize) -> Result { Self::random_with_salt_len(rng, bit_size, ::output_size()) } /// Generate a new random RSASSA-PSS signing key with a salt of the given length. + #[allow(clippy::missing_errors_doc, reason = "TODO")] pub fn random_with_salt_len( rng: &mut R, bit_size: usize, @@ -85,6 +89,7 @@ where } /// Return specified salt length for this key + #[must_use] pub fn salt_len(&self) -> usize { self.salt_len } @@ -296,7 +301,7 @@ where { fn serialize(&self, serializer: S) -> core::result::Result where - S: serdect::serde::Serializer, + S: serde::Serializer, { let der = self.to_pkcs8_der().map_err(ser::Error::custom)?; serdect::slice::serialize_hex_lower_or_bin(&der.as_bytes(), serializer) @@ -310,7 +315,7 @@ where { fn deserialize(deserializer: De) -> core::result::Result where - De: serdect::serde::Deserializer<'de>, + De: serde::Deserializer<'de>, { let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; Self::from_pkcs8_der(&der_bytes).map_err(de::Error::custom) diff --git a/src/pss/verifying_key.rs b/src/pss/verifying_key.rs index 840c38bb..9bbec666 100644 --- a/src/pss/verifying_key.rs +++ b/src/pss/verifying_key.rs @@ -37,11 +37,13 @@ where { /// Create a new RSASSA-PSS verifying key. /// Digest output size is used as a salt length. + #[must_use] pub fn new(key: RsaPublicKey) -> Self { Self::new_with_salt_len(key, ::output_size()) } /// Create a new RSASSA-PSS verifying key. + #[must_use] pub fn new_with_salt_len(key: RsaPublicKey, salt_len: usize) -> Self { Self { inner: key, @@ -52,6 +54,7 @@ where /// Create a new RSASSA-PSS verifying key. /// Attempts to automatically detect the salt length. + #[must_use] pub fn new_with_auto_salt_len(key: RsaPublicKey) -> Self { Self { inner: key, @@ -61,6 +64,7 @@ where } /// Return specified salt length for this key + #[must_use] pub fn salt_len(&self) -> Option { self.salt_len } @@ -87,7 +91,7 @@ where &signature.inner, self.salt_len, ) - .map_err(|e| e.into()) + .map_err(Into::into) } } @@ -97,7 +101,7 @@ where { fn verify_prehash(&self, prehash: &[u8], signature: &Signature) -> signature::Result<()> { verify_digest::(&self.inner, prehash, &signature.inner, self.salt_len) - .map_err(|e| e.into()) + .map_err(Into::into) } } @@ -112,7 +116,7 @@ where &signature.inner, self.salt_len, ) - .map_err(|e| e.into()) + .map_err(Into::into) } } diff --git a/src/traits/encryption.rs b/src/traits/encryption.rs index cb605419..d07273a6 100644 --- a/src/traits/encryption.rs +++ b/src/traits/encryption.rs @@ -8,18 +8,21 @@ use crate::errors::Result; /// Encrypt the message using provided random source pub trait RandomizedEncryptor { /// Encrypt the given message. + #[allow(clippy::missing_errors_doc, reason = "TODO")] fn encrypt_with_rng(&self, rng: &mut R, msg: &[u8]) -> Result>; } /// Decrypt the given message pub trait Decryptor { /// Decrypt the given message. + #[allow(clippy::missing_errors_doc, reason = "TODO")] fn decrypt(&self, ciphertext: &[u8]) -> Result>; } /// Decrypt the given message using provided random source pub trait RandomizedDecryptor { /// Decrypt the given message. + #[allow(clippy::missing_errors_doc, reason = "TODO")] fn decrypt_with_rng( &self, rng: &mut R, diff --git a/src/traits/padding.rs b/src/traits/padding.rs index 568c76da..c96ecf40 100644 --- a/src/traits/padding.rs +++ b/src/traits/padding.rs @@ -11,8 +11,8 @@ use crate::key::{RsaPrivateKey, RsaPublicKey}; pub trait PaddingScheme { /// Decrypt the given message using the given private key. /// - /// If an `rng` is passed, it uses RSA blinding to help mitigate timing - /// side-channel attacks. + /// If an `rng` is passed, it uses RSA blinding to help mitigate timing side-channel attacks. + #[allow(clippy::missing_errors_doc, reason = "TODO")] fn decrypt( self, rng: Option<&mut Rng>, @@ -21,6 +21,7 @@ pub trait PaddingScheme { ) -> Result>; /// Encrypt the given message using the given public key. + #[allow(clippy::missing_errors_doc, reason = "TODO")] fn encrypt( self, rng: &mut Rng, @@ -32,6 +33,7 @@ pub trait PaddingScheme { /// Digital signature scheme. pub trait SignatureScheme { /// Sign the given digest. + #[allow(clippy::missing_errors_doc, reason = "TODO")] fn sign( self, rng: Option<&mut Rng>, @@ -45,5 +47,6 @@ pub trait SignatureScheme { /// passed in through `hash`. /// /// If the message is valid `Ok(())` is returned, otherwise an `Err` indicating failure. + #[allow(clippy::missing_errors_doc, reason = "TODO")] fn verify(self, pub_key: &RsaPublicKey, hashed: &[u8], sig: &[u8]) -> Result<()>; } diff --git a/tests/pkcs1v15.rs b/tests/pkcs1v15.rs index 49f7f7d7..ca45571e 100644 --- a/tests/pkcs1v15.rs +++ b/tests/pkcs1v15.rs @@ -1,4 +1,5 @@ -// simple but prevent regression - see https://github.com/RustCrypto/RSA/issues/329 +//! PKCS#1 v1.5 tests. + #[cfg(feature = "encoding")] #[test] fn signature_stringify() { diff --git a/tests/wycheproof.rs b/tests/wycheproof.rs index 3d30e869..b71f0ae6 100644 --- a/tests/wycheproof.rs +++ b/tests/wycheproof.rs @@ -218,7 +218,7 @@ fn test_rsa_pss_verify(#[case] file: &str) { for group in tests.groups { summary.group(&group); - let key = rsa::RsaPublicKey::from_pkcs1_der(&group.public_key_asn).unwrap(); + let key = RsaPublicKey::from_pkcs1_der(&group.public_key_asn).unwrap(); println!("key is {:?}", key); for test in group.tests {