diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-11-17 16:54:32 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-12-07 16:37:57 +0100 |
commit | d05f6cecbaeda0be9eae6a80517c1839d581545e (patch) | |
tree | 6af2ad42f85b623022056c36d5ffa5ec5e2283e5 | |
parent | 3b88cd1725bdded57c2ff845db5d471d2da63e6a (diff) |
openpgp: Drop hash::Context in favor of a pub trait hash::Digest.
-rw-r--r-- | ipc/src/keygrip.rs | 7 | ||||
-rw-r--r-- | openpgp/src/cert.rs | 5 | ||||
-rw-r--r-- | openpgp/src/crypto/ecdh.rs | 1 | ||||
-rw-r--r-- | openpgp/src/crypto/hash.rs | 163 | ||||
-rw-r--r-- | openpgp/src/crypto/mem.rs | 1 | ||||
-rw-r--r-- | openpgp/src/crypto/mpi.rs | 23 | ||||
-rw-r--r-- | openpgp/src/crypto/s2k.rs | 1 | ||||
-rw-r--r-- | openpgp/src/packet/container.rs | 4 | ||||
-rw-r--r-- | openpgp/src/packet/key.rs | 2 | ||||
-rw-r--r-- | openpgp/src/packet/mdc.rs | 4 | ||||
-rw-r--r-- | openpgp/src/packet/signature.rs | 6 | ||||
-rw-r--r-- | openpgp/src/parse.rs | 6 | ||||
-rw-r--r-- | openpgp/src/parse/hashed_reader.rs | 4 | ||||
-rw-r--r-- | openpgp/src/serialize/stream.rs | 4 |
14 files changed, 110 insertions, 121 deletions
diff --git a/ipc/src/keygrip.rs b/ipc/src/keygrip.rs index 1f4f3edf..968b975f 100644 --- a/ipc/src/keygrip.rs +++ b/ipc/src/keygrip.rs @@ -89,17 +89,16 @@ impl Keygrip { /// ``` pub fn of(key: &PublicKey) -> Result<Keygrip> { use openpgp::crypto::hash; - use std::io::Write; use self::PublicKey::*; let mut hash = HashAlgorithm::SHA1.context().unwrap(); - fn hash_sexp_mpi(hash: &mut hash::Context, kind: char, prefix: &[u8], + fn hash_sexp_mpi(hash: &mut dyn hash::Digest, kind: char, prefix: &[u8], mpi: &MPI) { hash_sexp(hash, kind, prefix, mpi.value()); } - fn hash_sexp(hash: &mut hash::Context, kind: char, prefix: &[u8], + fn hash_sexp(hash: &mut dyn hash::Digest, kind: char, prefix: &[u8], buf: &[u8]) { write!(hash, "(1:{}{}:", @@ -109,7 +108,7 @@ impl Keygrip { write!(hash, ")").unwrap(); } - fn hash_ecc(hash: &mut hash::Context, curve: &Curve, q: &MPI) + fn hash_ecc(hash: &mut dyn hash::Digest, curve: &Curve, q: &MPI) { for (i, name) in "pabgnhq".chars().enumerate() { if i == 5 { diff --git a/openpgp/src/cert.rs b/openpgp/src/cert.rs index bc274021..3876b8e1 100644 --- a/openpgp/src/cert.rs +++ b/openpgp/src/cert.rs @@ -148,7 +148,10 @@ use std::ops::{Deref, DerefMut}; use std::time; use crate::{ - crypto::Signer, + crypto::{ + Signer, + hash::Digest, + }, Error, Result, SignatureType, diff --git a/openpgp/src/crypto/ecdh.rs b/openpgp/src/crypto/ecdh.rs index c203e397..84b8660e 100644 --- a/openpgp/src/crypto/ecdh.rs +++ b/openpgp/src/crypto/ecdh.rs @@ -12,6 +12,7 @@ use crate::vec_truncate; use crate::{Error, Result}; use crate::crypto::SessionKey; +use crate::crypto::hash::Digest; use crate::crypto::mem::Protected; use crate::crypto::mpi::{self, MPI}; use crate::key; diff --git a/openpgp/src/crypto/hash.rs b/openpgp/src/crypto/hash.rs index 27641429..13645379 100644 --- a/openpgp/src/crypto/hash.rs +++ b/openpgp/src/crypto/hash.rs @@ -1,12 +1,35 @@ //! Cryptographic hash functions and hashing of OpenPGP data //! structures. //! -//! This module provides [`Context`] representing a hash function +//! This module provides trait [`Digest`] representing a hash function //! context independent of the cryptographic backend, as well as trait //! [`Hash`] that handles hashing of OpenPGP data structures. //! -//! [`Context`]: struct.Context.html +//! [`Digest`]: trait.Digest.html //! [`Hash`]: trait.Hash.html +//! +//! # Examples +//! +//! ```rust +//! # fn main() -> sequoia_openpgp::Result<()> { +//! use sequoia_openpgp::types::HashAlgorithm; +//! +//! // Create a context and feed data to it. +//! let mut ctx = HashAlgorithm::SHA512.context()?; +//! ctx.update(&b"The quick brown fox jumps over the lazy dog."[..]); +//! +//! // Extract the digest. +//! let mut digest = vec![0; ctx.digest_size()]; +//! ctx.digest(&mut digest); +//! +//! use sequoia_openpgp::fmt::hex; +//! assert_eq!(&hex::encode(digest), +//! "91EA1245F20D46AE9A037A989F54F1F7\ +//! 90F0A47607EEB8A14D12890CEA77A1BB\ +//! C6C7ED9CF205E67B7F2B8FD4C7DFD3A7\ +//! A8617E45F3C463D481C7E586C39AC1ED"); +//! # Ok(()) } +//! ``` use std::convert::TryFrom; @@ -31,7 +54,12 @@ use std::io::{self, Write}; const DUMP_HASHED_VALUES: Option<&str> = None; /// Hasher capable of calculating a digest for the input byte stream. -pub(crate) trait Digest: DynClone + Write + Send + Sync { +/// +/// This provides an abstract interface to the hash functions used in +/// OpenPGP. `Digest`s can be are created using [`HashAlgorithm::context`]. +/// +/// [`HashAlgorithm::context`]: ../../types/enum.HashAlgorithm.html#method.context +pub trait Digest: DynClone + Write + Send + Sync { /// Returns the algorithm. fn algo(&self) -> HashAlgorithm; @@ -49,59 +77,30 @@ pub(crate) trait Digest: DynClone + Write + Send + Sync { /// `digest` must be at least `self.digest_size()` bytes large, /// otherwise the digest will be truncated. fn digest(&mut self, digest: &mut [u8]) -> Result<()>; + + /// Finalizes the hash function and computes the digest. + fn into_digest(mut self) -> Result<Vec<u8>> + where Self: std::marker::Sized + { + let mut digest = vec![0u8; self.digest_size()]; + self.digest(&mut digest)?; + Ok(digest) + } } dyn_clone::clone_trait_object!(Digest); -/// State of a hash function. -/// -/// This provides an abstract interface to the hash functions used in -/// OpenPGP. `Context`s are created using [`HashAlgorithm::context`]. -/// -/// [`HashAlgorithm::context`]: ../../types/enum.HashAlgorithm.html#method.context -/// -/// # Examples -/// -/// ```rust -/// # fn main() -> sequoia_openpgp::Result<()> { -/// use sequoia_openpgp::types::HashAlgorithm; -/// -/// // Create a context and feed data to it. -/// let mut ctx = HashAlgorithm::SHA512.context()?; -/// ctx.update(&b"The quick brown fox jumps over the lazy dog."[..]); -/// -/// // Extract the digest. -/// let mut digest = vec![0; ctx.digest_size()]; -/// ctx.digest(&mut digest); -/// -/// use sequoia_openpgp::fmt::hex; -/// assert_eq!(&hex::encode(digest), -/// "91EA1245F20D46AE9A037A989F54F1F7\ -/// 90F0A47607EEB8A14D12890CEA77A1BB\ -/// C6C7ED9CF205E67B7F2B8FD4C7DFD3A7\ -/// A8617E45F3C463D481C7E586C39AC1ED"); -/// # Ok(()) } -/// ``` -#[derive(Clone)] -pub struct Context { - algo: HashAlgorithm, - ctx: Box<dyn Digest>, -} - -impl Context { - /// Returns the algorithm. - pub fn algo(&self) -> HashAlgorithm { - self.algo +impl Digest for Box<dyn Digest> { + fn algo(&self) -> HashAlgorithm { + self.as_ref().algo() } - - /// Size of the digest in bytes - pub fn digest_size(&self) -> usize { - self.ctx.digest_size() + fn digest_size(&self) -> usize { + self.as_ref().digest_size() } /// Writes data into the hash function. - pub fn update<D: AsRef<[u8]>>(&mut self, data: D) { - self.ctx.update(data.as_ref()); + fn update(&mut self, data: &[u8]) { + self.as_mut().update(data) } /// Finalizes the hash function and writes the digest into the @@ -113,26 +112,8 @@ impl Context { /// otherwise the digest will be truncated. /// /// [`self.digest_size()`]: #method.digest_size - pub fn digest<D: AsMut<[u8]>>(&mut self, mut digest: D) -> Result<()> { - self.ctx.digest(digest.as_mut()) - } - - /// Finalizes the hash function and computes the digest. - pub fn into_digest(mut self) -> Result<Vec<u8>> { - let mut digest = vec![0u8; self.digest_size()]; - self.digest(&mut digest)?; - Ok(digest) - } -} - -impl io::Write for Context { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - self.update(buf); - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) + fn digest(&mut self, digest: &mut [u8]) -> Result<()>{ + self.as_mut().digest(digest) } } @@ -146,19 +127,16 @@ impl HashAlgorithm { /// [`HashAlgorithm::is_supported`]. /// /// [`HashAlgorithm::is_supported`]: #method.is_supported - pub fn context(self) -> Result<Context> { - let hasher = match self { + pub fn context(self) -> Result<Box<dyn Digest>> { + let hasher: Box<dyn Digest> = match self { HashAlgorithm::SHA1 => Box::new(crate::crypto::backend::sha1cd::build()), _ => self.new_hasher()?, }; - Ok(Context { - algo: self, - ctx: if let Some(prefix) = DUMP_HASHED_VALUES { - Box::new(HashDumper::new(hasher, prefix)) - } else { - hasher - }, + Ok(if let Some(prefix) = DUMP_HASHED_VALUES { + Box::new(HashDumper::new(hasher, prefix)) + } else { + hasher }) } } @@ -261,24 +239,24 @@ impl io::Write for HashDumper { /// [`Signature`'s hashing functions]: ../../packet/enum.Signature.html#hashing-functions pub trait Hash { /// Updates the given hash with this object. - fn hash(&self, hash: &mut Context); + fn hash(&self, hash: &mut dyn Digest); } impl Hash for UserID { - fn hash(&self, hash: &mut Context) { + fn hash(&self, hash: &mut dyn Digest) { let len = self.value().len() as u32; let mut header = [0; 5]; header[0] = 0xB4; header[1..5].copy_from_slice(&len.to_be_bytes()); - hash.update(header); + hash.update(&header); hash.update(self.value()); } } impl Hash for UserAttribute { - fn hash(&self, hash: &mut Context) { + fn hash(&self, hash: &mut dyn Digest) { let len = self.value().len() as u32; let mut header = [0; 5]; @@ -294,7 +272,7 @@ impl<P, R> Hash for Key4<P, R> where P: key::KeyParts, R: key::KeyRole, { - fn hash(&self, hash: &mut Context) { + fn hash(&self, hash: &mut dyn Digest) { use crate::serialize::MarshalInto; // We hash 9 bytes plus the MPIs. But, the len doesn't @@ -330,7 +308,7 @@ impl<P, R> Hash for Key4<P, R> } impl Hash for Signature { - fn hash(&self, hash: &mut Context) { + fn hash(&self, hash: &mut dyn Digest) { match self { Signature::V4(sig) => sig.hash(hash), } @@ -338,13 +316,13 @@ impl Hash for Signature { } impl Hash for Signature4 { - fn hash(&self, hash: &mut Context) { + fn hash(&self, hash: &mut dyn Digest) { self.fields.hash(hash); } } impl Hash for signature::SignatureFields { - fn hash(&self, hash: &mut Context) { + fn hash(&self, hash: &mut dyn Digest) { use crate::serialize::MarshalInto; // XXX: Annoyingly, we have no proper way of handling errors @@ -406,20 +384,20 @@ impl Hash for signature::SignatureFields { /// <a name="hashing-functions"></a> impl signature::SignatureFields { /// Computes the message digest of standalone signatures. - pub fn hash_standalone(&self, hash: &mut Context) + pub fn hash_standalone(&self, hash: &mut dyn Digest) { self.hash(hash); } /// Computes the message digest of timestamp signatures. - pub fn hash_timestamp(&self, hash: &mut Context) + pub fn hash_timestamp(&self, hash: &mut dyn Digest) { self.hash_standalone(hash); } /// Returns the message digest of the direct key signature over /// the specified primary key. - pub fn hash_direct_key<P>(&self, hash: &mut Context, + pub fn hash_direct_key<P>(&self, hash: &mut dyn Digest, key: &Key<P, key::PrimaryRole>) where P: key::KeyParts, { @@ -429,7 +407,7 @@ impl signature::SignatureFields { /// Returns the message digest of the subkey binding over the /// specified primary key and subkey. - pub fn hash_subkey_binding<P, Q>(&self, hash: &mut Context, + pub fn hash_subkey_binding<P, Q>(&self, hash: &mut dyn Digest, key: &Key<P, key::PrimaryRole>, subkey: &Key<Q, key::SubordinateRole>) where P: key::KeyParts, @@ -442,7 +420,7 @@ impl signature::SignatureFields { /// Returns the message digest of the primary key binding over the /// specified primary key and subkey. - pub fn hash_primary_key_binding<P, Q>(&self, hash: &mut Context, + pub fn hash_primary_key_binding<P, Q>(&self, hash: &mut dyn Digest, key: &Key<P, key::PrimaryRole>, subkey: &Key<Q, key::SubordinateRole>) where P: key::KeyParts, @@ -453,7 +431,7 @@ impl signature::SignatureFields { /// Returns the message digest of the user ID binding over the /// specified primary key, user ID, and signature. - pub fn hash_userid_binding<P>(&self, hash: &mut Context, + pub fn hash_userid_binding<P>(&self, hash: &mut dyn Digest, key: &Key<P, key::PrimaryRole>, userid: &UserID) where P: key::KeyParts, @@ -467,7 +445,7 @@ impl signature::SignatureFields { /// the specified primary key, user attribute, and signature. pub fn hash_user_attribute_binding<P>( &self, - hash: &mut Context, + hash: &mut dyn Digest, key: &Key<P, key::PrimaryRole>, ua: &UserAttribute) where P: key::KeyParts, @@ -480,6 +458,7 @@ impl signature::SignatureFields { #[cfg(test)] mod test { + use super::*; use crate::Cert; use crate::parse::Parse; diff --git a/openpgp/src/crypto/mem.rs b/openpgp/src/crypto/mem.rs index 96f80483..f9979868 100644 --- a/openpgp/src/crypto/mem.rs +++ b/openpgp/src/crypto/mem.rs @@ -249,6 +249,7 @@ mod has_access_to_prekey { use lazy_static; use crate::types::{AEADAlgorithm, HashAlgorithm, SymmetricAlgorithm}; use crate::crypto::{aead, SessionKey}; + use crate::crypto::hash::Digest; use super::*; lazy_static::lazy_static! { diff --git a/openpgp/src/crypto/mpi.rs b/openpgp/src/crypto/mpi.rs index 8f9cfb2a..9eac133b 100644 --- a/openpgp/src/crypto/mpi.rs +++ b/openpgp/src/crypto/mpi.rs @@ -17,6 +17,7 @@ use std::fmt; use std::cmp::Ordering; +use std::io::Write; #[cfg(test)] use quickcheck::{Arbitrary, Gen}; @@ -237,7 +238,7 @@ impl fmt::Debug for MPI { } impl Hash for MPI { - fn hash(&self, hash: &mut hash::Context) { + fn hash(&self, hash: &mut dyn hash::Digest) { let len = self.bits() as u16; hash.update(&len.to_be_bytes()); @@ -545,8 +546,9 @@ impl PublicKey { } impl Hash for PublicKey { - fn hash(&self, hash: &mut hash::Context) { - self.serialize(hash).expect("hashing does not fail") + fn hash(&self, mut hash: &mut dyn hash::Digest) { + self.serialize(&mut hash as &mut dyn Write) + .expect("hashing does not fail") } } @@ -806,8 +808,9 @@ impl SecretKeyMaterial { } impl Hash for SecretKeyMaterial { - fn hash(&self, hash: &mut hash::Context) { - self.serialize(hash).expect("hashing does not fail") + fn hash(&self, mut hash: &mut dyn hash::Digest) { + self.serialize(&mut hash as &mut dyn Write) + .expect("hashing does not fail") } } @@ -930,8 +933,9 @@ impl Ciphertext { } impl Hash for Ciphertext { - fn hash(&self, hash: &mut hash::Context) { - self.serialize(hash).expect("hashing does not fail") + fn hash(&self, mut hash: &mut dyn hash::Digest) { + self.serialize(&mut hash as &mut dyn Write) + .expect("hashing does not fail") } } @@ -1021,8 +1025,9 @@ pub enum Signature { } impl Hash for Signature { - fn hash(&self, hash: &mut hash::Context) { - self.serialize(hash).expect("hashing does not fail") + fn hash(&self, mut hash: &mut dyn hash::Digest) { + self.serialize(&mut hash as &mut dyn Write) + .expect("hashing does not fail") } } diff --git a/openpgp/src/crypto/s2k.rs b/openpgp/src/crypto/s2k.rs index ecc6313e..93430810 100644 --- a/openpgp/src/crypto/s2k.rs +++ b/openpgp/src/crypto/s2k.rs @@ -11,6 +11,7 @@ use crate::Result; use crate::HashAlgorithm; use crate::crypto::Password; use crate::crypto::SessionKey; +use crate::crypto::hash::Digest; use std::fmt; diff --git a/openpgp/src/packet/container.rs b/openpgp/src/packet/container.rs index a06d84cc..cb96b85d 100644 --- a/openpgp/src/packet/container.rs +++ b/openpgp/src/packet/container.rs @@ -296,14 +296,14 @@ impl Container { /// Creates a hash context for hashing the body. pub(crate) // For parse.rs - fn make_body_hash() -> hash::Context { + fn make_body_hash() -> Box<dyn hash::Digest> { CONTAINER_BODY_HASH.context() .expect("CONTAINER_BODY_HASH must be implemented") } /// Hashes content that has been streamed. pub(crate) // For parse.rs - fn set_body_hash(&mut self, mut h: hash::Context) { + fn set_body_hash(&mut self, mut h: Box<dyn hash::Digest>) { self.body_digest.resize(h.digest_size(), 0); let _ = h.digest(&mut self.body_digest); } diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs index 34fbedc0..f705b60d 100644 --- a/openpgp/src/packet/key.rs +++ b/openpgp/src/packet/key.rs @@ -96,7 +96,7 @@ use quickcheck::{Arbitrary, Gen}; use crate::Error; use crate::cert::prelude::*; -use crate::crypto::{self, mem, mpi, hash::Hash}; +use crate::crypto::{self, mem, mpi, hash::{Hash, Digest}}; use crate::packet; use crate::packet::prelude::*; use crate::PublicKeyAlgorithm; diff --git a/openpgp/src/packet/mdc.rs b/openpgp/src/packet/mdc.rs index fdb6513e..9f07dafe 100644 --- a/openpgp/src/packet/mdc.rs +++ b/openpgp/src/packet/mdc.rs @@ -88,8 +88,8 @@ impl From<[u8; 20]> for MDC { } } -impl From<crypto::hash::Context> for MDC { - fn from(mut hash: crypto::hash::Context) -> Self { +impl From<Box<dyn crypto::hash::Digest>> for MDC { + fn from(mut hash: Box<dyn crypto::hash::Digest>) -> Self { let mut value : [u8; 20] = Default::default(); let _ = hash.digest(&mut value[..]); value.into() diff --git a/openpgp/src/packet/signature.rs b/openpgp/src/packet/signature.rs index ff952c7b..9128332d 100644 --- a/openpgp/src/packet/signature.rs +++ b/openpgp/src/packet/signature.rs @@ -126,7 +126,7 @@ use crate::Error; use crate::Result; use crate::crypto::{ mpi, - hash::{self, Hash}, + hash::{self, Hash, Digest}, Signer, }; use crate::KeyHandle; @@ -1424,7 +1424,7 @@ impl SignatureBuilder { /// [`set_signature_creation_time` |