From 2712580e1bbc8ae6e525638f299d50240ab015dd Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Tue, 21 May 2024 21:39:28 -0700 Subject: [PATCH 1/2] der: implement `Hash` for `Any` --- der/src/asn1/any.rs | 4 ++-- der/src/bytes_owned.rs | 2 +- der/src/bytes_ref.rs | 2 +- der/src/length.rs | 2 +- der/src/tag.rs | 2 +- der/src/tag/number.rs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/der/src/asn1/any.rs b/der/src/asn1/any.rs index 1ed9286c0..42ac3f669 100644 --- a/der/src/asn1/any.rs +++ b/der/src/asn1/any.rs @@ -23,7 +23,7 @@ use crate::SliceWriter; /// and useful concept which is still extensively used in things like /// PKI-related RFCs. #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] pub struct AnyRef<'a> { /// Tag representing the type of the encoded value. tag: Tag, @@ -169,7 +169,7 @@ mod allocating { /// This type provides the same functionality as [`AnyRef`] but owns the /// backing data. #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] - #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] + #[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] pub struct Any { /// Tag representing the type of the encoded value. tag: Tag, diff --git a/der/src/bytes_owned.rs b/der/src/bytes_owned.rs index 38f5855f0..04ad0348b 100644 --- a/der/src/bytes_owned.rs +++ b/der/src/bytes_owned.rs @@ -9,7 +9,7 @@ use alloc::{boxed::Box, vec::Vec}; use core::cmp::Ordering; /// Byte slice newtype which respects the `Length::max()` limit. -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] pub(crate) struct BytesOwned { /// Precomputed `Length` (avoids possible panicking conversions) length: Length, diff --git a/der/src/bytes_ref.rs b/der/src/bytes_ref.rs index ca40e3156..7d384ba41 100644 --- a/der/src/bytes_ref.rs +++ b/der/src/bytes_ref.rs @@ -10,7 +10,7 @@ use core::cmp::Ordering; use crate::StrOwned; /// Byte slice newtype which respects the `Length::max()` limit. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] pub(crate) struct BytesRef<'a> { /// Precomputed `Length` (avoids possible panicking conversions) pub length: Length, diff --git a/der/src/length.rs b/der/src/length.rs index 7ffdfc0cc..726c1c7b7 100644 --- a/der/src/length.rs +++ b/der/src/length.rs @@ -24,7 +24,7 @@ const INDEFINITE_LENGTH_OCTET: u8 = 0b10000000; // 0x80 /// ASN.1-encoded length. /// /// Maximum length is defined by the [`Length::MAX`] constant (256 MiB). -#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)] pub struct Length(u32); impl Length { diff --git a/der/src/tag.rs b/der/src/tag.rs index 4ece7cbad..80b797ca9 100644 --- a/der/src/tag.rs +++ b/der/src/tag.rs @@ -48,7 +48,7 @@ impl Tagged for T { /// - Bit 6: primitive (0) or constructed (1) /// - Bits 5-1: tag number #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)] #[non_exhaustive] pub enum Tag { /// `BOOLEAN` tag: `1`. diff --git a/der/src/tag/number.rs b/der/src/tag/number.rs index 6a7eaae22..dfff9a961 100644 --- a/der/src/tag/number.rs +++ b/der/src/tag/number.rs @@ -18,7 +18,7 @@ use core::fmt; /// encoded by using a leading tag number of 31 (`0b11111`). This library /// deliberately does not support this: tag numbers greater than 30 are /// disallowed. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] pub struct TagNumber(pub(super) u8); impl TagNumber { From cdef103fa0f64a9347bc7e6fc21b431ac6ee3a88 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Tue, 21 May 2024 21:19:19 -0700 Subject: [PATCH 2/2] spki: implement `Hash` for `AlgorithmIdentifier` This allows to build an hashmap with various hashing algorithm when verifying objects. --- spki/src/algorithm.rs | 2 +- spki/tests/spki.rs | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/spki/src/algorithm.rs b/spki/src/algorithm.rs index baa89cc4f..5cbc8b655 100644 --- a/spki/src/algorithm.rs +++ b/spki/src/algorithm.rs @@ -21,7 +21,7 @@ use der::asn1::Any; /// /// [RFC 5280 Section 4.1.1.2]: https://tools.ietf.org/html/rfc5280#section-4.1.1.2 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] pub struct AlgorithmIdentifier { /// Algorithm OID, i.e. the `algorithm` field in the `AlgorithmIdentifier` /// ASN.1 schema. diff --git a/spki/tests/spki.rs b/spki/tests/spki.rs index f912d4875..0b03f9fb6 100644 --- a/spki/tests/spki.rs +++ b/spki/tests/spki.rs @@ -5,7 +5,10 @@ use hex_literal::hex; use spki::SubjectPublicKeyInfoRef; #[cfg(feature = "alloc")] -use der::Encode; +use { + der::Encode, + spki::{AlgorithmIdentifier, AlgorithmIdentifierOwned}, +}; #[cfg(feature = "pem")] use der::{pem::LineEnding, EncodePem}; @@ -159,3 +162,20 @@ fn encode_rsa_2048_pem() { let pk_encoded = pk.to_pem(LineEnding::LF).unwrap(); assert_eq!(RSA_2048_PEM_EXAMPLE, pk_encoded); } + +#[test] +#[cfg(feature = "alloc")] +fn build_hashset_of_digests() { + const SHA1: AlgorithmIdentifierOwned = AlgorithmIdentifier { + oid: ObjectIdentifier::new_unwrap("1.3.14.3.2.26"), + parameters: None, + }; + const SHA256: AlgorithmIdentifierOwned = AlgorithmIdentifier { + oid: ObjectIdentifier::new_unwrap("2.16.840.1.101.3.4.2.1"), + parameters: None, + }; + + let mut hashes = std::collections::HashSet::new(); + hashes.insert(SHA1); + hashes.insert(SHA256); +}