use crate::crypto::hash::Digest;
use crate::Result;
pub(crate) fn build() -> sha1collisiondetection::Sha1CD {
sha1collisiondetection::Builder::default()
.detect_collisions(true)
.use_ubc(true)
.safe_hash(true)
.build()
}
impl Digest for sha1collisiondetection::Sha1CD {
fn algo(&self) -> crate::types::HashAlgorithm {
crate::types::HashAlgorithm::SHA1
}
fn digest_size(&self) -> usize {
20
}
fn update(&mut self, data: &[u8]) {
sha1collisiondetection::Sha1CD::update(self, data);
}
fn digest(&mut self, digest: &mut [u8]) -> Result<()> {
let mut d = sha1collisiondetection::Output::default();
let r = self.finalize_into_dirty_cd(&mut d);
self.reset();
let l = digest.len().min(d.len());
digest[..l].copy_from_slice(&d[..l]);
r.map_err(Into::into)
}
}
#[cfg(test)]
mod test {
use crate::*;
use crate::parse::{Parse, stream::*};
use crate::policy::StandardPolicy;
#[test]
fn shambles() -> Result<()> {
let alice =
PacketPile::from_bytes(crate::tests::key("sha-mbles.alice.asc"))?;
let bob =
PacketPile::from_bytes(crate::tests::key("sha-mbles.bob.asc"))?;
let ca_keyid: KeyID = "AFBB 1FED 6951 A956".parse()?;
assert_eq!(alice.children().count(), 4);
assert_eq!(bob.children().count(), 7);
let alice_sha1_fingerprint: Fingerprint =
"43CD 5C5B 04FF 5742 FA14 1ABC A9D7 55A9 6354 8C78".parse()?;
let bob_sha1_fingerprint: Fingerprint =
"C6BF E2FC BBE5 1A89 2BEB 7798 1233 D4CC 61DB D9C4".parse()?;
let alice_sha1cd_fingerprint: Fingerprint =
"4D84 B08A A181 21DB D79E EA05 9CD0 8D5B 1680 87E2".parse()?;
let bob_sha1cd_fingerprint: Fingerprint =
"6434 B04B 4648 BA41 15BD C5C2 B67A DB26 6F74 DF89".parse()?;
assert_eq!(bob.path_ref(&[6]).unwrap(), alice.path_ref(&[3]).unwrap());
match bob.path_ref(&[6]).unwrap() {
Packet::Signature(s) => {
assert_eq!(s.issuers().next().unwrap(), &ca_keyid);
},
o => panic!("unexpected packet: {:?}", o),
}
let alice = Cert::from_packets(alice.into_children())?;
let bob = Cert::from_packets(bob.into_children())?;
assert_eq!(alice.bad_signatures().count(), 1);
assert_eq!(bob.bad_signatures().count(), 2);
assert!(alice.fingerprint() != alice_sha1_fingerprint);
assert_eq!(alice.fingerprint(), alice_sha1cd_fingerprint);
assert!(bob.fingerprint() != bob_sha1_fingerprint);
assert_eq!(bob.fingerprint(), bob_sha1cd_fingerprint);
Ok(())
}
#[test]
fn shattered() -> Result<()> {
let cert =
Cert::from_bytes(crate::tests::key("testy-new.pgp"))?;
let shattered_1 = crate::tests::message("shattered-1.pdf");
let shattered_1_sig = crate::tests::message("shattered-1.pdf.sig");
let shattered_2 = crate::tests::message("shattered-2.pdf");
let shattered_2_sig = crate::tests::message("shattered-2.pdf.sig");
let mut p = StandardPolicy::new();
p.accept_hash(types::HashAlgorithm::SHA1);
struct Helper(Cert);
impl VerificationHelper for Helper {
fn get_certs(&mut self, _ids: &[KeyHandle]) -> Result<Vec<Cert>> {
Ok(vec![self.0.clone()])
}
fn check(&mut self, structure: MessageStructure) -> Result<()> {
if let MessageLayer::SignatureGroup { results } =
structure.into_iter().next().unwrap()
{
assert_eq!(results.len(), 1);
assert!(results[0].is_err());
} else {
unreachable!()
}
Ok(())
}
}
let h = Helper(cert.clone());
let mut v = DetachedVerifierBuilder::from_bytes(shattered_1_sig)?
.with_policy(&p, None, h)?;
v.verify_bytes(shattered_1)?;
let h = Helper(cert);
let mut v = DetachedVerifierBuilder::from_bytes(shattered_2_sig)?
.with_policy(&p, None, h)?;
v.verify_bytes(shattered_2)?;
Ok(())
}
}