diff --git a/data/messages/shattered-1.pdf b/data/messages/shattered-1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ba9aaa145ccd24ef760cf31c74d8f7ca1a2e47b0 Binary files /dev/null and b/data/messages/shattered-1.pdf differ diff --git a/data/messages/shattered-1.pdf.asc b/data/messages/shattered-1.pdf.asc new file mode 100644 index 0000000000000000000000000000000000000000..28711ebeb7e9783fcc1a353b769d969777da100d --- /dev/null +++ b/data/messages/shattered-1.pdf.asc @@ -0,0 +1,14 @@ +-----BEGIN PGP SIGNATURE----- + +wsDzBAABAgAdFiEE0aZuGiOxgsmYD3iM+/zIKgFeczAFAl+uh1wACgkQ+/zIKgFe +czBqzAv9G9v98so++R88YSVMTGbfzq4fSh4C/DkfZCT9+j6H1IpYfjfouFQNtTE7 +0ACiusd0cTxBdRKOqsbh9EW3yfv77+8XU+sNY0QZ2UgfbEW1USAP4BgACMkpSu5X +mlcE65jw7bhfdnnNsypOKORpH/uyLSMTAvBj3rrzFyikDjJwmSyLdJocjCawkr0U +aOQfDZfJVXhRCj9oXrRW2LBdB7HsLqwFvt/EIct8FYnTxriV8+xuVaihCbX357uE +NXqbT8x07xMAUws/iwrHptmPZP6sz4+bdekMXAMncY4hBR8J0NDh6vpq8yYRylpa +ebJ8mLGhujJPIcU12VOMimGE7+zpAwmlJgPQqdZsjS1ZuvQ/BS37hRIvdUTZljff +EXqqJq3SwZOvdvyRzTk3vciZhEzJ2aLSj0A4PY/k/6fZEdY3ZHRKdWP3btOU6GNF +b+BXPE/eNerLy0Y5BgMOKfsOaqPGz4bDJTNv83gsbYPyFXvhb0hTESRgyNeGC+rC +WOUcC767 +=Ox9v +-----END PGP SIGNATURE----- diff --git a/data/messages/shattered-2.pdf b/data/messages/shattered-2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b621eeccd5c7edac9b7dcba35a8d5afd075e24f2 Binary files /dev/null and b/data/messages/shattered-2.pdf differ diff --git a/data/messages/shattered-2.pdf.asc b/data/messages/shattered-2.pdf.asc new file mode 100644 index 0000000000000000000000000000000000000000..4faa7a85d050d84507f3a35f000392da67b27006 --- /dev/null +++ b/data/messages/shattered-2.pdf.asc @@ -0,0 +1,14 @@ +-----BEGIN PGP SIGNATURE----- + +wsDzBAABAgAdFiEE0aZuGiOxgsmYD3iM+/zIKgFeczAFAl+uh3MACgkQ+/zIKgFe +czCqAgwAtNZWYfg3S2kytvaBjxW9nExtj5/Iacuxv08xUVdnJ8S+KZh0i3WXy4wo +d0ZhN2WlcoTY71Eof1QEvoSyoWJ1LaK9xsRiKoQCj0+NFXCzUzLoB08iYh+7hc9c +q0jn7m6Sp8BwKQ3fsE/ytR4bQPgWOY2FFRv4V6YUcmt5HdBzcIUyztyWTFIXt50S +68N4kcF+3qB51eIwvKPkKFLIOrIc5Ds1IgMjlu2jMZzsDkFQDr4rJ9efUMjuDGya +8fy5oCEtpxXcM9KUtiZSxMoKjisrBMFQV32rxu/W7EfvN280rgqz0G9j+8Ha0UX4 +xQz+/ygkmf3aAHW4cx2iQC72UfuvfqW/07XRa7HDFYwfP/kr50LtyhxfV91nKdIo +i3pFKmM6DH9j+bDfeAvLhvRDBgjuhLQCbEu7pVEeLWoISh7F2TE2xz0XUz1YPQv7 +p2Ma6X7buWPGX1Z9+26tdaU/7YWX33+PZ6QXDzmHCGba14Ya36RqE99tobislcIT +q4Z/4b0w +=p4TW +-----END PGP SIGNATURE----- diff --git a/src/tests/hashes.rs b/src/tests/hashes.rs index f099616953b0dadd81c37cd35d7ad87aa134874f..e8bc2033473139f0dfa90cd127a81eb22a6446ff 100644 --- a/src/tests/hashes.rs +++ b/src/tests/hashes.rs @@ -10,6 +10,8 @@ use crate::{ }, }; +mod shattered; + pub fn schedule(report: &mut Report) -> Result<()> { use openpgp::types::HashAlgorithm::*; @@ -26,6 +28,7 @@ pub fn schedule(report: &mut Report) -> Result<()> { openpgp::Cert::from_bytes(data::certificate("bob-secret.pgp"))?, b"Hello, world!".to_vec().into_boxed_slice(), hash)?)); } + report.add(Box::new(shattered::Shattered::new()?)); Ok(()) } diff --git a/src/tests/hashes/shattered.rs b/src/tests/hashes/shattered.rs new file mode 100644 index 0000000000000000000000000000000000000000..f22cf64cf43f6f3daba16cad46bfc6b9a5e30fb2 --- /dev/null +++ b/src/tests/hashes/shattered.rs @@ -0,0 +1,77 @@ +use crate::{ + Data, + OpenPGP, + Result, + data, + tests::{ + ConsumerTest, + Expectation, + Test, + TestMatrix, + }, +}; + +/// Explores whether SHA-1 signatures over colliding files are +/// considered valid. +pub struct Shattered { +} + +impl Shattered { + pub fn new() -> Result { + Ok(Shattered { + }) + } +} + +impl Test for Shattered { + fn title(&self) -> String { + "Signature over the shattered collision".into() + } + + fn description(&self) -> String { + "

This tests whether detached signatures using SHA-1 over + the collision from the paper The first collision for full + SHA-1 are considered valid.

" + .into() + } + + fn artifacts(&self) -> Vec<(String, Data)> { + vec![("Certificate".into(), data::certificate("bob.pgp").into())] + } + + + fn run(&self, implementations: &[Box]) + -> Result { + ConsumerTest::run(self, implementations) + } +} + +impl ConsumerTest for Shattered { + fn produce(&self) -> Result)>> { + Ok(vec![ + ("SIG-1 over PDF-1".into(), + data::message("shattered-1.pdf.asc").into(), + Some(Err("Attack must be mitigated".into()))), + ("SIG-1 over PDF-2".into(), + data::message("shattered-1.pdf.asc").into(), + Some(Err("Attack must be mitigated".into()))), + ("SIG-2 over PDF-1".into(), + data::message("shattered-2.pdf.asc").into(), + Some(Err("Attack must be mitigated".into()))), + ("SIG-2 over PDF-2".into(), + data::message("shattered-2.pdf.asc").into(), + Some(Err("Attack must be mitigated".into()))), + ]) + + } + + fn consume(&self, i: usize, pgp: &mut dyn OpenPGP, artifact: &[u8]) + -> Result { + let message = match i { + 0 | 2 => data::message("shattered-1.pdf"), + 1 | 3 => data::message("shattered-2.pdf"), + _ => unreachable!(), + }; + pgp.verify_detached(data::certificate("bob.pgp"), message, artifact) + } +}