1use 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
54const DUMP_HASHED_VALUES: Option<&str> = None;
57
58const 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
67const ASN1_OID_RIPEMD160: &[u8] = &[
69 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05,
70 0x00, 0x04, 0x14,
71];
72
73const ASN1_OID_SHA1: &[u8] = &[
75 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
76 0x00, 0x04, 0x14,
77];
78
79const 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
85const 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
91const 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
97const 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
103const 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
109const 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
115pub(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
133pub(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
145pub(crate) trait Digest: DynClone + Write + Send + Sync {
151 fn update(&mut self, data: &[u8]);
153
154 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#[derive(Clone)]
182pub struct Context {
183 algo: HashAlgorithm,
185
186 for_signature: Option<u8>,
189
190 ctx: Box<dyn Digest>,
192}
193
194impl Context {
195 pub fn algo(&self) -> HashAlgorithm {
197 self.algo
198 }
199
200 pub fn digest_size(&self) -> usize {
202 self.algo.digest_size()
203 .expect("we only create Contexts for known hash algos")
204 }
205
206 pub fn update(&mut self, data: &[u8]) {
208 self.ctx.update(data)
209 }
210
211 pub fn digest(&mut self, digest: &mut [u8]) -> Result<()>{
219 self.ctx.digest(digest)
220 }
221
222 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 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
248pub struct Builder(Context);
250
251impl Builder {
252 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 pub fn for_digest(self) -> Context {
263 self.0
264 }
265}
266
267
268impl HashAlgorithm {
269 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 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 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
407pub trait Hash {
428 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
472fn 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 header.push(0x99);
502
503 header.extend_from_slice(
505 &u16::try_from(public_len)?.to_be_bytes());
506
507 Ok(())
508 },
509
510 Some(6) => {
511 header.push(0x9b);
518
519 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 let len = (9 - 3) + self.mpis().serialized_len();
542
543 let mut header: Vec<u8> = Vec::with_capacity(9 + 2);
549
550 write_key_hash_header(&mut header, len, hash)?;
553
554 header.push(4);
556
557 let creation_time: u32 = self.creation_time_raw().into();
559 header.extend_from_slice(&creation_time.to_be_bytes());
560
561 header.push(self.pk_algo().into());
563
564 hash.update(&header[..]);
566
567 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 let len = (15 - 5) + self.mpis().serialized_len();
584
585 let mut header: Vec<u8> = Vec::with_capacity(15);
587
588 write_key_hash_header(&mut header, len, hash)?;
591
592 header.push(6);
594
595 let creation_time: u32 = self.creation_time_raw().into();
597 header.extend_from_slice(&creation_time.to_be_bytes());
598
599 header.push(self.pk_algo().into());
601
602 header.extend_from_slice(
604 &(self.mpis().serialized_len() as u32).to_be_bytes());
605
606 hash.update(&header[..]);
608
609 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 fn hash_fields(hash: &mut Context, f: &signature::SignatureFields)
638 -> Result<()>
639 {
640 let mut buffer = [0u8; 5];
641
642 buffer[0] = u8::from(f.typ());
644
645 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 fn hash_fields(mut hash: &mut Context, f: &signature::SignatureFields)
675 -> Result<()>
676 {
677 use crate::serialize::{Marshal, MarshalInto};
678
679 let mut header = [0u8; 6];
690
691 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 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 let mut trailer = [0u8; 6];
716
717 trailer[0] = 4;
718 trailer[1] = 0xff;
719 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 let mut header = [0u8; 8];
753
754 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 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 let mut trailer = [0u8; 6];
780
781 trailer[0] = 6;
782 trailer[1] = 0xff;
783 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
818impl signature::SignatureBuilder {
822 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 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 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 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 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 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 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
979impl Signature {
983 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 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 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 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 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 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 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 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 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 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
1197impl Signature4 {
1201 pub fn hash_for_confirmation(&self, hash: &mut Context)
1204 -> Result<()>
1205 {
1206 use crate::serialize::{Marshal, MarshalInto};
1207 let mut body = vec![
1222 self.version(),
1223 self.typ().into(),
1224 self.pk_algo().into(),
1225 self.hash_algo().into(),
1226 ];
1227
1228 let l = self.hashed_area().serialized_len()
1230 .min(std::u16::MAX as usize);
1232 body.extend(&(l as u16).to_be_bytes());
1233 self.hashed_area().serialize(&mut body)?;
1235
1236 body.extend(&[0, 0]); 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}