diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-12-14 16:37:33 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-12-14 16:37:33 +0100 |
commit | 8c50ba96a5434aeefbf44e0d034072dfc6669521 (patch) | |
tree | 7c6a5d31c22dac12fa97c4545de873a3605c7b2e /openpgp/src/cert.rs | |
parent | 7e57122f0bd6db27c6e2f0c7deac1333256e5146 (diff) |
openpgp: Change general purpose keys to have a signing subkey.
- Certificates with a primary key that is not signing capable, and a
subkey that is, are strictly more secure than ones that combine
signing and certification capabilities in the primary key.
- If the owner of a certificate with a signing-capable primary key
can be tricked into creating a binary signature over carefully
chosen attacker-controlled data, this signature can be repurposed
to bind arbitrary attacker-controlled components to the
certificate using a chosen-prefix collision attack on the hash
function (see e.g. "SHA-1 is a Shambles" for a similar attack).
- Having a separate signing-subkey mitigates the attack, because
signatures by the signing subkey cannot bind components to the
certificate.
Diffstat (limited to 'openpgp/src/cert.rs')
-rw-r--r-- | openpgp/src/cert.rs | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/openpgp/src/cert.rs b/openpgp/src/cert.rs index fc548cd2..648be37a 100644 --- a/openpgp/src/cert.rs +++ b/openpgp/src/cert.rs @@ -4034,6 +4034,8 @@ mod test { + 1 // binding signature + 1 // subkey + 1 // binding signature + + 1 // subkey + + 1 // binding signature ); let cert = check_set_validity_period(p, cert); assert_eq!(cert.clone().into_packet_pile().children().count(), @@ -4045,6 +4047,8 @@ mod test { + 2 // two new binding signatures + 1 // subkey + 1 // binding signature + + 1 // subkey + + 1 // binding signature ); } @@ -4075,6 +4079,8 @@ mod test { + 1 // binding signature + 1 // subkey + 1 // binding signature + + 1 // subkey + + 1 // binding signature ); let cert = check_set_validity_period(p, cert); assert_eq!(cert.clone().into_packet_pile().children().count(), @@ -4089,6 +4095,8 @@ mod test { + 2 // two new binding signatures + 1 // subkey + 1 // binding signature + + 1 // subkey + + 1 // binding signature ); assert_eq!(&primary_uid, cert.with_policy(p, None)?.primary_userid()?.userid()); Ok(()) @@ -5674,11 +5682,12 @@ Pu1xwz57O4zo1VYf6TqHJzVC3OMvMUM2hhdecMUe5x6GorNaj6g= let (cert, _) = CertBuilder::general_purpose( None, Some("alice@example.org")).generate().unwrap(); assert_eq!(cert.userids().count(), 1); - assert_eq!(cert.subkeys().count(), 1); + assert_eq!(cert.subkeys().count(), 2); assert_eq!(cert.unknowns().count(), 0); assert_eq!(cert.bad_signatures().count(), 0); assert_eq!(cert.userids().nth(0).unwrap().self_signatures().len(), 1); assert_eq!(cert.subkeys().nth(0).unwrap().self_signatures().len(), 1); + assert_eq!(cert.subkeys().nth(1).unwrap().self_signatures().len(), 1); // Create a variant of cert where the signatures have // additional information in the unhashed area. @@ -5698,11 +5707,12 @@ Pu1xwz57O4zo1VYf6TqHJzVC3OMvMUM2hhdecMUe5x6GorNaj6g= let cert_b = Cert::from_packets(packets.into_iter())?; let cert = cert.merge_public_and_secret(cert_b)?; assert_eq!(cert.userids().count(), 1); - assert_eq!(cert.subkeys().count(), 1); + assert_eq!(cert.subkeys().count(), 2); assert_eq!(cert.unknowns().count(), 0); assert_eq!(cert.bad_signatures().count(), 0); assert_eq!(cert.userids().nth(0).unwrap().self_signatures().len(), 1); assert_eq!(cert.subkeys().nth(0).unwrap().self_signatures().len(), 1); + assert_eq!(cert.subkeys().nth(1).unwrap().self_signatures().len(), 1); Ok(()) } |