From cdfea9e005b7db59dd02ef6187df79353f915a95 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Tue, 29 Nov 2022 11:19:32 -0800 Subject: [PATCH 1/6] spki: make `SubjectPublicKeyInfo` own the public key --- der/src/asn1.rs | 2 +- der/src/asn1/bit_string.rs | 20 ++++++-- pkcs1/src/traits.rs | 9 ++-- spki/src/lib.rs | 7 ++- spki/src/spki.rs | 89 ++++++++++++++++++++++++------------ spki/src/traits.rs | 14 +++--- spki/tests/spki.rs | 8 ++-- x509-cert/src/anchor.rs | 4 +- x509-cert/src/certificate.rs | 4 +- x509-cert/src/request.rs | 4 +- x509-cert/tests/certreq.rs | 2 +- 11 files changed, 106 insertions(+), 57 deletions(-) diff --git a/der/src/asn1.rs b/der/src/asn1.rs index 12fe46b4b..7e01e1e17 100644 --- a/der/src/asn1.rs +++ b/der/src/asn1.rs @@ -27,7 +27,7 @@ mod videotex_string; pub use self::{ any::AnyRef, - bit_string::{BitStringIter, BitStringRef}, + bit_string::{BitStringIter, BitStringLike, BitStringRef}, choice::Choice, context_specific::{ContextSpecific, ContextSpecificRef}, generalized_time::GeneralizedTime, diff --git a/der/src/asn1/bit_string.rs b/der/src/asn1/bit_string.rs index eed14e456..dbd425912 100644 --- a/der/src/asn1/bit_string.rs +++ b/der/src/asn1/bit_string.rs @@ -1,8 +1,8 @@ //! ASN.1 `BIT STRING` support. use crate::{ - asn1::AnyRef, ByteSlice, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind, FixedTag, Header, - Length, Reader, Result, Tag, ValueOrd, Writer, + asn1::AnyRef, ByteSlice, Decode, DecodeValue, DerOrd, Encode, EncodeValue, Error, ErrorKind, + FixedTag, Header, Length, Reader, Result, Tag, ValueOrd, Writer, }; use core::{cmp::Ordering, iter::FusedIterator}; @@ -153,8 +153,8 @@ impl ValueOrd for BitStringRef<'_> { } } -impl<'a> From<&BitStringRef<'a>> for BitStringRef<'a> { - fn from(value: &BitStringRef<'a>) -> BitStringRef<'a> { +impl<'a, 'k> From<&'k BitStringRef<'a>> for BitStringRef<'a> { + fn from(value: &'k BitStringRef<'a>) -> BitStringRef<'a> { *value } } @@ -452,6 +452,18 @@ where } } +/// Trait used as a marker to ensure the type can hold the content of a Bit String +pub trait BitStringLike<'der> +where + Self: Decode<'der> + Encode + FixedTag, +{ +} + +impl<'der> BitStringLike<'der> for BitStringRef<'der> {} + +#[cfg(feature = "alloc")] +impl<'a> BitStringLike<'a> for BitString {} + #[cfg(test)] mod tests { use super::{BitStringRef, Result, Tag}; diff --git a/pkcs1/src/traits.rs b/pkcs1/src/traits.rs index b9899564a..90c98dc5e 100644 --- a/pkcs1/src/traits.rs +++ b/pkcs1/src/traits.rs @@ -16,7 +16,10 @@ use { }; #[cfg(feature = "pkcs8")] -use crate::{ALGORITHM_ID, ALGORITHM_OID}; +use { + crate::{ALGORITHM_ID, ALGORITHM_OID}, + der::asn1::BitStringRef, +}; #[cfg(feature = "std")] use std::path::Path; @@ -191,7 +194,7 @@ where fn from_pkcs1_der(public_key: &[u8]) -> Result { Ok(Self::try_from(pkcs8::SubjectPublicKeyInfo { algorithm: ALGORITHM_ID, - subject_public_key: public_key, + subject_public_key: BitStringRef::from_bytes(public_key)?, })?) } } @@ -214,6 +217,6 @@ impl EncodeRsaPublicKey for T { let doc = self.to_public_key_der()?; let spki = pkcs8::SubjectPublicKeyInfo::from_der(doc.as_bytes())?; spki.algorithm.assert_algorithm_oid(ALGORITHM_OID)?; - RsaPublicKey::from_der(spki.subject_public_key)?.try_into() + RsaPublicKey::from_der(spki.subject_public_key.raw_bytes())?.try_into() } } diff --git a/spki/src/lib.rs b/spki/src/lib.rs index ada8ca3d2..34f5b347e 100644 --- a/spki/src/lib.rs +++ b/spki/src/lib.rs @@ -43,13 +43,16 @@ mod fingerprint; pub use crate::{ algorithm::{AlgorithmIdentifier, AlgorithmIdentifierRef}, error::{Error, Result}, - spki::SubjectPublicKeyInfo, + spki::{SubjectPublicKeyInfo, SubjectPublicKeyInfoRef}, traits::DecodePublicKey, }; pub use der::{self, asn1::ObjectIdentifier}; #[cfg(feature = "alloc")] -pub use {crate::traits::EncodePublicKey, der::Document}; +pub use { + crate::{spki::SubjectPublicKeyInfoOwned, traits::EncodePublicKey}, + der::Document, +}; #[cfg(feature = "fingerprint")] pub use crate::fingerprint::FingerprintBytes; diff --git a/spki/src/spki.rs b/spki/src/spki.rs index 164446512..ca581a145 100644 --- a/spki/src/spki.rs +++ b/spki/src/spki.rs @@ -1,13 +1,17 @@ //! X.509 `SubjectPublicKeyInfo` -use crate::{AlgorithmIdentifierRef, Error, Result}; +use crate::{AlgorithmIdentifier, Error, Result}; use core::cmp::Ordering; use der::{ - asn1::BitStringRef, Decode, DecodeValue, DerOrd, Encode, Header, Reader, Sequence, ValueOrd, + asn1::{AnyRef, BitStringLike, BitStringRef}, + Choice, Decode, DecodeValue, DerOrd, Encode, Header, Reader, Sequence, ValueOrd, }; #[cfg(feature = "alloc")] -use der::Document; +use der::{ + asn1::{Any, BitString}, + Document, +}; #[cfg(feature = "fingerprint")] use crate::{fingerprint, FingerprintBytes}; @@ -15,8 +19,12 @@ use crate::{fingerprint, FingerprintBytes}; #[cfg(feature = "pem")] use der::pem::PemLabel; -#[cfg(doc)] -use crate::AlgorithmIdentifier; +/// [`SubjectPublicKeyInfo`] with [`AnyRef`] algorithm parameters, and [`BitStringRef`] params. +pub type SubjectPublicKeyInfoRef<'a> = SubjectPublicKeyInfo, BitStringRef<'a>>; + +/// [`SubjectPublicKeyInfo`] with [`Any`] algorithm parameters, and [`BitString`] params. +#[cfg(feature = "alloc")] +pub type SubjectPublicKeyInfoOwned = SubjectPublicKeyInfo; /// X.509 `SubjectPublicKeyInfo` (SPKI) as defined in [RFC 5280 § 4.1.2.7]. /// @@ -30,16 +38,20 @@ use crate::AlgorithmIdentifier; /// ``` /// /// [RFC 5280 § 4.1.2.7]: https://tools.ietf.org/html/rfc5280#section-4.1.2.7 -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct SubjectPublicKeyInfo<'a> { +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct SubjectPublicKeyInfo { /// X.509 [`AlgorithmIdentifier`] for the public key type - pub algorithm: AlgorithmIdentifierRef<'a>, + pub algorithm: AlgorithmIdentifier, /// Public key data - pub subject_public_key: &'a [u8], + pub subject_public_key: Key, } -impl<'a> SubjectPublicKeyInfo<'a> { +impl<'a, Params, Key> SubjectPublicKeyInfo +where + Params: Choice<'a> + Encode, + Key: BitStringLike<'a>, +{ /// Calculate the SHA-256 fingerprint of this [`SubjectPublicKeyInfo`] and /// encode it as a Base64 string. /// @@ -69,36 +81,41 @@ impl<'a> SubjectPublicKeyInfo<'a> { self.encode(&mut builder)?; Ok(builder.finish()) } - - /// Get a [`BitString`] representing the `subject_public_key` - fn bitstring(&self) -> der::Result> { - BitStringRef::from_bytes(self.subject_public_key) - } } -impl<'a> DecodeValue<'a> for SubjectPublicKeyInfo<'a> { +impl<'a: 'k, 'k, Params, Key: 'k> DecodeValue<'a> for SubjectPublicKeyInfo +where + Params: Choice<'a> + Encode, + Key: Decode<'a>, +{ fn decode_value>(reader: &mut R, header: Header) -> der::Result { reader.read_nested(header.length, |reader| { Ok(Self { algorithm: reader.decode()?, - subject_public_key: BitStringRef::decode(reader)? - .as_bytes() - .ok_or_else(|| der::Tag::BitString.value_error())?, + subject_public_key: Key::decode(reader)?, }) }) } } -impl<'a> Sequence<'a> for SubjectPublicKeyInfo<'a> { +impl<'a, Params, Key> Sequence<'a> for SubjectPublicKeyInfo +where + Params: Choice<'a> + Encode, + Key: BitStringLike<'a>, +{ fn fields(&self, f: F) -> der::Result where F: FnOnce(&[&dyn Encode]) -> der::Result, { - f(&[&self.algorithm, &self.bitstring()?]) + f(&[&self.algorithm, &self.subject_public_key]) } } -impl<'a> TryFrom<&'a [u8]> for SubjectPublicKeyInfo<'a> { +impl<'a, Params, Key> TryFrom<&'a [u8]> for SubjectPublicKeyInfo +where + Params: Choice<'a> + Encode, + Key: BitStringLike<'a>, +{ type Error = Error; fn try_from(bytes: &'a [u8]) -> Result { @@ -106,10 +123,14 @@ impl<'a> TryFrom<&'a [u8]> for SubjectPublicKeyInfo<'a> { } } -impl ValueOrd for SubjectPublicKeyInfo<'_> { +impl<'a, Params, Key> ValueOrd for SubjectPublicKeyInfo +where + Params: Choice<'a> + DerOrd + Encode, + Key: ValueOrd, +{ fn value_cmp(&self, other: &Self) -> der::Result { match self.algorithm.der_cmp(&other.algorithm)? { - Ordering::Equal => self.bitstring()?.der_cmp(&other.bitstring()?), + Ordering::Equal => self.subject_public_key.value_cmp(&other.subject_public_key), other => Ok(other), } } @@ -117,26 +138,36 @@ impl ValueOrd for SubjectPublicKeyInfo<'_> { #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] -impl TryFrom> for Document { +impl<'a: 'k, 'k, Params, Key: 'k> TryFrom> for Document +where + Params: Choice<'a> + Encode, + Key: BitStringLike<'a>, + BitStringRef<'a>: From<&'k Key>, +{ type Error = Error; - fn try_from(spki: SubjectPublicKeyInfo<'_>) -> Result { + fn try_from(spki: SubjectPublicKeyInfo) -> Result { Self::try_from(&spki) } } #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] -impl TryFrom<&SubjectPublicKeyInfo<'_>> for Document { +impl<'a: 'k, 'k, Params, Key: 'k> TryFrom<&SubjectPublicKeyInfo> for Document +where + Params: Choice<'a> + Encode, + Key: BitStringLike<'a>, + BitStringRef<'a>: From<&'k Key>, +{ type Error = Error; - fn try_from(spki: &SubjectPublicKeyInfo<'_>) -> Result { + fn try_from(spki: &SubjectPublicKeyInfo) -> Result { Ok(Self::encode_msg(spki)?) } } #[cfg(feature = "pem")] #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] -impl PemLabel for SubjectPublicKeyInfo<'_> { +impl PemLabel for SubjectPublicKeyInfo { const PEM_LABEL: &'static str = "PUBLIC KEY"; } diff --git a/spki/src/traits.rs b/spki/src/traits.rs index 2bafcf51b..b9088b965 100644 --- a/spki/src/traits.rs +++ b/spki/src/traits.rs @@ -1,6 +1,6 @@ //! Traits for encoding/decoding SPKI public keys. -use crate::{Error, Result, SubjectPublicKeyInfo}; +use crate::{Error, Result, SubjectPublicKeyInfoRef}; #[cfg(feature = "alloc")] use der::Document; @@ -31,7 +31,7 @@ pub trait DecodePublicKey: Sized { #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] fn from_public_key_pem(s: &str) -> Result { let (label, doc) = Document::from_pem(s)?; - SubjectPublicKeyInfo::validate_pem_label(label)?; + SubjectPublicKeyInfoRef::validate_pem_label(label)?; Self::from_public_key_der(doc.as_bytes()) } @@ -49,17 +49,17 @@ pub trait DecodePublicKey: Sized { #[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "std"))))] fn read_public_key_pem_file(path: impl AsRef) -> Result { let (label, doc) = Document::read_pem_file(path)?; - SubjectPublicKeyInfo::validate_pem_label(&label)?; + SubjectPublicKeyInfoRef::validate_pem_label(&label)?; Self::from_public_key_der(doc.as_bytes()) } } impl DecodePublicKey for T where - T: for<'a> TryFrom, Error = Error>, + T: for<'a> TryFrom, Error = Error>, { fn from_public_key_der(bytes: &[u8]) -> Result { - Self::try_from(SubjectPublicKeyInfo::try_from(bytes)?) + Self::try_from(SubjectPublicKeyInfoRef::try_from(bytes)?) } } @@ -75,7 +75,7 @@ pub trait EncodePublicKey { #[cfg_attr(docsrs, doc(cfg(feature = "pem")))] fn to_public_key_pem(&self, line_ending: LineEnding) -> Result { let doc = self.to_public_key_der()?; - Ok(doc.to_pem(SubjectPublicKeyInfo::PEM_LABEL, line_ending)?) + Ok(doc.to_pem(SubjectPublicKeyInfoRef::PEM_LABEL, line_ending)?) } /// Write ASN.1 DER-encoded public key to the given path @@ -94,6 +94,6 @@ pub trait EncodePublicKey { line_ending: LineEnding, ) -> Result<()> { let doc = self.to_public_key_der()?; - Ok(doc.write_pem_file(path, SubjectPublicKeyInfo::PEM_LABEL, line_ending)?) + Ok(doc.write_pem_file(path, SubjectPublicKeyInfoRef::PEM_LABEL, line_ending)?) } } diff --git a/spki/tests/spki.rs b/spki/tests/spki.rs index 3f8ce9684..6653e5a12 100644 --- a/spki/tests/spki.rs +++ b/spki/tests/spki.rs @@ -55,7 +55,7 @@ fn decode_ec_p256_der() { "1.2.840.10045.3.1.7".parse().unwrap() ); - assert_eq!(spki.subject_public_key, &hex!("041CACFFB55F2F2CEFD89D89EB374B2681152452802DEEA09916068137D839CF7FC481A44492304D7EF66AC117BEFE83A8D08F155F2B52F9F618DD447029048E0F")[..]); + assert_eq!(spki.subject_public_key.raw_bytes(), &hex!("041CACFFB55F2F2CEFD89D89EB374B2681152452802DEEA09916068137D839CF7FC481A44492304D7EF66AC117BEFE83A8D08F155F2B52F9F618DD447029048E0F")[..]); } #[test] @@ -67,7 +67,7 @@ fn decode_ed25519_and_fingerprint_spki() { assert_eq!(spki.algorithm.oid, "1.3.101.112".parse().unwrap()); assert_eq!(spki.algorithm.parameters, None); assert_eq!( - spki.subject_public_key, + spki.subject_public_key.raw_bytes(), &hex!("4D29167F3F1912A6F7ADFA293A051A15C05EC67B8F17267B1C5550DCE853BD0D")[..] ); @@ -87,7 +87,7 @@ fn decode_ed25519_and_fingerprint_base64() { assert_eq!(spki.algorithm.oid, "1.3.101.112".parse().unwrap()); assert_eq!(spki.algorithm.parameters, None); assert_eq!( - spki.subject_public_key, + spki.subject_public_key.raw_bytes(), &hex!("4D29167F3F1912A6F7ADFA293A051A15C05EC67B8F17267B1C5550DCE853BD0D")[..] ); @@ -104,7 +104,7 @@ fn decode_rsa_2048_der() { assert_eq!(spki.algorithm.oid, "1.2.840.113549.1.1.1".parse().unwrap()); assert!(spki.algorithm.parameters.unwrap().is_null()); - assert_eq!(spki.subject_public_key, &hex!("3082010A0282010100B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F0203010001")[..]); + assert_eq!(spki.subject_public_key.raw_bytes(), &hex!("3082010A0282010100B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F0203010001")[..]); } #[test] diff --git a/x509-cert/src/anchor.rs b/x509-cert/src/anchor.rs index ad7ef08e1..2a329b7c6 100644 --- a/x509-cert/src/anchor.rs +++ b/x509-cert/src/anchor.rs @@ -7,7 +7,7 @@ use crate::{Certificate, TbsCertificate}; use der::asn1::{OctetStringRef, Utf8StringRef}; use der::{Choice, Enumerated, Sequence}; use flagset::{flags, FlagSet}; -use spki::SubjectPublicKeyInfo; +use spki::SubjectPublicKeyInfoRef; /// Version identifier for TrustAnchorInfo #[derive(Clone, Debug, Copy, PartialEq, Eq, Enumerated)] @@ -45,7 +45,7 @@ pub struct TrustAnchorInfo<'a> { #[asn1(default = "Default::default")] pub version: Version, - pub pub_key: SubjectPublicKeyInfo<'a>, + pub pub_key: SubjectPublicKeyInfoRef<'a>, pub key_id: OctetStringRef<'a>, diff --git a/x509-cert/src/certificate.rs b/x509-cert/src/certificate.rs index d8abe515e..a1853c565 100644 --- a/x509-cert/src/certificate.rs +++ b/x509-cert/src/certificate.rs @@ -8,7 +8,7 @@ use core::cmp::Ordering; use const_oid::AssociatedOid; use der::asn1::{BitStringRef, UintRef}; use der::{Decode, Enumerated, Error, ErrorKind, Sequence, ValueOrd}; -use spki::{AlgorithmIdentifierRef, SubjectPublicKeyInfo}; +use spki::{AlgorithmIdentifierRef, SubjectPublicKeyInfoRef}; #[cfg(feature = "pem")] use der::pem::PemLabel; @@ -88,7 +88,7 @@ pub struct TbsCertificate<'a> { pub issuer: Name<'a>, pub validity: Validity, pub subject: Name<'a>, - pub subject_public_key_info: SubjectPublicKeyInfo<'a>, + pub subject_public_key_info: SubjectPublicKeyInfoRef<'a>, #[asn1(context_specific = "1", tag_mode = "IMPLICIT", optional = "true")] pub issuer_unique_id: Option>, diff --git a/x509-cert/src/request.rs b/x509-cert/src/request.rs index 3ed2c73b6..23c01c54d 100644 --- a/x509-cert/src/request.rs +++ b/x509-cert/src/request.rs @@ -9,7 +9,7 @@ use const_oid::db::rfc5912::ID_EXTENSION_REQ; use const_oid::{AssociatedOid, ObjectIdentifier}; use der::asn1::BitStringRef; use der::{Decode, Enumerated, Sequence}; -use spki::{AlgorithmIdentifierRef, SubjectPublicKeyInfo}; +use spki::{AlgorithmIdentifierRef, SubjectPublicKeyInfoRef}; /// Version identifier for certification request information. /// @@ -43,7 +43,7 @@ pub struct CertReqInfo<'a> { pub subject: Name<'a>, /// Subject public key info. - pub public_key: SubjectPublicKeyInfo<'a>, + pub public_key: SubjectPublicKeyInfoRef<'a>, /// Request attributes. #[asn1(context_specific = "0", tag_mode = "IMPLICIT")] diff --git a/x509-cert/tests/certreq.rs b/x509-cert/tests/certreq.rs index 547524cd9..a76c02866 100644 --- a/x509-cert/tests/certreq.rs +++ b/x509-cert/tests/certreq.rs @@ -52,7 +52,7 @@ fn decode_rsa_2048_der() { let alg = cr.info.public_key.algorithm; assert_eq!(alg.oid, "1.2.840.113549.1.1.1".parse().unwrap()); assert!(alg.parameters.unwrap().is_null()); - assert_eq!(cr.info.public_key.subject_public_key, RSA_KEY); + assert_eq!(cr.info.public_key.subject_public_key.raw_bytes(), RSA_KEY); // Check the attributes (just one; contains extensions). assert_eq!(cr.info.attributes.len(), 1); From a477702f79cc49b9c2df77841cd0aa4f71392fb7 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Sun, 11 Dec 2022 19:52:38 -0800 Subject: [PATCH 2/6] fixes --- pkcs1/src/traits.rs | 6 +++--- pkcs8/src/lib.rs | 4 +++- spki/tests/spki.rs | 22 +++++++++++----------- spki/tests/traits.rs | 6 +++--- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/pkcs1/src/traits.rs b/pkcs1/src/traits.rs index 90c98dc5e..96f403f5f 100644 --- a/pkcs1/src/traits.rs +++ b/pkcs1/src/traits.rs @@ -189,10 +189,10 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))] impl DecodeRsaPublicKey for T where - T: for<'a> TryFrom, Error = pkcs8::Error>, + T: for<'a> TryFrom, Error = pkcs8::Error>, { fn from_pkcs1_der(public_key: &[u8]) -> Result { - Ok(Self::try_from(pkcs8::SubjectPublicKeyInfo { + Ok(Self::try_from(pkcs8::SubjectPublicKeyInfoRef { algorithm: ALGORITHM_ID, subject_public_key: BitStringRef::from_bytes(public_key)?, })?) @@ -215,7 +215,7 @@ impl EncodeRsaPrivateKey for T { impl EncodeRsaPublicKey for T { fn to_pkcs1_der(&self) -> Result { let doc = self.to_public_key_der()?; - let spki = pkcs8::SubjectPublicKeyInfo::from_der(doc.as_bytes())?; + let spki = pkcs8::SubjectPublicKeyInfoRef::from_der(doc.as_bytes())?; spki.algorithm.assert_algorithm_oid(ALGORITHM_OID)?; RsaPublicKey::from_der(spki.subject_public_key.raw_bytes())?.try_into() } diff --git a/pkcs8/src/lib.rs b/pkcs8/src/lib.rs index 05fc94d7c..de71bc782 100644 --- a/pkcs8/src/lib.rs +++ b/pkcs8/src/lib.rs @@ -83,7 +83,9 @@ pub use crate::{ version::Version, }; pub use der::{self, asn1::ObjectIdentifier, oid::AssociatedOid}; -pub use spki::{self, AlgorithmIdentifierRef, DecodePublicKey, SubjectPublicKeyInfo}; +pub use spki::{ + self, AlgorithmIdentifierRef, DecodePublicKey, SubjectPublicKeyInfo, SubjectPublicKeyInfoRef, +}; #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] diff --git a/spki/tests/spki.rs b/spki/tests/spki.rs index 6653e5a12..e655c0b29 100644 --- a/spki/tests/spki.rs +++ b/spki/tests/spki.rs @@ -1,7 +1,7 @@ //! `SubjectPublicKeyInfo` tests. use hex_literal::hex; -use spki::SubjectPublicKeyInfo; +use spki::SubjectPublicKeyInfoRef; #[cfg(feature = "alloc")] use der::Encode; @@ -46,7 +46,7 @@ const ED25519_SPKI_FINGERPRINT: &[u8] = #[test] fn decode_ec_p256_der() { - let spki = SubjectPublicKeyInfo::try_from(EC_P256_DER_EXAMPLE).unwrap(); + let spki = SubjectPublicKeyInfoRef::try_from(EC_P256_DER_EXAMPLE).unwrap(); assert_eq!(spki.algorithm.oid, "1.2.840.10045.2.1".parse().unwrap()); @@ -62,7 +62,7 @@ fn decode_ec_p256_der() { #[cfg(feature = "fingerprint")] fn decode_ed25519_and_fingerprint_spki() { // Repeat the decode test from the pkcs8 crate - let spki = SubjectPublicKeyInfo::try_from(ED25519_DER_EXAMPLE).unwrap(); + let spki = SubjectPublicKeyInfoRef::try_from(ED25519_DER_EXAMPLE).unwrap(); assert_eq!(spki.algorithm.oid, "1.3.101.112".parse().unwrap()); assert_eq!(spki.algorithm.parameters, None); @@ -82,7 +82,7 @@ fn decode_ed25519_and_fingerprint_spki() { #[cfg(all(feature = "fingerprint", feature = "alloc", feature = "base64ct"))] fn decode_ed25519_and_fingerprint_base64() { // Repeat the decode test from the pkcs8 crate - let spki = SubjectPublicKeyInfo::try_from(ED25519_DER_EXAMPLE).unwrap(); + let spki = SubjectPublicKeyInfoRef::try_from(ED25519_DER_EXAMPLE).unwrap(); assert_eq!(spki.algorithm.oid, "1.3.101.112".parse().unwrap()); assert_eq!(spki.algorithm.parameters, None); @@ -100,7 +100,7 @@ fn decode_ed25519_and_fingerprint_base64() { #[test] fn decode_rsa_2048_der() { - let spki = SubjectPublicKeyInfo::try_from(RSA_2048_DER_EXAMPLE).unwrap(); + let spki = SubjectPublicKeyInfoRef::try_from(RSA_2048_DER_EXAMPLE).unwrap(); assert_eq!(spki.algorithm.oid, "1.2.840.113549.1.1.1".parse().unwrap()); assert!(spki.algorithm.parameters.unwrap().is_null()); @@ -110,7 +110,7 @@ fn decode_rsa_2048_der() { #[test] #[cfg(feature = "alloc")] fn encode_ec_p256_der() { - let pk = SubjectPublicKeyInfo::try_from(EC_P256_DER_EXAMPLE).unwrap(); + let pk = SubjectPublicKeyInfoRef::try_from(EC_P256_DER_EXAMPLE).unwrap(); let pk_encoded = pk.to_vec().unwrap(); assert_eq!(EC_P256_DER_EXAMPLE, pk_encoded.as_slice()); } @@ -118,7 +118,7 @@ fn encode_ec_p256_der() { #[test] #[cfg(feature = "alloc")] fn encode_ed25519_der() { - let pk = SubjectPublicKeyInfo::try_from(ED25519_DER_EXAMPLE).unwrap(); + let pk = SubjectPublicKeyInfoRef::try_from(ED25519_DER_EXAMPLE).unwrap(); let pk_encoded = pk.to_vec().unwrap(); assert_eq!(ED25519_DER_EXAMPLE, pk_encoded.as_slice()); } @@ -126,7 +126,7 @@ fn encode_ed25519_der() { #[test] #[cfg(feature = "alloc")] fn encode_rsa_2048_der() { - let pk = SubjectPublicKeyInfo::try_from(RSA_2048_DER_EXAMPLE).unwrap(); + let pk = SubjectPublicKeyInfoRef::try_from(RSA_2048_DER_EXAMPLE).unwrap(); let pk_encoded = pk.to_vec().unwrap(); assert_eq!(RSA_2048_DER_EXAMPLE, pk_encoded.as_slice()); } @@ -134,7 +134,7 @@ fn encode_rsa_2048_der() { #[test] #[cfg(feature = "pem")] fn encode_ec_p256_pem() { - let pk = SubjectPublicKeyInfo::try_from(EC_P256_DER_EXAMPLE).unwrap(); + let pk = SubjectPublicKeyInfoRef::try_from(EC_P256_DER_EXAMPLE).unwrap(); let pk_encoded = pk.to_pem(LineEnding::LF).unwrap(); assert_eq!(EC_P256_PEM_EXAMPLE, pk_encoded); } @@ -142,7 +142,7 @@ fn encode_ec_p256_pem() { #[test] #[cfg(feature = "pem")] fn encode_ed25519_pem() { - let pk = SubjectPublicKeyInfo::try_from(ED25519_DER_EXAMPLE).unwrap(); + let pk = SubjectPublicKeyInfoRef::try_from(ED25519_DER_EXAMPLE).unwrap(); let pk_encoded = pk.to_pem(LineEnding::LF).unwrap(); assert_eq!(ED25519_PEM_EXAMPLE, pk_encoded); } @@ -150,7 +150,7 @@ fn encode_ed25519_pem() { #[test] #[cfg(feature = "pem")] fn encode_rsa_2048_pem() { - let pk = SubjectPublicKeyInfo::try_from(RSA_2048_DER_EXAMPLE).unwrap(); + let pk = SubjectPublicKeyInfoRef::try_from(RSA_2048_DER_EXAMPLE).unwrap(); let pk_encoded = pk.to_pem(LineEnding::LF).unwrap(); assert_eq!(RSA_2048_PEM_EXAMPLE, pk_encoded); } diff --git a/spki/tests/traits.rs b/spki/tests/traits.rs index 3c3cec95a..aa68921aa 100644 --- a/spki/tests/traits.rs +++ b/spki/tests/traits.rs @@ -3,7 +3,7 @@ #![cfg(any(feature = "pem", feature = "std"))] use der::{Decode, Encode}; -use spki::{DecodePublicKey, Document, EncodePublicKey, Error, Result, SubjectPublicKeyInfo}; +use spki::{DecodePublicKey, Document, EncodePublicKey, Error, Result, SubjectPublicKeyInfoRef}; #[cfg(feature = "pem")] use spki::der::pem::LineEnding; @@ -36,10 +36,10 @@ impl EncodePublicKey for MockKey { } } -impl TryFrom> for MockKey { +impl TryFrom> for MockKey { type Error = Error; - fn try_from(spki: SubjectPublicKeyInfo<'_>) -> Result { + fn try_from(spki: SubjectPublicKeyInfoRef<'_>) -> Result { Ok(MockKey(spki.to_vec()?)) } } From 5409c632aed9f1e7a36185b3123dad69bf851103 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Sun, 11 Dec 2022 20:10:26 -0800 Subject: [PATCH 3/6] doc fixes --- spki/src/traits.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spki/src/traits.rs b/spki/src/traits.rs index b9088b965..99818ed1f 100644 --- a/spki/src/traits.rs +++ b/spki/src/traits.rs @@ -14,6 +14,9 @@ use { #[cfg(feature = "std")] use std::path::Path; +#[cfg(doc)] +use crate::SubjectPublicKeyInfo; + /// Parse a public key object from an encoded SPKI document. pub trait DecodePublicKey: Sized { /// Deserialize object from ASN.1 DER-encoded [`SubjectPublicKeyInfo`] From d62140f9a7135054f1c423ef21a1207cda046855 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Tue, 13 Dec 2022 09:58:20 -0800 Subject: [PATCH 4/6] remove BitStringLike trait --- der/src/asn1.rs | 2 +- der/src/asn1/bit_string.rs | 16 ++-------------- spki/src/spki.rs | 16 +++++++++------- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/der/src/asn1.rs b/der/src/asn1.rs index 7e01e1e17..12fe46b4b 100644 --- a/der/src/asn1.rs +++ b/der/src/asn1.rs @@ -27,7 +27,7 @@ mod videotex_string; pub use self::{ any::AnyRef, - bit_string::{BitStringIter, BitStringLike, BitStringRef}, + bit_string::{BitStringIter, BitStringRef}, choice::Choice, context_specific::{ContextSpecific, ContextSpecificRef}, generalized_time::GeneralizedTime, diff --git a/der/src/asn1/bit_string.rs b/der/src/asn1/bit_string.rs index dbd425912..6997632bf 100644 --- a/der/src/asn1/bit_string.rs +++ b/der/src/asn1/bit_string.rs @@ -1,8 +1,8 @@ //! ASN.1 `BIT STRING` support. use crate::{ - asn1::AnyRef, ByteSlice, Decode, DecodeValue, DerOrd, Encode, EncodeValue, Error, ErrorKind, - FixedTag, Header, Length, Reader, Result, Tag, ValueOrd, Writer, + asn1::AnyRef, ByteSlice, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind, FixedTag, Header, + Length, Reader, Result, Tag, ValueOrd, Writer, }; use core::{cmp::Ordering, iter::FusedIterator}; @@ -452,18 +452,6 @@ where } } -/// Trait used as a marker to ensure the type can hold the content of a Bit String -pub trait BitStringLike<'der> -where - Self: Decode<'der> + Encode + FixedTag, -{ -} - -impl<'der> BitStringLike<'der> for BitStringRef<'der> {} - -#[cfg(feature = "alloc")] -impl<'a> BitStringLike<'a> for BitString {} - #[cfg(test)] mod tests { use super::{BitStringRef, Result, Tag}; diff --git a/spki/src/spki.rs b/spki/src/spki.rs index ca581a145..aa880231c 100644 --- a/spki/src/spki.rs +++ b/spki/src/spki.rs @@ -3,8 +3,8 @@ use crate::{AlgorithmIdentifier, Error, Result}; use core::cmp::Ordering; use der::{ - asn1::{AnyRef, BitStringLike, BitStringRef}, - Choice, Decode, DecodeValue, DerOrd, Encode, Header, Reader, Sequence, ValueOrd, + asn1::{AnyRef, BitStringRef}, + Choice, Decode, DecodeValue, DerOrd, Encode, FixedTag, Header, Reader, Sequence, ValueOrd, }; #[cfg(feature = "alloc")] @@ -50,7 +50,9 @@ pub struct SubjectPublicKeyInfo { impl<'a, Params, Key> SubjectPublicKeyInfo where Params: Choice<'a> + Encode, - Key: BitStringLike<'a>, + // TODO: replace FixedTag with FixedTag once + // /~https://github.com/rust-lang/rust/issues/92827 is fixed + Key: Decode<'a> + Encode + FixedTag, { /// Calculate the SHA-256 fingerprint of this [`SubjectPublicKeyInfo`] and /// encode it as a Base64 string. @@ -101,7 +103,7 @@ where impl<'a, Params, Key> Sequence<'a> for SubjectPublicKeyInfo where Params: Choice<'a> + Encode, - Key: BitStringLike<'a>, + Key: Decode<'a> + Encode + FixedTag, { fn fields(&self, f: F) -> der::Result where @@ -114,7 +116,7 @@ where impl<'a, Params, Key> TryFrom<&'a [u8]> for SubjectPublicKeyInfo where Params: Choice<'a> + Encode, - Key: BitStringLike<'a>, + Key: Decode<'a> + Encode + FixedTag, { type Error = Error; @@ -141,7 +143,7 @@ where impl<'a: 'k, 'k, Params, Key: 'k> TryFrom> for Document where Params: Choice<'a> + Encode, - Key: BitStringLike<'a>, + Key: Decode<'a> + Encode + FixedTag, BitStringRef<'a>: From<&'k Key>, { type Error = Error; @@ -156,7 +158,7 @@ where impl<'a: 'k, 'k, Params, Key: 'k> TryFrom<&SubjectPublicKeyInfo> for Document where Params: Choice<'a> + Encode, - Key: BitStringLike<'a>, + Key: Decode<'a> + Encode + FixedTag, BitStringRef<'a>: From<&'k Key>, { type Error = Error; From ecb918ebef990c1f9211b1fc4b8efc580243ac91 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Tue, 13 Dec 2022 10:37:28 -0800 Subject: [PATCH 5/6] unneeded lifetime --- der/src/asn1/bit_string.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/der/src/asn1/bit_string.rs b/der/src/asn1/bit_string.rs index 6997632bf..eed14e456 100644 --- a/der/src/asn1/bit_string.rs +++ b/der/src/asn1/bit_string.rs @@ -153,8 +153,8 @@ impl ValueOrd for BitStringRef<'_> { } } -impl<'a, 'k> From<&'k BitStringRef<'a>> for BitStringRef<'a> { - fn from(value: &'k BitStringRef<'a>) -> BitStringRef<'a> { +impl<'a> From<&BitStringRef<'a>> for BitStringRef<'a> { + fn from(value: &BitStringRef<'a>) -> BitStringRef<'a> { *value } } From b9308fd3e166669e1145c4014139f93adc1da4db Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Tue, 13 Dec 2022 10:48:53 -0800 Subject: [PATCH 6/6] Update spki/src/spki.rs Co-authored-by: Tony Arcieri --- spki/src/spki.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spki/src/spki.rs b/spki/src/spki.rs index aa880231c..ee7494d4a 100644 --- a/spki/src/spki.rs +++ b/spki/src/spki.rs @@ -50,7 +50,7 @@ pub struct SubjectPublicKeyInfo { impl<'a, Params, Key> SubjectPublicKeyInfo where Params: Choice<'a> + Encode, - // TODO: replace FixedTag with FixedTag once + // TODO: replace FixedTag with FixedTag once // /~https://github.com/rust-lang/rust/issues/92827 is fixed Key: Decode<'a> + Encode + FixedTag, {