diff options
author | Neal H. Walfield <neal@pep.foundation> | 2020-05-13 17:10:49 +0200 |
---|---|---|
committer | Neal H. Walfield <neal@pep.foundation> | 2020-05-13 17:56:33 +0200 |
commit | 034b3ccff0142a19307bdcb206e66ce846d556f4 (patch) | |
tree | 5aae5bb6737c46f103a71b7132959b0b24114af2 | |
parent | dc8ea94ab33c0ad5521a98c6b2b74097104bb5c0 (diff) |
openpgp: Sometimes set the primary User ID flag on a User Attribute
- When using `CertBuilder` to generate a certificate, if there are
no User IDs, set the primary User ID flag on the first User
Attribute.
-rw-r--r-- | openpgp/src/cert/builder.rs | 18 | ||||
-rw-r--r-- | openpgp/src/cert/mod.rs | 27 |
2 files changed, 27 insertions, 18 deletions
diff --git a/openpgp/src/cert/builder.rs b/openpgp/src/cert/builder.rs index 1ef60e71..f6afbf30 100644 --- a/openpgp/src/cert/builder.rs +++ b/openpgp/src/cert/builder.rs @@ -209,6 +209,13 @@ impl CertBuilder { } /// Adds a new user attribute. + /// + /// Adds a User Attribute to the certificate. If there are no + /// user ids, the first User attribute that is added, whether via + /// this interface or another interface, will have the [primary + /// User ID flag] set. + /// + /// [primary User ID flag]: https://tools.ietf.org/html/rfc4880#section-5.2.3.19 pub fn add_user_attribute<'a, U>(mut self, ua: U) -> Self where U: Into<packet::UserAttribute> { @@ -328,6 +335,8 @@ impl CertBuilder { let mut cert = Cert::try_from(packets)?; + let have_userids = self.userids.len() > 0; + // Sign UserIDs. for (i, uid) in self.userids.into_iter().enumerate() { let mut builder = sig.clone() @@ -343,11 +352,14 @@ impl CertBuilder { } // Sign UserAttributes. - for ua in self.user_attributes.into_iter() { - let builder = sig.clone() + for (i, ua) in self.user_attributes.into_iter().enumerate() { + let mut builder = sig.clone() .set_type(SignatureType::PositiveCertification) - // GnuPG wants at least a 512-bit hash for P521 keys. + // GnuPG wants at least a 512-bit hash for P521 keys. .set_hash_algo(HashAlgorithm::SHA512); + if i == 0 && ! have_userids { + builder = builder.set_primary_userid(true)?; + } let signature = ua.bind(&mut signer, &cert, builder)?; cert = cert.merge_packets( vec![Packet::from(ua), signature.into()])?; diff --git a/openpgp/src/cert/mod.rs b/openpgp/src/cert/mod.rs index b3cd11be..94ba1472 100644 --- a/openpgp/src/cert/mod.rs +++ b/openpgp/src/cert/mod.rs @@ -2829,42 +2829,39 @@ impl<'a> ValidCert<'a> { /// let vc = cert.with_policy(p, t1)?; /// let alice = vc.primary_userid().unwrap(); /// assert_eq!(alice.value(), b"Alice"); - /// // By default, the primary User ID flag is not set. - /// assert!(alice.binding_signature().primary_userid().is_none()); + /// // By default, the primary User ID flag is set. + /// assert!(alice.binding_signature().primary_userid().is_some()); /// /// let template: signature::SignatureBuilder /// = alice.binding_signature().clone().into(); /// - /// /// // Add another user id whose creation time is after the - /// // existing User ID. + /// // existing User ID, and doesn't have the User ID set. /// let sig = template.clone() - /// .set_signature_creation_time(t2)?; + /// .set_signature_creation_time(t2)? + /// .set_primary_userid(false)?; /// let bob: UserID = "Bob".into(); /// let sig = bob.bind(&mut signer, &cert, sig)?; /// let cert = cert.merge_packets(vec![ Packet::from(bob), sig.into() ])?; /// # assert_eq!(cert.userids().count(), 2); /// - /// // It should now be the primary User ID, because it is newer. - /// let bob = cert.with_policy(p, t2)?.primary_userid().unwrap(); - /// assert_eq!(bob.value(), b"Bob"); - /// // But, not before it was created!. - /// let alice = cert.with_policy(p, t1)?.primary_userid().unwrap(); + /// // Alice should still be the primary User ID, because it has the + /// // primary User ID flag set. + /// let alice = cert.with_policy(p, t2)?.primary_userid().unwrap(); /// assert_eq!(alice.value(), b"Alice"); /// /// /// // Add another User ID, whose binding signature's creation - /// // time is prior to Bob's, but mark it as the primary User ID. + /// // time is after Alice's and also has the primary User ID flag set. /// let sig = template.clone() - /// .set_signature_creation_time(t1)? - /// .set_primary_userid(true)?; + /// .set_signature_creation_time(t2)?; /// let carol: UserID = "Carol".into(); /// let sig = carol.bind(&mut signer, &cert, sig)?; /// let cert = cert.merge_packets(vec![ Packet::from(carol), sig.into() ])?; /// # assert_eq!(cert.userids().count(), 3); /// - /// // It should now be the primary User ID, because the primary User ID - /// // bit is set. + /// // It should now be the primary User ID, because it is the + /// // newest User ID with the primary User ID bit is set. /// let carol = cert.with_policy(p, t2)?.primary_userid().unwrap(); /// assert_eq!(carol.value(), b"Carol"); /// # Ok(()) } |