summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2020-05-13 17:10:49 +0200
committerNeal H. Walfield <neal@pep.foundation>2020-05-13 17:56:33 +0200
commit034b3ccff0142a19307bdcb206e66ce846d556f4 (patch)
tree5aae5bb6737c46f103a71b7132959b0b24114af2
parentdc8ea94ab33c0ad5521a98c6b2b74097104bb5c0 (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.rs18
-rw-r--r--openpgp/src/cert/mod.rs27
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(()) }