diff --git a/Cargo.lock b/Cargo.lock index 5047ac05f..225e6a278 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1478,6 +1478,7 @@ dependencies = [ "arbitrary", "base64ct", "der", + "digest", "hex-literal 1.0.0", "sha2", "tempfile", diff --git a/spki/Cargo.toml b/spki/Cargo.toml index 2d6ebe7e7..bccd23484 100644 --- a/spki/Cargo.toml +++ b/spki/Cargo.toml @@ -21,6 +21,7 @@ der = { version = "0.8.0-rc.0", features = ["oid"] } # Optional dependencies arbitrary = { version = "1.4", features = ["derive"], optional = true } base64ct = { version = "1", optional = true, default-features = false } +digest = { version = "0.11.0-pre.10", optional = true, default-features = false } sha2 = { version = "=0.11.0-pre.5", optional = true, default-features = false } [dev-dependencies] @@ -33,7 +34,7 @@ std = ["der/std", "alloc"] arbitrary = ["std", "dep:arbitrary", "der/arbitrary"] base64 = ["dep:base64ct"] -fingerprint = ["sha2"] +fingerprint = ["digest", "sha2"] pem = ["alloc", "der/pem"] [package.metadata.docs.rs] diff --git a/spki/src/digest.rs b/spki/src/digest.rs new file mode 100644 index 000000000..fd9d3169c --- /dev/null +++ b/spki/src/digest.rs @@ -0,0 +1,15 @@ +use der::{Result, Writer}; +use digest::Digest; + +/// Adapter object to write to a digest backend +pub struct DigestWriter<'d, D>(pub &'d mut D); + +impl Writer for DigestWriter<'_, D> +where + D: Digest, +{ + fn write(&mut self, slice: &[u8]) -> Result<()> { + self.0.update(slice); + Ok(()) + } +} diff --git a/spki/src/fingerprint.rs b/spki/src/fingerprint.rs deleted file mode 100644 index ba06e62e8..000000000 --- a/spki/src/fingerprint.rs +++ /dev/null @@ -1,42 +0,0 @@ -//! SPKI fingerprint support. - -use der::Writer; -use sha2::{Digest, Sha256}; - -/// Size of a SHA-256 SPKI fingerprint in bytes. -pub(crate) const SIZE: usize = 32; - -/// Raw bytes of a SPKI fingerprint i.e. SHA-256 digest of -/// `SubjectPublicKeyInfo`'s DER encoding. -/// -/// See [RFC7469 § 2.1.1] for more information. -/// -/// [RFC7469 § 2.1.1]: https://datatracker.ietf.org/doc/html/rfc7469#section-2.1.1 -pub type FingerprintBytes = [u8; SIZE]; - -/// Writer newtype which accepts DER being serialized on-the-fly and computes a -/// hash of the contents. -#[derive(Clone, Default)] -pub(crate) struct Builder { - /// In-progress digest being computed from streaming DER. - digest: Sha256, -} - -impl Builder { - /// Create a new fingerprint builder. - pub fn new() -> Self { - Self::default() - } - - /// Finish computing a fingerprint, returning the computed digest. - pub fn finish(self) -> FingerprintBytes { - self.digest.finalize().into() - } -} - -impl Writer for Builder { - fn write(&mut self, der_bytes: &[u8]) -> der::Result<()> { - self.digest.update(der_bytes); - Ok(()) - } -} diff --git a/spki/src/lib.rs b/spki/src/lib.rs index 6c0caa72a..f3fb26f3a 100644 --- a/spki/src/lib.rs +++ b/spki/src/lib.rs @@ -43,8 +43,8 @@ mod error; mod spki; mod traits; -#[cfg(feature = "fingerprint")] -mod fingerprint; +#[cfg(feature = "digest")] +mod digest; pub use crate::{ algorithm::{AlgorithmIdentifier, AlgorithmIdentifierRef, AlgorithmIdentifierWithOid}, @@ -67,5 +67,18 @@ pub use { der::Document, }; +#[cfg(feature = "digest")] +pub use crate::digest::DigestWriter; + +/// Size of a SHA-256 SPKI fingerprint in bytes. +#[cfg(feature = "fingerprint")] +pub(crate) const SIZE: usize = 32; + +/// Raw bytes of a SPKI fingerprint i.e. SHA-256 digest of +/// `SubjectPublicKeyInfo`'s DER encoding. +/// +/// See [RFC7469 § 2.1.1] for more information. +/// +/// [RFC7469 § 2.1.1]: https://datatracker.ietf.org/doc/html/rfc7469#section-2.1.1 #[cfg(feature = "fingerprint")] -pub use crate::fingerprint::FingerprintBytes; +pub type FingerprintBytes = [u8; SIZE]; diff --git a/spki/src/spki.rs b/spki/src/spki.rs index 78fd5eac7..6251d2ea1 100644 --- a/spki/src/spki.rs +++ b/spki/src/spki.rs @@ -15,7 +15,11 @@ use der::{ }; #[cfg(feature = "fingerprint")] -use crate::{FingerprintBytes, fingerprint}; +use { + crate::{DigestWriter, FingerprintBytes}, + digest::Digest, + sha2::Sha256, +}; #[cfg(feature = "pem")] use der::pem::PemLabel; @@ -80,9 +84,9 @@ where /// [RFC7469 § 2.1.1]: https://datatracker.ietf.org/doc/html/rfc7469#section-2.1.1 #[cfg(feature = "fingerprint")] pub fn fingerprint_bytes(&self) -> Result { - let mut builder = fingerprint::Builder::new(); - self.encode(&mut builder)?; - Ok(builder.finish()) + let mut hash = Sha256::new(); + self.encode(&mut DigestWriter(&mut hash))?; + Ok(hash.finalize().into()) } }