summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2022-09-29 18:02:43 +0200
committerJustus Winter <justus@sequoia-pgp.org>2022-09-29 18:04:36 +0200
commitf89695585459799981d83c0b6eecb13511490e56 (patch)
treeb493f6a8834ddb2a67e75d98abf1d7c820192847
parentdd14446c736745e9cac9f6076c91421dd7726fdb (diff)
ipc: Fix computing keygrips.
-rw-r--r--ipc/src/keygrip.rs74
-rw-r--r--ipc/tests/data/keys/alpha.pgp28
-rw-r--r--ipc/tests/data/keys/zulu.pgp23
3 files changed, 114 insertions, 11 deletions
diff --git a/ipc/src/keygrip.rs b/ipc/src/keygrip.rs
index 5bb2ee07..82b5f87f 100644
--- a/ipc/src/keygrip.rs
+++ b/ipc/src/keygrip.rs
@@ -92,9 +92,26 @@ impl Keygrip {
use self::PublicKey::*;
let mut hash = HashAlgorithm::SHA1.context().unwrap();
- fn hash_sexp_mpi(hash: &mut dyn hash::Digest, kind: char, prefix: &[u8],
- mpi: &MPI)
+ fn hash_sexp_mpi(hash: &mut dyn hash::Digest, kind: char, mpi: &MPI)
{
+ // gcrypt's MPIs can be signed or unsigned. Our MPIs are
+ // always unsigned (well, for us they are opaque byte
+ // strings, so the concept of a sign does not apply).
+ // Every now and then we need to pay attention to this, as
+ // gcrypt sometimes prepends a zero to prevent the most
+ // significant bit from being interpreted as a sign bit.
+ // Computing keygrips is one of these times.
+ let prefix = if mpi.value().get(0).map(|msb| msb & 0x80 > 0)
+ .unwrap_or(false)
+ {
+ // The most significant bit is set. Prepend a zero
+ // byte so that the MSB will not be interpreted as a
+ // sign bit.
+ &b"\x00"[..]
+ } else {
+ // The MSB is not set, no need to prepend anything.
+ &b""[..]
+ };
hash_sexp(hash, kind, prefix, mpi.value());
}
@@ -153,18 +170,16 @@ impl Keygrip {
},
&DSA { ref p, ref q, ref g, ref y } => {
- // Empirical evidence suggest that we need to prepend
- // a 0 to some parameters.
- hash_sexp_mpi(&mut hash, 'p', b"\x00", p);
- hash_sexp_mpi(&mut hash, 'q', b"\x00", q);
- hash_sexp_mpi(&mut hash, 'g', b"", g);
- hash_sexp_mpi(&mut hash, 'y', b"", y);
+ hash_sexp_mpi(&mut hash, 'p', p);
+ hash_sexp_mpi(&mut hash, 'q', q);
+ hash_sexp_mpi(&mut hash, 'g', g);
+ hash_sexp_mpi(&mut hash, 'y', y);
},
&ElGamal { ref p, ref g, ref y } => {
- hash_sexp_mpi(&mut hash, 'p', b"\x00", p);
- hash_sexp_mpi(&mut hash, 'g', b"", g);
- hash_sexp_mpi(&mut hash, 'y', b"", y);
+ hash_sexp_mpi(&mut hash, 'p', p);
+ hash_sexp_mpi(&mut hash, 'g', g);
+ hash_sexp_mpi(&mut hash, 'y', y);
},
&EdDSA { ref curve, ref q } => hash_ecc(&mut hash, curve, q)?,
@@ -405,4 +420,41 @@ mod tests {
}
}
}
+
+ /// Tests vectors from GPGME, using GnuPG as oracle.
+ #[test]
+ fn gpgme_keys() {
+ use std::collections::HashMap;
+ use openpgp::Fingerprint as FP;
+ use super::Keygrip as KG;
+ use openpgp::parse::Parse;
+
+ let keygrips: HashMap<FP, KG> = [
+ // alpha.pgp
+ ("A0FF4590BB6122EDEF6E3C542D727CC768697734".parse::<FP>().unwrap(),
+ "76F7E2B35832976B50A27A282D9B87E44577EB66".parse::<KG>().unwrap()),
+ ("3B3FBC948FE59301ED629EFB6AE6D7EE46A871F8".parse::<FP>().unwrap(),
+ "A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD".parse::<KG>().unwrap()),
+ // zulu.pgp
+ ("23FD347A419429BACCD5E72D6BC4778054ACD246".parse::<FP>().unwrap(),
+ "13CBE3758AFE42B5E5E2AE4CED27AFA455E3F87F".parse::<KG>().unwrap()),
+ ("2DCA5A1392DE06ED4FCB8C53EF9DC276A172C881".parse::<FP>().unwrap(),
+ "7A030357C0F253A5BBCD282FFC4E521B37558F5C".parse::<KG>().unwrap()),
+ ].iter().cloned().collect();
+
+ for (name, cert) in [
+ "alpha.pgp",
+ "zulu.pgp",
+ ]
+ .iter().map(|n| (n, openpgp::Cert::from_bytes(crate::tests::key(n)).unwrap()))
+ {
+ eprintln!("{}", name);
+ for key in cert.keys().map(|a| a.key()) {
+ let fp = key.fingerprint();
+ eprintln!("(sub)key: {}", fp);
+ assert_eq!(&Keygrip::of(key.mpis()).unwrap(),
+ keygrips.get(&fp).unwrap());
+ }
+ }
+ }
}
diff --git a/ipc/tests/data/keys/alpha.pgp b/ipc/tests/data/keys/alpha.pgp
new file mode 100644
index 00000000..6d5b3b4f
--- /dev/null
+++ b/ipc/tests/data/keys/alpha.pgp
@@ -0,0 +1,28 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQGiBDbjjp4RBAC2ZbFDX0wmJI8yLDYQdIiZeAuHLmfyHsqXaLGUMZtWiAvn/hNp
+ctwahmzKm5oXinHUvUkLOQ0s8rOlu15nhw4azc30rTP1LsIkn5zORNnFdgYC6RKy
+hOeim/63+/yGtdnTm49lVfaCqwsEmBCEkXaeWDGq+ie1b89J89T6n/JquwCgoQkj
+VeVGG+B/SzJ6+yifdHWQVkcD/RXDyLXX4+WHGP2aet51XlKojWGwsZmc9LPPYhwU
+/RcUO7ce1QQb0XFlUVFBhY0JQpM/ty/kNi+aGWFzigbQ+HAWZkUvA8+VIAVneN+p
++SHhGIyLTXKpAYTq46AwvllZ5Cpvf02Cp/+W1aVyA0qnBWMyeIxXmR9HOi6lxxn5
+cjajA/9VZufOXWqCXkBvz4Oy3Q5FbjQQ0/+ty8rDn8OTaiPi41FyUnEi6LO+qyBS
+09FjnZj++PkcRcXW99SNxmEJRY7MuNHt5wIvEH2jNEOJ9lszzZFBDbuwsjXHK35+
+lPbGEy69xCP26iEafysKKbRXJhE1C+tk8SnK+Gm62sivmK/5arQpQWxwaGEgVGVz
+dCAoZGVtbyBrZXkpIDxhbHBoYUBleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOOngML
+CgMDFQMCAxYCAQIXgAAKCRAtcnzHaGl3NDl4AKCBLmRplv/8ZfSqep5IjqEAuaXv
+WwCgl6NEzT+/WewPTGcwZY+pLkycLv20EEFsaWNlIChkZW1vIGtleSmIVQQTEQIA
+FQUCNuO2qwMLCgMDFQMCAxYCAQIXgAAKCRAtcnzHaGl3NCeMAJ9MeUVrago5Jc6P
+dwdeN5OMwby37QCghW65cZTQlD1bBlIq/QM8bz9AN4G0J0FsZmEgVGVzdCAoZGVt
+byBrZXkpIDxhbGZhQGV4YW1wbGUubmV0PohVBBMRAgAVBQI247hYAwsKAwMVAwID
+FgIBAheAAAoJEC1yfMdoaXc0t8IAoJPwa6j+Vm5Vi3Nvuo8JZri4PJ/DAJ9dqbma
+JdB8FdJnHfGh1rXK3y/JcrkBDQQ2448PEAQAnI3XH1f0uyN9fZnw72zsHMw706g7
+EW29nD4UDQG4OzRZViSrUa5n39eI7QrfTO+1meVvs0y8F/PvFst5jH68rPLnGSrX
+z4sTl1T4cop1FBkquvCAKwPLy0lE7jjtCyItOSwIOo8xoTfY4JEEXmcqsbm+KHv9
+yYSF/YK4Cf7bIzcAAwcD/Rnl5jKxoucDA96pD2829TKsLFQSau+Xiy8bvOSSDdly
+ABsOkNBSaeKO3eAQEKgDM7dzjVNTnAlpQ0EQ8Y9Z8pxOWYEQYlaMrnRBC4DZ2Iad
+zEhLlIOz5BVp/jfhrr8oVVBwKZXsrz9PZLz+e4Yn+siUUvlei9boD9L2ZgSOHakP
+iEYEGBECAAYFAjbjjw8ACgkQLXJ8x2hpdzQgqQCfcDXmD8uNVdKg/C9vqI3JSndq
+knsAnRxzVeHi/iJ73OCKtvFrHbV9Gogq
+=sBZo
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/ipc/tests/data/keys/zulu.pgp b/ipc/tests/data/keys/zulu.pgp
new file mode 100644
index 00000000..b1811ced
--- /dev/null
+++ b/ipc/tests/data/keys/zulu.pgp
@@ -0,0 +1,23 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQGiBDbjtcsRBACBDJOGX9C/xxCVZNP6OHz6cL5vM3PimUAhV+9HAVVPQViTnFKr
+kYPSQyRfWzjOU8RO1Tp5CHz747oOb6j9P74yH1uy78yFg4UuhXBWinhuCKKq4IIW
+wJkCKBFr1U8fu8a6Y6NcjqiDA0KmGRJrMPmXenXkJpFGHG78rUvNi9IMfwCgugzN
+ILh/3XZCZU+BUPYeXL+nUAEEAIDXZhj1vFXHgi9lmijKDjJocEBoamN/taQy6Ox1
+RRD6HtfAPY5TER1n7xm9hMzE+Ov1IKpH/E872Rha1qu1v7eOa6eTuNWF0NvmSR95
+5freRsNuR8JNIb6StI2ER9pzBUfjykC9pg2wPeC7wpQJIF9TF+Ja1BvG2I+ha2xJ
+786AA/sHEUvAOsc58YbPlbIPyp2JdEHvXTRT2NISVRuTMQsg8vV99nMYR2CUh270
+uPyy2xZaD/kYcJ9/1ngY7C9pbbNWoV70PkEMO/qj67OIViWVPzUhIdURorbpGhuc
+3oBzUxOgial7IbISPRItDgg2oZoY4hqyQNx8Cj2ZZAzDpM2vCrQnWnVsdSBUZXN0
+IChkZW1vIGtleSkgPHp1bHVAZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjtcsDCwoD
+AxUDAgMWAgECF4AACgkQa8R3gFSs0kZA6wCeJUyRzuFbsZ0uQulvpgOIRTLTKscA
+oLd3InVEj20peTUQ5b2NOimSXnKxuQENBDbjtfIQBADMfPDBQoMzv52Mmjb8SdaY
+KKNzqDd9K1oY2hcMSi+LcHag+KJFOyKBf3SoHmcU/vCEN+LyTgljYSKDmEf4wZ2+
+eLfqFgSdBJp2xm55ih+9CHXg3dXx9SbHiGJCIxfJaIsnNz3VmJGPDDjBlaf/hjl/
+7SZvR+MJpVLFPGjj7uOhTwADBQP/Sgv0abeCXVdVXwGEmhdV0VDo833IQRdRu1yt
++QLnWRMGTY1oQapsH6QLwYSZfDJlxbsBA3tfqKStpRSbdGNNTsK+RIehsGddi3sW
+GplRGm5Xt5KpkY/mc/tLFaYJNMqAgfWQcKlZHBp7EoWMgiRiDJUWq0TH1wRDoPaR
+c+H5GdqIRgQYEQIABgUCNuO18gAKCRBrxHeAVKzSRn1jAKC5Gp5sHM9sWdZeM6qf
+u54F2OwMQACfTjYXfpMApAROPkjhhFNqH0d8x5E=
+=Ch/w
+-----END PGP PUBLIC KEY BLOCK-----