summaryrefslogtreecommitdiffstats
path: root/autocrypt
diff options
context:
space:
mode:
authorWiktor Kwapisiewicz <wiktor@metacode.biz>2020-03-25 11:18:06 +0100
committerWiktor Kwapisiewicz <wiktor@metacode.biz>2020-03-27 11:24:49 +0100
commitd6cf1330eb3d22e8e9e82bc5fef4490c271521d6 (patch)
tree0cd649ad7d7fa35008379dc93c48498b06800657 /autocrypt
parenta41e4725c1d9096575986bad5e4ac81cb61e9a17 (diff)
autocrypt: Add ability to parse Autocrypt-Gossip headers.
- Refactor parsing of Autocrypt headers into own function. - Key gossip uses the same format as specified in the spec [0]. - Add tests from attached ticket. - Fixes #394. [0]: https://autocrypt.org/level1.html#key-gossip
Diffstat (limited to 'autocrypt')
-rw-r--r--autocrypt/src/lib.rs193
1 files changed, 155 insertions, 38 deletions
diff --git a/autocrypt/src/lib.rs b/autocrypt/src/lib.rs
index 6caa5a21..f336be9a 100644
--- a/autocrypt/src/lib.rs
+++ b/autocrypt/src/lib.rs
@@ -231,56 +231,70 @@ impl AutocryptHeaders {
}
const AUTOCRYPT : &str = "Autocrypt: ";
+ const AUTOCRYPT_GOSSIP : &str = "Autocrypt-Gossip: ";
const FROM : &str = "From: ";
if line.starts_with(FROM) {
headers.from
= Some(line[FROM.len()..].trim_matches(' ').into());
- } else if line.starts_with(AUTOCRYPT) {
- let ac_value = &line[AUTOCRYPT.len()..];
+ } else if line.starts_with(AUTOCRYPT) || line.starts_with(AUTOCRYPT_GOSSIP) {
+ headers.headers.push(Self::decode_autocrypt_like_header(&line));
+ }
+ }
- let mut header = AutocryptHeader::empty(
- AutocryptHeaderType::Sender);
+ return Ok(headers)
+ }
- for pair in ac_value.split(';') {
- let pair = pair
- .splitn(2, |c| c == '=')
- .collect::<Vec<&str>>();
+ /// Decode header that has the same format as the Autocrypt header.
+ /// This function should be called only on "Autocrypt" or "Autocrypt-Gossip"
+ /// headers.
+ fn decode_autocrypt_like_header(line: &str) -> AutocryptHeader {
+ let mut parts = line.splitn(2, ": ");
+ let header_name = parts.next().unwrap();
+ let ac_value = parts.next().unwrap();
+
+ let header_type = match header_name {
+ "Autocrypt" => AutocryptHeaderType::Sender,
+ "Autocrypt-Gossip" => AutocryptHeaderType::Gossip,
+ other => panic!("Expected Autocrypt header but found: {}", other)
+ };
- let (key, value) : (String, String) = if pair.len() == 1 {
- // No value...
- (pair[0].trim_matches(' ').into(), "".into())
- } else {
- (pair[0].trim_matches(' ').into(),
- pair[1].trim_matches(' ').into())
- };
-
- if key == "keydata" {
- if let Ok(decoded) = base64::decode(
- &value.replace(" ", "")[..]) {
- if let Ok(cert) = Cert::from_bytes(&decoded[..]) {
- header.key = Some(cert);
- }
- }
- }
+ let mut header = AutocryptHeader::empty(header_type);
- let critical = key.len() >= 1 && &key[0..1] == "_";
- header.attributes.push(Attribute {
- critical: critical,
- key: if critical {
- key[1..].to_string()
- } else {
- key
- },
- value,
- });
- }
+ for pair in ac_value.split(';') {
+ let pair = pair
+ .splitn(2, |c| c == '=')
+ .collect::<Vec<&str>>();
- headers.headers.push(header);
+ let (key, value) : (String, String) = if pair.len() == 1 {
+ // No value...
+ (pair[0].trim_matches(' ').into(), "".into())
+ } else {
+ (pair[0].trim_matches(' ').into(),
+ pair[1].trim_matches(' ').into())
+ };
+
+ if key == "keydata" {
+ if let Ok(decoded) = base64::decode(
+ &value.replace(" ", "")[..]) {
+ if let Ok(cert) = Cert::from_bytes(&decoded[..]) {
+ header.key = Some(cert);
+ }
+ }
}
- }
- return Ok(headers)
+ let critical = key.len() >= 1 && &key[0..1] == "_";
+ header.attributes.push(Attribute {
+ critical,
+ key: if critical {
+ key[1..].to_string()
+ } else {
+ key
+ },
+ value,
+ });
+ }
+ header
}
/// Parses an autocrypt header.
@@ -905,6 +919,7 @@ In the light of the Efail vulnerability I am asking myself if it's
// We expect exactly one Autocrypt header.
assert_eq!(ac.headers.len(), 1);
+ assert_eq!(ac.headers[0].header_type, AutocryptHeaderType::Sender);
assert_eq!(ac.headers[0].get("addr").unwrap().value,
"holger@merlinux.eu");
@@ -969,6 +984,108 @@ In the light of the Efail vulnerability I am asking myself if it's
assert_eq!(ac, ac2);
}
+
+ #[test]
+ fn decode_gossip() {
+ const GOSSIP : &'static [u8] = b"\
+Autocrypt-Gossip: addr=dkg@fifthhorseman.net; keydata=
+ mDMEXEK/AhYJKwYBBAHaRw8BAQdAr/gSROcn+6m8ijTN0DV9AahoHGafy52RRkhCZVwxhEe0
+ K0RhbmllbCBLYWhuIEdpbGxtb3IgPGRrZ0BmaWZ0aGhvcnNlbWFuLm5ldD6ImQQTFggAQQIb
+ AQUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgBYhBMS8Lds4zOlkhevpwvIGkReQOOXG
+ BQJcQsbzAhkBAAoJEPIGkReQOOXG4fkBAO1joRxqAZY57PjdzGieXLpluk9RkWa3ufkt3YUV
+ EpH/AP9c+pgIxtyW+FwMQRjlqljuj8amdN4zuEqaCy4hhz/1DbgzBFxCv4sWCSsGAQQB2kcP
+ AQEHQERSZxSPmgtdw6nNu7uxY7bzb9TnPrGAOp9kClBLRwGfiPUEGBYIACYWIQTEvC3bOMzp
+ ZIXr6cLyBpEXkDjlxgUCXEK/iwIbAgUJAeEzgACBCRDyBpEXkDjlxnYgBBkWCAAdFiEEyQ5t
+ NiAKG5IqFQnndhgZZSmuX/gFAlxCv4sACgkQdhgZZSmuX/iVWgD/fCU4ONzgy8w8UCHGmrmI
+ ZfDvdhg512NIBfx+Mz9ls5kA/Rq97vz4z48MFuBdCuu0W/fVqVjnY7LN5n+CQJwGC0MIA7QA
+ /RyY7Sz2gFIOcrns0RpoHr+3WI+won3xCD8+sVXSHZvCAP98HCjDnw/b0lGuCR7coTXKLIM4
+ 4/LFWgXAdZjm1wjODbg4BFxCv50SCisGAQQBl1UBBQEBB0BG4iXnHX/fs35NWKMWQTQoRI7o
+ iAUt0wJHFFJbomxXbAMBCAeIfgQYFggAJhYhBMS8Lds4zOlkhevpwvIGkReQOOXGBQJcQr+d
+ AhsMBQkB4TOAAAoJEPIGkReQOOXGe/cBAPlek5d9xzcXUn/DkY6jKmxe26CTws3ZkbK6Aa5E
+ y/qKAP0VuPQSCRxA7RKfcB/XrEphfUFkraL06Xn/xGwJ+D0hCw==
+Autocrypt-Gossip: addr=neal@walfield.org; keydata=
+ mQHhBFUjmukBDqCpmVI7Ve+2xTFSTG+mXMFHml63/Yai2nqxBk9gBfQfRFIjMt74whGG3LA1
+ ccH2vtsUMbm+F9d+hmzfiErloOVeamfSTCXVPHl4vuVRGXoH5tL09bbmLE7cidDj49GelOxb
+ fqHKVw3+Fd2zLlQdiaWYJ7CdRDZOT22zEx+6n59/gO5WNnymaib+nXWAbXJ+pU7fzHU4PlhD
+ XT/FfV2mzyQg6AiToColG5/CfOBp+WP6pAU4eNIxIlKYxzLnyAPUy+nuqojTJ+Ni16Jve/hp
+ KM7G1TGAzjzdC5zSVMELi/5kdldCD9Hg7sqw6RPlxbH52bryenYfLyfIaInHCHKmqWRAu3fx
+ McZ65qo8khYrzZngYewVAafRi/GSZmKxzntmP0GYziceGsbF8dEFF1scfebGKuDqtBhQ0MMu
+ xTbTLg1+KKN8rhqWTeikrt0JPbD1viaVX7Z7G12fZ8lBU4sjd3HGO5EK+3Cs8bjLXbzb8UIz
+ 7u28u7DqVQB4jhgh+IXyZzaeELV9KPr5IVNjT9K9gX6JJlVSi5BnxUVY0pEhtKiiLO6PCC2N
+ PenWkWpp3UEZ5ILnLhlmPe7ICiBCK1IQtNHEAfDalKO1t/gWKi0JlOqv2j9ER68AEQEAAbQk
+ TmVhbCBILiBXYWxmaWVsZCA8bmVhbEB3YWxmaWVsZC5vcmc+iQIoBBMBCgA+AhsDCAsJCAcN
+ DAsKBRUKCQgLAh4BAheAAhkBFiEEjxd3cRijPdqbpI5iqssyQ2MAUtkFAlywiLoFCQtPVNEA
+ CgkQqssyQ2MAUtnvpg6cDmDQGM+osZ4qF8R2e0NUKzpi3Zu5ti9eee3XUmUKYfwD4Mp1xpuc
+ +mmGsc86t0EaWy2b/4qFUnai1XTLsulnSaJ35+hf+dzVhWOosJN4gMo74RLpi3v/Tx7++dAo
+ +AHGUXqoaxSwfpyR0FLNEkgiesU3OIFuIep0okXD3e9hVMn2bkgY/xtEneWxLuU7LrcMQcwk
+ NeqT2rr5jvJWrPb7AfiWGAnQomWVipAZP/RW/ah3jtyNFKKYJsshvdYmdsZ1K59e1QoquLPb
+ vZ40YL1E1DuZjGq+b5daIxTNd4MRp6BpQ/kEY+xMa7qFGNlgcqNtwDICliaT/w5S8rZ/QUlp
+ kdGwikOy/ZYFAApfCSBqnWebc+Jh9JLR1o/0qhtPM/ab6Wv+vh3m6LEMuvKJadQraMIDE427
+ LaA3B3StEnEx6w5L/WRX0qinjEikZ3H/DNOHzp+rZsNGZkqm/Y11mQ1H6A493tXBnImZU2gA
+ g0o/8w3jyjbD6PzFVGFWQlT9Kmo5cvunJHx1Rycv2XJLhnyvF66T64dfKlrZMaWxafSO50rQ
+ +QtIt91l2ZepYc92Z8Urywcy3vb4jhG1oPRet37Z/ZTmPkSdCNBGNsWGw9Wc9liPIKdHuQEN
+ BFUjppYBCACnNVEkX+6074zvfHCgfOuiQ3j1VIFzGQEeHsbobHNfo3kO8EGGSHiYZVnzWrh2
+ UwUy2mrXEFvXseDDmJaaO/g/H/asB4J87OTXNILg4yXktvLfr8KaIONwkaqBHS2peImJ/gHz
+ YwGAkg2JtpuIYb76IdCb2SaRZJWq4AyyrtgjJN2AB1u5J3kFWKHWGOrMGsHsAzJ9HMNIJogM
+ z/O0qNuoOewP9z20W8xAUwxJjMZ+Rx1QPcdMsHHJ7VcPkhq/0AY/ko0y5iSjYz9ycp6bGXco
+ hmWlxlH5oSuPlTldo6E636S4BTALpFwu08rhiE4Dm0JN72Uc4N1uT+TsEZdd5JBVABEBAAGJ
+ Ay8EGAEKACYCGwIWIQSPF3dxGKM92pukjmKqyzJDYwBS2QUCXLCI3AUJC09JRgEpwF0gBBkB
+ CgAGBQJVI6aWAAoJEHIjtWZ44CUoppQH/3kEzoY+2kigIIjGCtyWjF3eV2vGBz4tTiSs3mC1
+ hCQ0OP9i1uintq9Gt+m05LlSTFuKu91Q0Y3ArCDANAbagDmS7RVShbINhPZX7I3CF/O89Tb3
+ DKDTCdaDhueOrmTpKX6J29c2o5TDbVIjGcjVMsvQQyM/o6/y7DXP8BdkyI/ewdsEt8uk9T4V
+ pZTBV1ig49980YzRaykpYFoOn0L+MXcf/8okApjtMehRIzNRejYT303w1R8XfQIKDWRRGDwQ
+ XO9eVSaiw+Z2EbE4oROkY5ImalD+sK4FYnsxnK4w3O74fGlYCd3Q2cAjSSfyVEqcjyuUog6W
+ gcmWeKMxCTLZpO8JEKrLMkNjAFLZZZoOniqm+87OELpGHg3/DgaXibZ91OA/FrW4JniOeax2
+ eZwoFiaMW98en1u7hA6uFKOKBGiBIOZOxESFOTSNf3AQGawUJRImZ7O4+p0sm7g37p5vVVLb
+ pcjZNZ+3MPtUkX/suZIqiMJ0khmo6x5Ce0QwjegKXRDu1xXTywnVlzb77OGciP63J0jqpUyf
+ 1haEb0rm4+OEDyB18PjG/8RSqUXHKsg26HlPmvYeeyRhcFAKf1yq9Ozaw0FGZ+UIUb630PA9
+ DtewUsqnKcRo2TpYl67sxc+7eRvgslK76Zvvih5la7SQBgSLVByRhcIIVxVnvDX0cvoO16Hf
+ xLCZlTlzTi0np44yvqlR+SmzBq8vgJXrvAkVpHlGckdupFDKrA9Awy9aWYO4WSpX8nLdAkf8
+ VvHee+rxYS+RBOs6j4IG4PiHydvTWasNUcnpVxsQ0/GKRzNkPg2VdW2IrU6hFgnt0U5diq+3
+ KqFVzTHgnYOne12FDTasYk1AwadVZJkkgXBPywe7HMY8I3HOIuXj8Uk49t8G67x/8MBGx0ab
+ HxZ++NnMAzKwlMILkErv+280k5FPv+Vr8qk6LuZtYtd9twX21j2hm7mk+3lKCABUY7ga6L1P
+ JGP0idNjMrkBDQRVI6a4AQgAtJXjUkflDqtXShIkeSZJo6dN2owSlFC81OE9qber6gAsCAbA
+ c3rlevzL6NkxnElQfecxPtYoVBORDk+X0bvbwW6WHvllci+r8yYIpKUzuNQZ/5DnE1vJA1MI
+ Y0xUXYIMfaSTlzQLKDPvRkMQJ6g4AMMBBMt9OX2f00LOMMGJ0Tb7PhDYwCk5jw2jMqseIl4y
+ RLVXiWLvjnms6TihDxGIQzpNU9CTZGps348GM6mr7LGG8CnW5D4Cv/g++p2uDFN2dNixs+UF
+ ddzgVpCgAp7QorK5HOFCEvwMGxYjBcI6IYbKbzj93O98L4Mnr0OUqK6p4USdwgCRoS1gKMZm
+ yi2vMwARAQABiQIQBBgBCgAmAhsMFiEEjxd3cRijPdqbpI5iqssyQ2MAUtkFAlywiP0FCQtP
+ SUUACgkQqssyQ2MAUtnA1g6fVRvQE+lSZ5Yb4w6QSG6CCGsjUDuZvwh2P24fGUdQaWQsi929
+ FZoYQ9Hd3t5MkAPqNCZcpjds7z16jZE2sqHESzP6wgOCKi69uYGuvTzRpUpXEmYsa0l7OIk+
+ 88ebRU/Kj1KX+PxbCyDj1B9Mk7Zx3M0/v87/+jtHCILVL/ZxIOJTB/f/bHGSDTuHfbcItOjh
+ eS6TYm2i6tQPewGiateLQ25hLPjVt+tIVAcgnzGTERfXjGeSnY1hODYBam7ynorwcItAElg5
+ TXHVDCJ7xli3H8MnLpLFpPfY+e3krqJWRVwL39fwah/2Y60hM4J/byeiBKzz3u/Zi5NgHWOn
+ 0I+Vm/c0AdmA/LxmrCz1WbF0MYPq09pvuxkXg4NptUxn8lIFYUlLWL5Qv4WR0ocLS67Iieny
+ XlIwbe3T2SPqISVLWBJBdsw2p9TqqS7T0i41daYcFyPrLAILLEs2Zrh88i/0bXZDMTV6E/6a
+ GWluAV36k0QziinMPpeKyuGiZf3ELBqeAoJ0YdWH62HXpnaEm+lGxxAzsitf3QENEMmda621
+ BQFYapg16oofuQT17e0wTCPAvEIhFk6leoDZz9HPXA7b3sncMFSJ9jlGKAOSZURbxHOwin6l
+
+...
+"
+;
+ let ac = AutocryptHeaders::from_bytes(&GOSSIP[..]).unwrap();
+ //eprintln!("ac: {:#?}", ac);
+
+ // We expect exactly two Autocrypt headers.
+ assert_eq!(ac.headers.len(), 2);
+
+ assert_eq!(ac.headers[0].header_type, AutocryptHeaderType::Gossip);
+ assert_eq!(ac.headers[0].get("addr").unwrap().value,
+ "dkg@fifthhorseman.net");
+
+ assert_eq!(ac.headers[1].get("addr").unwrap().value,
+ "neal@walfield.org");
+
+ let cert = ac.headers[0].key.as_ref()
+ .expect("Failed to parse key material.");
+ assert_eq!(cert.fingerprint(),
+ Fingerprint::from_hex(
+ &"C4BC2DDB38CCE96485EBE9C2F20691179038E5C6"[..]).unwrap());
+ assert_eq!(cert.userids().next().unwrap().value(),
+ &b"Daniel Kahn Gillmor <dkg@fifthhorseman.net>"[..]);
+
+ }
+
#[test]
fn passcode_gen_test() {
let mut dist = [0usize; 10];