sequoia_openpgp/crypto/
hash.rs

1//! Cryptographic hash functions and hashing of OpenPGP data
2//! structures.
3//!
4//! This module provides struct [`Context`] representing a hash
5//! function context independent of the cryptographic backend, as well
6//! as trait [`Hash`] that handles hashing of OpenPGP data structures.
7//!
8//!
9//! # Examples
10//!
11//! ```rust
12//! # fn main() -> sequoia_openpgp::Result<()> {
13//! use sequoia_openpgp::types::HashAlgorithm;
14//!
15//! // Create a context and feed data to it.
16//! let mut ctx = HashAlgorithm::SHA512.context()?.for_digest();
17//! ctx.update(&b"The quick brown fox jumps over the lazy dog."[..]);
18//!
19//! // Extract the digest.
20//! let mut digest = vec![0; ctx.digest_size()];
21//! ctx.digest(&mut digest);
22//!
23//! use sequoia_openpgp::fmt::hex;
24//! assert_eq!(&hex::encode(digest),
25//!            "91EA1245F20D46AE9A037A989F54F1F7\
26//!             90F0A47607EEB8A14D12890CEA77A1BB\
27//!             C6C7ED9CF205E67B7F2B8FD4C7DFD3A7\
28//!             A8617E45F3C463D481C7E586C39AC1ED");
29//! # Ok(()) }
30//! ```
31
32use std::{
33    convert::TryFrom,
34    sync::OnceLock,
35};
36
37use dyn_clone::DynClone;
38
39use crate::HashAlgorithm;
40use crate::packet::Key;
41use crate::packet::UserID;
42use crate::packet::UserAttribute;
43use crate::packet::key;
44use crate::packet::key::{Key4, Key6};
45use crate::packet::Signature;
46use crate::packet::signature::{self, Signature3, Signature4, Signature6};
47use crate::Error;
48use crate::Result;
49use crate::types::{SignatureType, Timestamp};
50
51use std::fs::{File, OpenOptions};
52use std::io::{self, Write};
53
54// If set to e.g. Some("/tmp/hash"), we will dump everything that is
55// hashed to files /tmp/hash-N, where N is a number.
56const DUMP_HASHED_VALUES: Option<&str> = None;
57
58// ASN.1 OID values copied from the nettle-rs crate:
59// https://gitlab.com/sequoia-pgp/nettle-rs/-/blob/main/src/rsa/pkcs1.rs#L22
60
61/// ASN.1 OID for MD5
62const ASN1_OID_MD5: &[u8] = &[
63    0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
64    0x02, 0x05, 0x05, 0x00, 0x04, 0x10,
65];
66
67/// ASN.1 OID for RipeMD160
68const ASN1_OID_RIPEMD160: &[u8] = &[
69    0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05,
70    0x00, 0x04, 0x14,
71];
72
73/// ASN.1 OID for SHA1
74const ASN1_OID_SHA1: &[u8] = &[
75    0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
76    0x00, 0x04, 0x14,
77];
78
79/// ASN.1 OID for SHA224
80const ASN1_OID_SHA224: &[u8] = &[
81    0x30, 0x2D, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
82    0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C,
83];
84
85/// ASN.1 OID for SHA256
86const ASN1_OID_SHA256: &[u8] = &[
87    0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
88    0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20,
89];
90
91/// ASN.1 OID for SHA384
92const ASN1_OID_SHA384: &[u8] = &[
93    0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
94    0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30,
95];
96
97/// ASN.1 OID for SHA512
98const ASN1_OID_SHA512: &[u8] = &[
99    0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
100    0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40,
101];
102
103/// ASN.1 OID for SHA3-256
104const ASN1_OID_SHA3_256: &[u8] = &[
105    0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
106    0x04, 0x02, 0x08, 0x05, 0x00, 0x04, 0x20
107];
108
109/// ASN.1 OID for SHA3-512.
110const ASN1_OID_SHA3_512: &[u8] = &[
111    0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
112    0x04, 0x02, 0x0a, 0x05, 0x00, 0x04, 0x40
113];
114
115/// List of hashes that the signer may produce.
116///
117/// This list is ordered by the preference so that the most preferred
118/// hash algorithm is first.
119pub(crate) fn default_hashes() -> &'static [HashAlgorithm] {
120    static DEFAULT_HASHES: OnceLock<Vec<HashAlgorithm>> = OnceLock::new();
121    DEFAULT_HASHES.get_or_init(|| vec![
122        HashAlgorithm::default(),
123        HashAlgorithm::SHA512,
124        HashAlgorithm::SHA384,
125        HashAlgorithm::SHA256,
126        HashAlgorithm::SHA224,
127        HashAlgorithm::SHA1,
128        HashAlgorithm::RipeMD,
129        HashAlgorithm::MD5,
130    ])
131}
132
133/// List of hashes that the signer may produce.
134///
135/// This list is sorted.
136pub(crate) fn default_hashes_sorted() -> &'static [HashAlgorithm] {
137    static DEFAULT_HASHES: OnceLock<Vec<HashAlgorithm>> = OnceLock::new();
138    DEFAULT_HASHES.get_or_init(|| {
139        let mut hashes = default_hashes().to_vec();
140        hashes.sort();
141        hashes
142    })
143}
144
145/// Hasher capable of calculating a digest for the input byte stream.
146///
147/// This provides an abstract interface to the hash functions used in
148/// OpenPGP.  It is used by the crypto backends to provide a uniform
149/// interface to hash functions.
150pub(crate) trait Digest: DynClone + Write + Send + Sync {
151    /// Writes data into the hash function.
152    fn update(&mut self, data: &[u8]);
153
154    /// Finalizes the hash function and writes the digest into the
155    /// provided slice.
156    ///
157    /// Resets the hash function contexts.
158    ///
159    /// `digest` must be at least `self.digest_size()` bytes large,
160    /// otherwise the digest will be truncated.
161    fn digest(&mut self, digest: &mut [u8]) -> Result<()>;
162}
163
164dyn_clone::clone_trait_object!(Digest);
165
166impl Digest for Box<dyn Digest> {
167    fn update(&mut self, data: &[u8]) {
168        self.as_mut().update(data)
169    }
170
171    fn digest(&mut self, digest: &mut [u8]) -> Result<()>{
172        self.as_mut().digest(digest)
173    }
174}
175
176/// A hash algorithm context.
177///
178/// Provides additional metadata for the hashing contexts.  This is
179/// implemented here once, so that the backends don't have to provide
180/// it.
181#[derive(Clone)]
182pub struct Context {
183    /// The hash algorithm.
184    algo: HashAlgorithm,
185
186    /// Whether we are hashing for a signature, and if so, which
187    /// version.
188    for_signature: Option<u8>,
189
190    /// The underlying bare hash context.
191    ctx: Box<dyn Digest>,
192}
193
194impl Context {
195    /// Returns the algorithm.
196    pub fn algo(&self) -> HashAlgorithm {
197        self.algo
198    }
199
200    /// Size of the digest in bytes.
201    pub fn digest_size(&self) -> usize {
202        self.algo.digest_size()
203            .expect("we only create Contexts for known hash algos")
204    }
205
206    /// Writes data into the hash function.
207    pub fn update(&mut self, data: &[u8]) {
208        self.ctx.update(data)
209    }
210
211    /// Finalizes the hash function and writes the digest into the
212    /// provided slice.
213    ///
214    /// Resets the hash function contexts.
215    ///
216    /// `digest` must be at least `self.digest_size()` bytes large,
217    /// otherwise the digest will be truncated.
218    pub fn digest(&mut self, digest: &mut [u8]) -> Result<()>{
219        self.ctx.digest(digest)
220    }
221
222    /// Finalizes the hash function and computes the digest.
223    pub fn into_digest(mut self) -> Result<Vec<u8>>
224        where Self: std::marker::Sized
225    {
226        let mut digest = vec![0u8; self.digest_size()];
227        self.digest(&mut digest)?;
228        Ok(digest)
229    }
230
231    /// Returns whether we are hashing for a signature, and if so,
232    /// which version.
233    fn for_signature(&self) -> Option<u8> {
234        self.for_signature.clone()
235    }
236}
237
238impl io::Write for Context {
239    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
240        self.ctx.write(buf)
241    }
242
243    fn flush(&mut self) -> io::Result<()> {
244        self.ctx.flush()
245    }
246}
247
248/// Builds hash contexts.
249pub struct Builder(Context);
250
251impl Builder {
252    /// Returns a hash context for signing and verification of OpenPGP
253    /// signatures.
254    pub fn for_signature(self, version: u8) -> Context {
255        let mut ctx = self.0;
256        ctx.for_signature = Some(version);
257        ctx
258    }
259
260    /// Returns a hash context for general hashing, i.e. not for the
261    /// purpose of signing and verification of OpenPGP signatures
262    pub fn for_digest(self) -> Context {
263        self.0
264    }
265}
266
267
268impl HashAlgorithm {
269    /// Creates a new hash context builder for this algorithm.
270    ///
271    /// # Errors
272    ///
273    /// Fails with [`Error::UnsupportedHashAlgorithm`] if Sequoia does
274    /// not support this algorithm. See
275    /// [`HashAlgorithm::is_supported`].
276    pub fn context(self) -> Result<Builder> {
277        if ! self.is_supported() {
278            return Err(Error::UnsupportedHashAlgorithm(self).into());
279        }
280
281        let mut hasher: Box<dyn Digest> = match self {
282            HashAlgorithm::SHA1 if ! cfg!(feature = "crypto-fuzzing") =>
283                Box::new(crate::crypto::backend::sha1cd::build()),
284            _ => self.new_hasher()?,
285        };
286
287        if let Some(prefix) = DUMP_HASHED_VALUES {
288            hasher = Box::new(HashDumper::new(hasher, prefix))
289        }
290
291        Ok(Builder(Context {
292            algo: self,
293            for_signature: None,
294            ctx: hasher,
295        }))
296    }
297
298    /// Returns the prefix of a serialized `DigestInfo` structure
299    /// that contains the ASN.1 OID of this hash algorithm.
300    ///
301    /// The prefix is used for encoding RSA signatures according to
302    /// the `EMSA-PKCS1-v1_5` algorithm as specified in [RFC 8017].
303    ///
304    /// [RFC 8017]: https://www.rfc-editor.org/rfc/rfc8017.html#section-9.2
305    ///
306    /// ```
307    /// # use sequoia_openpgp::types::HashAlgorithm;
308    /// # fn main() -> sequoia_openpgp::Result<()> {
309    /// let algo = HashAlgorithm::SHA512;
310    /// let digest = // raw bytes of the digest
311    /// # Vec::<u8>::new();
312    /// let digest_info = Vec::from(algo.oid()?).extend(digest);
313    /// # Ok(()) }
314    /// ```
315    ///
316    /// # Errors
317    ///
318    /// Fails with `Error::UnsupportedHashAlgorithm` for unknown or
319    /// private hash algorithms.
320    pub fn oid(self) -> Result<&'static [u8]> {
321        match self {
322            HashAlgorithm::SHA1 => Ok(ASN1_OID_SHA1),
323            HashAlgorithm::SHA224 => Ok(ASN1_OID_SHA224),
324            HashAlgorithm::SHA256 => Ok(ASN1_OID_SHA256),
325            HashAlgorithm::SHA384 => Ok(ASN1_OID_SHA384),
326            HashAlgorithm::SHA512 => Ok(ASN1_OID_SHA512),
327            HashAlgorithm::SHA3_256 => Ok(ASN1_OID_SHA3_256),
328            HashAlgorithm::SHA3_512 => Ok(ASN1_OID_SHA3_512),
329            HashAlgorithm::MD5 => Ok(ASN1_OID_MD5),
330            HashAlgorithm::RipeMD => Ok(ASN1_OID_RIPEMD160),
331            HashAlgorithm::Private(_) | HashAlgorithm::Unknown(_) =>
332                Err(crate::Error::UnsupportedHashAlgorithm(self).into()),
333        }
334    }
335}
336
337struct HashDumper {
338    hasher: Box<dyn Digest>,
339    sink: File,
340    filename: String,
341    written: usize,
342}
343
344impl HashDumper {
345    fn new(hasher: Box<dyn Digest>, prefix: &str) -> Self {
346        let mut n = 0;
347        let mut filename;
348        let sink = loop {
349            filename = format!("{}-{}", prefix, n);
350            match OpenOptions::new().write(true).create_new(true)
351                .open(&filename)
352            {
353                Ok(f) => break f,
354                Err(_) => n += 1,
355            }
356        };
357        eprintln!("HashDumper: Writing to {}...", &filename);
358        HashDumper {
359            hasher,
360            sink,
361            filename,
362            written: 0,
363        }
364    }
365}
366
367impl Clone for HashDumper {
368    fn clone(&self) -> HashDumper {
369        // We only ever create instances of HashDumper when debugging.
370        // Whenever we're cloning an instance, just open another file for
371        // inspection.
372        let prefix = DUMP_HASHED_VALUES
373            .expect("cloning a HashDumper but DUMP_HASHED_VALUES wasn't specified");
374        HashDumper::new(self.hasher.clone(), prefix)
375    }
376}
377
378impl Drop for HashDumper {
379    fn drop(&mut self) {
380        eprintln!("HashDumper: Wrote {} bytes to {}...", self.written,
381                  self.filename);
382    }
383}
384
385impl Digest for HashDumper {
386    fn update(&mut self, data: &[u8]) {
387        self.hasher.update(data);
388        self.sink.write_all(data).unwrap();
389        self.written += data.len();
390    }
391    fn digest(&mut self, digest: &mut [u8]) -> Result<()> {
392        self.hasher.digest(digest)
393    }
394}
395
396impl io::Write for HashDumper {
397    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
398        self.update(buf);
399        Ok(buf.len())
400    }
401
402    fn flush(&mut self) -> io::Result<()> {
403        self.hasher.flush()
404    }
405}
406
407/// Hashes OpenPGP packets and related types.
408///
409/// Some OpenPGP data structures need to be hashed to be covered by
410/// OpenPGP signatures.  Hashing is often based on the serialized
411/// form, with some aspects fixed to ensure consistent results.  This
412/// trait implements hashing as specified by OpenPGP.
413///
414/// Most of the time it is not necessary to manually compute hashes.
415/// Instead, higher level functionality, like the streaming
416/// [`Verifier`], [`DetachedVerifier`], or [`Signature`'s verification
417/// functions] should be used, which handle the hashing internally.
418///
419///   [`Verifier`]: crate::parse::stream::Verifier
420///   [`DetachedVerifier`]: crate::parse::stream::DetachedVerifier
421///   [`Signature`'s verification functions]: crate::packet::Signature#verification-functions
422///
423/// This is a low-level mechanism.  See [`Signature`'s hashing
424/// functions] for how to hash compounds like (Key,UserID)-bindings.
425///
426///   [`Signature`'s hashing functions]: crate::packet::Signature#hashing-functions
427pub trait Hash {
428    /// Updates the given hash with this object.
429    fn hash(&self, hash: &mut Context) -> Result<()>;
430}
431
432impl Hash for UserID {
433    fn hash(&self, hash: &mut Context) -> Result<()> {
434        let len = self.value().len() as u32;
435
436        let mut header = [0; 5];
437        header[0] = 0xB4;
438        header[1..5].copy_from_slice(&len.to_be_bytes());
439
440        hash.update(&header);
441        hash.update(self.value());
442        Ok(())
443    }
444}
445
446impl Hash for UserAttribute {
447    fn hash(&self, hash: &mut Context) -> Result<()> {
448        let len = self.value().len() as u32;
449
450        let mut header = [0; 5];
451        header[0] = 0xD1;
452        header[1..5].copy_from_slice(&len.to_be_bytes());
453
454        hash.update(&header);
455        hash.update(self.value());
456        Ok(())
457    }
458}
459
460impl<P, R> Hash for Key<P, R>
461    where P: key::KeyParts,
462          R: key::KeyRole,
463{
464    fn hash(&self, hash: &mut Context) -> Result<()> {
465        match self {
466            Key::V4(k) => k.hash(hash),
467            Key::V6(k) => k.hash(hash),
468        }
469    }
470}
471
472/// Writes the appropriate hash prefix for keys.
473///
474/// In RFC9580, the way key packets are hashed depends not on the
475/// version of the key packet, but on the version of the signature
476/// that is being verified or generated.
477///
478/// See [Computing Signatures].
479///
480/// [Computing Signatures]: https://www.rfc-editor.org/rfc/rfc9580.html#name-computing-signatures
481fn write_key_hash_header(header: &mut Vec<u8>,
482                         public_len: usize,
483                         ctx: &Context)
484                         -> Result<()>
485{
486    match ctx.for_signature() {
487        None => Err(crate::Error::InvalidOperation(
488            "cannot hash key without knowing the signature version"
489                .into()).into()),
490
491        Some(3) | Some(4) => {
492            // When a version 4 signature is made over a key, the hash
493            // data starts with the octet 0x99, followed by a 2-octet
494            // length of the key, followed by the body of the key
495            // packet.
496
497            // Note: Reading RFC2440, this is also how keys should be
498            // hashed for version 3 signatures.
499
500            // Tag.
501            header.push(0x99);
502
503            // Length (2 bytes, big endian).
504            header.extend_from_slice(
505                &u16::try_from(public_len)?.to_be_bytes());
506
507            Ok(())
508        },
509
510        Some(6) => {
511            // When a version 6 signature is made over a key, the hash
512            // data starts with the [..] octet 0x9B, followed by a
513            // 4-octet length of the key, followed by the body of the
514            // key packet.
515
516            // Tag.
517            header.push(0x9b);
518
519            // Length (4 bytes, big endian).
520            header.extend_from_slice(
521                &u32::try_from(public_len)?.to_be_bytes());
522
523            Ok(())
524        },
525
526        Some(n) => Err(crate::Error::InvalidOperation(format!(
527            "don't know how to hash key for v{} signatures", n)
528        ).into()),
529    }
530}
531
532impl<P, R> Hash for Key4<P, R>
533    where P: key::KeyParts,
534          R: key::KeyRole,
535{
536    fn hash(&self, hash: &mut Context) -> Result<()> {
537        use crate::serialize::MarshalInto;
538
539        // We hash 9 bytes plus the MPIs.  But, the len doesn't
540        // include the tag (1 byte) or the length (2 bytes).
541        let len = (9 - 3) + self.mpis().serialized_len();
542
543        // Note: When making a v6 signature over the key, we hash a
544        // four octet length instead of a two octet length.  Reserve
545        // two extra bytes.
546        //
547        // XXX: Use SmallVec to avoid heap allocations.
548        let mut header: Vec<u8> = Vec::with_capacity(9 + 2);
549
550        // Write the appropriate header.  This depends on the version
551        // of the signature we hash the data for.
552        write_key_hash_header(&mut header, len, hash)?;
553
554        // Version.
555        header.push(4);
556
557        // Creation time.
558        let creation_time: u32 = self.creation_time_raw().into();
559        header.extend_from_slice(&creation_time.to_be_bytes());
560
561        // Algorithm.
562        header.push(self.pk_algo().into());
563
564        // Hash the header.
565        hash.update(&header[..]);
566
567        // MPIs.
568        self.mpis().hash(hash)?;
569
570        Ok(())
571    }
572}
573
574impl<P, R> Hash for Key6<P, R>
575    where P: key::KeyParts,
576          R: key::KeyRole,
577{
578    fn hash(&self, hash: &mut Context) -> Result<()> {
579        use crate::serialize::MarshalInto;
580
581        // We hash 15 bytes plus the MPIs.  But, the len doesn't
582        // include the tag (1 byte) or the length (4 bytes).
583        let len = (15 - 5) + self.mpis().serialized_len();
584
585        // XXX: Use SmallVec to avoid heap allocations.
586        let mut header: Vec<u8> = Vec::with_capacity(15);
587
588        // Write the appropriate header.  This depends on the version
589        // of the signature we hash the data for.
590        write_key_hash_header(&mut header, len, hash)?;
591
592        // Version.
593        header.push(6);
594
595        // Creation time.
596        let creation_time: u32 = self.creation_time_raw().into();
597        header.extend_from_slice(&creation_time.to_be_bytes());
598
599        // Algorithm.
600        header.push(self.pk_algo().into());
601
602        // Length of all MPIs.
603        header.extend_from_slice(
604            &(self.mpis().serialized_len() as u32).to_be_bytes());
605
606        // Hash the header.
607        hash.update(&header[..]);
608
609        // MPIs.
610        self.mpis().hash(hash)?;
611
612        Ok(())
613    }
614}
615
616impl Hash for Signature {
617    fn hash(&self, hash: &mut Context) -> Result<()> {
618        match self {
619            Signature::V3(sig) => sig.hash(hash),
620            Signature::V4(sig) => sig.hash(hash),
621            Signature::V6(sig) => sig.hash(hash),
622        }
623    }
624}
625
626impl Hash for Signature3 {
627    fn hash(&self, hash: &mut Context) -> Result<()> {
628        Self::hash_fields(hash, self)
629    }
630}
631
632impl Signature3 {
633    /// Hashes this signature.
634    ///
635    /// Because we need to call this from SignatureFields::hash, we
636    /// provide this as associated method.
637    fn hash_fields(hash: &mut Context, f: &signature::SignatureFields)
638                   -> Result<()>
639    {
640        let mut buffer = [0u8; 5];
641
642        // Signature type.
643        buffer[0] = u8::from(f.typ());
644
645        // Creation time.
646        let creation_time: u32 =
647            Timestamp::try_from(
648                f.signature_creation_time()
649                    .unwrap_or(std::time::UNIX_EPOCH))
650            .unwrap_or_else(|_| Timestamp::from(0))
651            .into();
652
653        buffer[1] = (creation_time >> 24) as u8;
654        buffer[2] = (creation_time >> 16) as u8;
655        buffer[3] = (creation_time >>  8) as u8;
656        buffer[4] = (creation_time      ) as u8;
657
658        hash.update(&buffer[..]);
659        Ok(())
660    }
661}
662
663impl Hash for Signature4 {
664    fn hash(&self, hash: &mut Context) -> Result<()> {
665        Self::hash_fields(hash, &self.fields)
666    }
667}
668
669impl Signature4 {
670    /// Hashes this signature.
671    ///
672    /// Because we need to call this from SignatureFields::hash, we
673    /// provide this as associated method.
674    fn hash_fields(mut hash: &mut Context, f: &signature::SignatureFields)
675                   -> Result<()>
676    {
677        use crate::serialize::{Marshal, MarshalInto};
678
679        // A version 4 signature packet is laid out as follows:
680        //
681        //   version - 1 byte                    \
682        //   type - 1 byte                        \
683        //   pk_algo - 1 byte                      \
684        //   hash_algo - 1 byte                      Included in the hash
685        //   hashed_area_len - 2 bytes (big endian)/
686        //   hashed_area                         _/
687        //   ...                                 <- Not included in the hash
688
689        let mut header = [0u8; 6];
690
691        // Version.
692        header[0] = 4;
693        header[1] = f.typ().into();
694        header[2] = f.pk_algo().into();
695        header[3] = f.hash_algo().into();
696
697        // The length of the hashed area, as a 16-bit big endian number.
698        let hashed_area_len = f.hashed_area().serialized_len();
699        header[4..6].copy_from_slice(&(hashed_area_len as u16).to_be_bytes());
700
701        hash.update(&header[..]);
702        f.hashed_area().serialize(&mut hash as &mut dyn Write)?;
703
704        // A version 4 signature trailer is:
705        //
706        //   version - 1 byte
707        //   0xFF (constant) - 1 byte
708        //   amount - 4 bytes (big endian)
709        //
710        // The amount field is the amount of hashed from this
711        // packet (this excludes the message content, and this
712        // trailer).
713        //
714        // See https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.4
715        let mut trailer = [0u8; 6];
716
717        trailer[0] = 4;
718        trailer[1] = 0xff;
719        // The signature packet's length, not including the previous
720        // two bytes and the length.
721        let len = (header.len() + hashed_area_len) as u32;
722        trailer[2..6].copy_from_slice(&len.to_be_bytes());
723
724        hash.update(&trailer[..]);
725
726        Ok(())
727    }
728}
729
730impl Hash for Signature6 {
731    fn hash(&self, hash: &mut Context) -> Result<()> {
732        Self::hash_fields(hash, &self.fields)
733    }
734}
735
736impl Signature6 {
737    fn hash_fields(mut hash: &mut Context, sig: &signature::SignatureFields)
738                   -> Result<()>
739    {
740        use crate::serialize::{Marshal, MarshalInto};
741
742        // A version 6 signature packet is laid out as follows:
743        //
744        //   version - 1 byte                    \
745        //   type - 1 byte                        \
746        //   pk_algo - 1 byte                      \
747        //   hash_algo - 1 byte                      Included in the hash
748        //   hashed_area_len - 4 bytes (big endian)/
749        //   hashed_area                         _/
750        //   ...                                 <- Not included in the hash
751
752        let mut header = [0u8; 8];
753
754        // Version.
755        header[0] = 6;
756        header[1] = sig.typ().into();
757        header[2] = sig.pk_algo().into();
758        header[3] = sig.hash_algo().into();
759
760        // The length of the hashed area, as a 32-bit big endian number.
761        let hashed_area_len = sig.hashed_area().serialized_len();
762        header[4..8].copy_from_slice(&(hashed_area_len as u32).to_be_bytes());
763
764        hash.update(&header[..]);
765
766        sig.hashed_area().serialize(&mut hash as &mut dyn Write)?;
767
768        // A version 6 signature trailer is:
769        //
770        //   version - 1 byte
771        //   0xFF (constant) - 1 byte
772        //   amount - 4 bytes (big endian)
773        //
774        // The amount field is the amount of hashed from this
775        // packet (this excludes the message content, and this
776        // trailer) modulo 2**32.
777        //
778        // See https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.4
779        let mut trailer = [0u8; 6];
780
781        trailer[0] = 6;
782        trailer[1] = 0xff;
783        // The signature packet's length, not including the previous
784        // two bytes and the length modulo 2**32.
785        let len = (header.len() + hashed_area_len) as u32;
786        trailer[2..6].copy_from_slice(&len.to_be_bytes());
787
788        hash.update(&trailer[..]);
789
790        Ok(())
791    }
792}
793
794impl Hash for signature::SignatureFields {
795    fn hash(&self, hash: &mut Context) -> Result<()> {
796        match self.version() {
797            3 => Signature3::hash_fields(hash, self),
798            4 => Signature4::hash_fields(hash, self),
799            6 => Signature6::hash_fields(hash, self),
800            n => Err(Error::InvalidOperation(format!(
801                "cannot hash a version {} signature packet", n)
802            ).into()),
803        }
804    }
805}
806
807impl Hash for signature::SignatureBuilder {
808    fn hash(&self, hash: &mut Context) -> Result<()> {
809        match self.sb_version {
810            signature::SBVersion::V4 {} =>
811                Signature4::hash_fields(hash, &self.fields),
812            signature::SBVersion::V6 { .. } =>
813                Signature6::hash_fields(hash, &self.fields),
814        }
815    }
816}
817
818/// Hashing-related functionality.
819///
820/// <a id="hashing-functions"></a>
821impl signature::SignatureBuilder {
822    /// Hashes this standalone signature.
823    pub fn hash_standalone(&self, hash: &mut Context)
824                           -> Result<()>
825    {
826        match self.typ() {
827            SignatureType::Standalone => (),
828            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
829        }
830
831        if let Some(salt) = self.prefix_salt() {
832            hash.update(salt);
833        }
834        self.hash(hash)?;
835        Ok(())
836    }
837
838    /// Hashes this timestamp signature.
839    pub fn hash_timestamp(&self, hash: &mut Context)
840                          -> Result<()>
841    {
842        match self.typ() {
843            SignatureType::Timestamp => (),
844            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
845        }
846
847
848        if let Some(salt) = self.prefix_salt() {
849            hash.update(salt);
850        }
851        self.hash(hash)?;
852        Ok(())
853    }
854
855    /// Hashes this direct key signature over the specified primary
856    /// key, and the primary key.
857    pub fn hash_direct_key<P>(&self, hash: &mut Context,
858                              key: &Key<P, key::PrimaryRole>)
859                              -> Result<()>
860        where P: key::KeyParts,
861    {
862        match self.typ() {
863            SignatureType::DirectKey => (),
864            SignatureType::KeyRevocation => (),
865            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
866        }
867
868        if let Some(salt) = self.prefix_salt() {
869            hash.update(salt);
870        }
871        key.hash(hash)?;
872        self.hash(hash)?;
873        Ok(())
874    }
875
876    /// Hashes this subkey binding over the specified primary key and
877    /// subkey, the primary key, and the subkey.
878    pub fn hash_subkey_binding<P, Q>(&self, hash: &mut Context,
879                                     key: &Key<P, key::PrimaryRole>,
880                                     subkey: &Key<Q, key::SubordinateRole>)
881                                     -> Result<()>
882        where P: key::KeyParts,
883              Q: key::KeyParts,
884    {
885        match self.typ() {
886            SignatureType::SubkeyBinding => (),
887            SignatureType::SubkeyRevocation => (),
888            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
889        }
890
891        if let Some(salt) = self.prefix_salt() {
892            hash.update(salt);
893        }
894        key.hash(hash)?;
895        subkey.hash(hash)?;
896        self.hash(hash)?;
897        Ok(())
898    }
899
900    /// Hashes this primary key binding over the specified primary key
901    /// and subkey, the primary key, and the subkey.
902    pub fn hash_primary_key_binding<P, Q>(&self, hash: &mut Context,
903                                          key: &Key<P, key::PrimaryRole>,
904                                          subkey: &Key<Q, key::SubordinateRole>)
905                                          -> Result<()>
906        where P: key::KeyParts,
907              Q: key::KeyParts,
908    {
909        match self.typ() {
910            SignatureType::PrimaryKeyBinding => (),
911            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
912        }
913
914        if let Some(salt) = self.prefix_salt() {
915            hash.update(salt);
916        }
917        key.hash(hash)?;
918        subkey.hash(hash)?;
919        self.hash(hash)?;
920        Ok(())
921    }
922
923    /// Hashes this user ID binding over the specified primary key and
924    /// user ID, the primary key, and the userid.
925    pub fn hash_userid_binding<P>(&self, hash: &mut Context,
926                                  key: &Key<P, key::PrimaryRole>,
927                                  userid: &UserID)
928                                  -> Result<()>
929        where P: key::KeyParts,
930    {
931        match self.typ() {
932            SignatureType::GenericCertification => (),
933            SignatureType::PersonaCertification => (),
934            SignatureType::CasualCertification => (),
935            SignatureType::PositiveCertification => (),
936            SignatureType::CertificationRevocation => (),
937            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
938        }
939
940        if let Some(salt) = self.prefix_salt() {
941            hash.update(salt);
942        }
943        key.hash(hash)?;
944        userid.hash(hash)?;
945        self.hash(hash)?;
946        Ok(())
947    }
948
949    /// Hashes this user attribute binding over the specified primary
950    /// key and user attribute, the primary key, and the user
951    /// attribute.
952    pub fn hash_user_attribute_binding<P>(
953        &self,
954        hash: &mut Context,
955        key: &Key<P, key::PrimaryRole>,
956        ua: &UserAttribute)
957        -> Result<()>
958        where P: key::KeyParts,
959    {
960        match self.typ() {
961            SignatureType::GenericCertification => (),
962            SignatureType::PersonaCertification => (),
963            SignatureType::CasualCertification => (),
964            SignatureType::PositiveCertification => (),
965            SignatureType::CertificationRevocation => (),
966            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
967        }
968
969        if let Some(salt) = self.prefix_salt() {
970            hash.update(salt);
971        }
972        key.hash(hash)?;
973        ua.hash(hash)?;
974        self.hash(hash)?;
975        Ok(())
976    }
977}
978
979/// Hashing-related functionality.
980///
981/// <a id="hashing-functions"></a>
982impl Signature {
983    /// Hashes this standalone signature.
984    pub fn hash_standalone(&self, hash: &mut Context)
985                           -> Result<()>
986    {
987        match self.typ() {
988            SignatureType::Standalone => (),
989            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
990        }
991
992        if let Some(salt) = self.salt() {
993            hash.update(salt);
994        }
995        self.hash(hash)?;
996        Ok(())
997    }
998
999    /// Hashes this timestamp signature.
1000    pub fn hash_timestamp(&self, hash: &mut Context)
1001                          -> Result<()>
1002    {
1003        match self.typ() {
1004            SignatureType::Timestamp => (),
1005            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
1006        }
1007
1008        if let Some(salt) = self.salt() {
1009            hash.update(salt);
1010        }
1011        self.hash(hash)?;
1012        Ok(())
1013    }
1014
1015    /// Hashes this direct key signature over the specified primary
1016    /// key, and the primary key.
1017    pub fn hash_direct_key<P>(&self, hash: &mut Context,
1018                              key: &Key<P, key::PrimaryRole>)
1019                              -> Result<()>
1020        where P: key::KeyParts,
1021    {
1022        match self.typ() {
1023            SignatureType::DirectKey => (),
1024            SignatureType::KeyRevocation => (),
1025            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
1026        }
1027
1028        if let Some(salt) = self.salt() {
1029            hash.update(salt);
1030        }
1031        key.hash(hash)?;
1032        self.hash(hash)?;
1033        Ok(())
1034    }
1035
1036    /// Hashes this subkey binding over the specified primary key and
1037    /// subkey, the primary key, and the subkey.
1038    pub fn hash_subkey_binding<P, Q>(&self, hash: &mut Context,
1039                                     key: &Key<P, key::PrimaryRole>,
1040                                     subkey: &Key<Q, key::SubordinateRole>)
1041                                     -> Result<()>
1042        where P: key::KeyParts,
1043              Q: key::KeyParts,
1044    {
1045        match self.typ() {
1046            SignatureType::SubkeyBinding => (),
1047            SignatureType::SubkeyRevocation => (),
1048            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
1049        }
1050
1051        if let Some(salt) = self.salt() {
1052            hash.update(salt);
1053        }
1054        key.hash(hash)?;
1055        subkey.hash(hash)?;
1056        self.hash(hash)?;
1057        Ok(())
1058    }
1059
1060    /// Hashes this primary key binding over the specified primary key
1061    /// and subkey, the primary key, and the subkey.
1062    pub fn hash_primary_key_binding<P, Q>(&self, hash: &mut Context,
1063                                          key: &Key<P, key::PrimaryRole>,
1064                                          subkey: &Key<Q, key::SubordinateRole>)
1065                                          -> Result<()>
1066        where P: key::KeyParts,
1067              Q: key::KeyParts,
1068    {
1069        match self.typ() {
1070            SignatureType::PrimaryKeyBinding => (),
1071            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
1072        }
1073
1074        if let Some(salt) = self.salt() {
1075            hash.update(salt);
1076        }
1077        key.hash(hash)?;
1078        subkey.hash(hash)?;
1079        self.hash(hash)?;
1080        Ok(())
1081    }
1082
1083    /// Hashes this user ID binding over the specified primary key and
1084    /// user ID, the primary key, and the userid.
1085    pub fn hash_userid_binding<P>(&self, hash: &mut Context,
1086                                  key: &Key<P, key::PrimaryRole>,
1087                                  userid: &UserID)
1088                                  -> Result<()>
1089        where P: key::KeyParts,
1090    {
1091        match self.typ() {
1092            SignatureType::GenericCertification => (),
1093            SignatureType::PersonaCertification => (),
1094            SignatureType::CasualCertification => (),
1095            SignatureType::PositiveCertification => (),
1096            SignatureType::CertificationRevocation => (),
1097            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
1098        }
1099
1100        if let Some(salt) = self.salt() {
1101            hash.update(salt);
1102        }
1103        key.hash(hash)?;
1104        userid.hash(hash)?;
1105        self.hash(hash)?;
1106        Ok(())
1107    }
1108
1109    /// Hashes this user attribute binding over the specified primary
1110    /// key and user attribute, the primary key, and the user
1111    /// attribute.
1112    pub fn hash_user_attribute_binding<P>(
1113        &self,
1114        hash: &mut Context,
1115        key: &Key<P, key::PrimaryRole>,
1116        ua: &UserAttribute)
1117        -> Result<()>
1118        where P: key::KeyParts,
1119    {
1120        match self.typ() {
1121            SignatureType::GenericCertification => (),
1122            SignatureType::PersonaCertification => (),
1123            SignatureType::CasualCertification => (),
1124            SignatureType::PositiveCertification => (),
1125            SignatureType::CertificationRevocation => (),
1126            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
1127        }
1128
1129        if let Some(salt) = self.salt() {
1130            hash.update(salt);
1131        }
1132        key.hash(hash)?;
1133        ua.hash(hash)?;
1134        self.hash(hash)?;
1135        Ok(())
1136    }
1137
1138    /// Hashes this user ID approval over the specified primary key
1139    /// and user ID.
1140    pub fn hash_userid_approval<P>(&self, hash: &mut Context,
1141                                  key: &Key<P, key::PrimaryRole>,
1142                                  userid: &UserID)
1143                                  -> Result<()>
1144        where P: key::KeyParts,
1145    {
1146        match self.typ() {
1147            SignatureType::CertificationApproval => (),
1148            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
1149        }
1150
1151        if let Some(salt) = self.salt() {
1152            hash.update(salt);
1153        }
1154        key.hash(hash)?;
1155        userid.hash(hash)?;
1156        self.hash(hash)?;
1157        Ok(())
1158    }
1159
1160    /// Hashes this user attribute approval over the specified primary
1161    /// key and user attribute.
1162    pub fn hash_user_attribute_approval<P>(
1163        &self,
1164        hash: &mut Context,
1165        key: &Key<P, key::PrimaryRole>,
1166        ua: &UserAttribute)
1167        -> Result<()>
1168        where P: key::KeyParts,
1169    {
1170        match self.typ() {
1171            SignatureType::CertificationApproval => (),
1172            _ => return Err(Error::UnsupportedSignatureType(self.typ()).into()),
1173        }
1174
1175        if let Some(salt) = self.salt() {
1176            hash.update(salt);
1177        }
1178        key.hash(hash)?;
1179        ua.hash(hash)?;
1180        self.hash(hash)?;
1181        Ok(())
1182    }
1183
1184    /// Hashes this signature for use in a Third-Party Confirmation
1185    /// signature.
1186    pub fn hash_for_confirmation(&self, hash: &mut Context)
1187                                 -> Result<()>
1188    {
1189        match self {
1190            Signature::V3(s) => s.hash_for_confirmation(hash),
1191            Signature::V4(s) => s.hash_for_confirmation(hash),
1192            Signature::V6(s) => s.hash_for_confirmation(hash),
1193        }
1194    }
1195}
1196
1197/// Hashing-related functionality.
1198///
1199/// <a id="hashing-functions"></a>
1200impl Signature4 {
1201    /// Hashes this signature for use in a Third-Party Confirmation
1202    /// signature.
1203    pub fn hash_for_confirmation(&self, hash: &mut Context)
1204                                 -> Result<()>
1205    {
1206        use crate::serialize::{Marshal, MarshalInto};
1207        // Section 5.2.4 of RFC4880:
1208        //
1209        // > When a signature is made over a Signature packet (type
1210        // > 0x50), the hash data starts with the octet 0x88, followed
1211        // > by the four-octet length of the signature, and then the
1212        // > body of the Signature packet.  (Note that this is an
1213        // > old-style packet header for a Signature packet with the
1214        // > length-of-length set to zero.)  The unhashed subpacket
1215        // > data of the Signature packet being hashed is not included
1216        // > in the hash, and the unhashed subpacket data length value
1217        // > is set to zero.
1218
1219        // This code assumes that the signature has been verified
1220        // prior to being confirmed, so it is well-formed.
1221        let mut body = vec![
1222            self.version(),
1223            self.typ().into(),
1224            self.pk_algo().into(),
1225            self.hash_algo().into(),
1226        ];
1227
1228        // The hashed area.
1229        let l = self.hashed_area().serialized_len()
1230             // Assumes well-formedness.
1231            .min(std::u16::MAX as usize);
1232        body.extend(&(l as u16).to_be_bytes());
1233         // Assumes well-formedness.
1234        self.hashed_area().serialize(&mut body)?;
1235
1236        // The unhashed area.
1237        body.extend(&[0, 0]); // Size replaced by zero.
1238        // Unhashed packets omitted.
1239
1240        body.extend(self.digest_prefix());
1241        self.mpis().serialize(&mut body)?;
1242
1243        hash.update(&[0x88]);
1244        hash.update(&(body.len() as u32).to_be_bytes());
1245        hash.update(&body);
1246        Ok(())
1247    }
1248}
1249
1250#[cfg(test)]
1251mod test {
1252    use crate::Cert;
1253    use crate::parse::Parse;
1254
1255    #[test]
1256    fn hash_verification() {
1257        fn check(cert: Cert) -> (usize, usize, usize) {
1258            let mut userid_sigs = 0;
1259            for (i, binding) in cert.userids().enumerate() {
1260                for selfsig in binding.self_signatures() {
1261                    let mut hash =
1262                        selfsig.hash_algo().context().unwrap()
1263                        .for_signature(selfsig.version());
1264                    selfsig.hash_userid_binding(
1265                        &mut hash,
1266                        cert.primary_key().key(),
1267                        binding.userid()).unwrap();
1268                    let h = hash.into_digest().unwrap();
1269                    if &h[..2] != selfsig.digest_prefix() {
1270                        eprintln!("{:?}: {:?} / {:?}",
1271                                  i, binding.userid(), selfsig);
1272                        eprintln!("  Hash: {:?}", h);
1273                    }
1274                    assert_eq!(&h[..2], selfsig.digest_prefix());
1275                    userid_sigs += 1;
1276                }
1277            }
1278            let mut ua_sigs = 0;
1279            for (i, a) in cert.user_attributes().enumerate()
1280            {
1281                for selfsig in a.self_signatures() {
1282                    let mut hash =
1283                        selfsig.hash_algo().context().unwrap()
1284                        .for_signature(selfsig.version());
1285                    selfsig.hash_user_attribute_binding(
1286                        &mut hash,
1287                        cert.primary_key().key(),
1288                        a.user_attribute()).unwrap();
1289                    let h = hash.into_digest().unwrap();
1290                    if &h[..2] != selfsig.digest_prefix() {
1291                        eprintln!("{:?}: {:?} / {:?}",
1292                                  i, a.user_attribute(), selfsig);
1293                        eprintln!("  Hash: {:?}", h);
1294                    }
1295                    assert_eq!(&h[..2], selfsig.digest_prefix());
1296                    ua_sigs += 1;
1297                }
1298            }
1299            let mut subkey_sigs = 0;
1300            for (i, binding) in cert.subkeys().enumerate() {
1301                for selfsig in binding.self_signatures() {
1302                    let mut hash =
1303                        selfsig.hash_algo().context().unwrap()
1304                        .for_signature(selfsig.version());
1305                    selfsig.hash_subkey_binding(
1306                        &mut hash,
1307                        cert.primary_key().key(),
1308                        binding.key()).unwrap();
1309                    let h = hash.into_digest().unwrap();
1310                    if &h[..2] != selfsig.digest_prefix() {
1311                        eprintln!("{:?}: {:?}", i, binding);
1312                        eprintln!("  Hash: {:?}", h);
1313                    }
1314                    assert_eq!(h[0], selfsig.digest_prefix()[0]);
1315                    assert_eq!(h[1], selfsig.digest_prefix()[1]);
1316                    subkey_sigs += 1;
1317                }
1318            }
1319
1320            (userid_sigs, ua_sigs, subkey_sigs)
1321        }
1322
1323        check(Cert::from_bytes(crate::tests::key("hash-algos/MD5.pgp")).unwrap());
1324        check(Cert::from_bytes(crate::tests::key("hash-algos/RipeMD160.pgp")).unwrap());
1325        check(Cert::from_bytes(crate::tests::key("hash-algos/SHA1.pgp")).unwrap());
1326        check(Cert::from_bytes(crate::tests::key("hash-algos/SHA224.pgp")).unwrap());
1327        check(Cert::from_bytes(crate::tests::key("hash-algos/SHA256.pgp")).unwrap());
1328        check(Cert::from_bytes(crate::tests::key("hash-algos/SHA384.pgp")).unwrap());
1329        check(Cert::from_bytes(crate::tests::key("hash-algos/SHA512.pgp")).unwrap());
1330        check(Cert::from_bytes(crate::tests::key("bannon-all-uids-subkeys.pgp")).unwrap());
1331        let (_userid_sigs, ua_sigs, _subkey_sigs)
1332            = check(Cert::from_bytes(crate::tests::key("dkg.pgp")).unwrap());
1333        assert!(ua_sigs > 0);
1334    }
1335}