summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2020-11-17 16:54:32 +0100
committerJustus Winter <justus@sequoia-pgp.org>2020-12-07 16:37:57 +0100
commitd05f6cecbaeda0be9eae6a80517c1839d581545e (patch)
tree6af2ad42f85b623022056c36d5ffa5ec5e2283e5
parent3b88cd1725bdded57c2ff845db5d471d2da63e6a (diff)
openpgp: Drop hash::Context in favor of a pub trait hash::Digest.
-rw-r--r--ipc/src/keygrip.rs7
-rw-r--r--openpgp/src/cert.rs5
-rw-r--r--openpgp/src/crypto/ecdh.rs1
-rw-r--r--openpgp/src/crypto/hash.rs163
-rw-r--r--openpgp/src/crypto/mem.rs1
-rw-r--r--openpgp/src/crypto/mpi.rs23
-rw-r--r--openpgp/src/crypto/s2k.rs1
-rw-r--r--openpgp/src/packet/container.rs4
-rw-r--r--openpgp/src/packet/key.rs2
-rw-r--r--openpgp/src/packet/mdc.rs4
-rw-r--r--openpgp/src/packet/signature.rs6
-rw-r--r--openpgp/src/parse.rs6
-rw-r--r--openpgp/src/parse/hashed_reader.rs4
-rw-r--r--openpgp/src/serialize/stream.rs4
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`