diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/info/KeyRingInfo.java b/pgpainless-core/src/main/java/org/pgpainless/key/info/KeyRingInfo.java index be45bb42..c0cf8346 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/key/info/KeyRingInfo.java +++ b/pgpainless-core/src/main/java/org/pgpainless/key/info/KeyRingInfo.java @@ -82,11 +82,8 @@ public class KeyRingInfo { * @return list of public keys */ public List getPublicKeys() { - List list = new ArrayList<>(); Iterator iterator = keys.getPublicKeys(); - while (iterator.hasNext()) { - list.add(iterator.next()); - } + List list = iteratorToList(iterator); return Collections.unmodifiableList(list); } @@ -122,15 +119,12 @@ public class KeyRingInfo { * @return list of secret keys */ public List getSecretKeys() { - List list = new ArrayList<>(); if (keys instanceof PGPSecretKeyRing) { PGPSecretKeyRing secretKeys = (PGPSecretKeyRing) keys; Iterator iterator = secretKeys.getSecretKeys(); - while (iterator.hasNext()) { - list.add(iterator.next()); - } + return Collections.unmodifiableList(iteratorToList(iterator)); } - return Collections.unmodifiableList(list); + return Collections.emptyList(); } /** @@ -151,17 +145,25 @@ public class KeyRingInfo { return new OpenPgpV4Fingerprint(getPublicKey()); } + public String getPrimaryUserId() throws PGPException { + List userIds = getValidUserIds(); + for (String userId : userIds) { + PGPSignature signature = getLatestValidSignatureOnUserId(userId); + if (signature.getHashedSubPackets().isPrimaryUserID()) { + return userId; + } + } + return null; + } + /** * Return a list of all user-ids of the primary key. * * @return list of user-ids */ public List getUserIds() { - List userIds = new ArrayList<>(); Iterator iterator = getPublicKey().getUserIDs(); - while (iterator.hasNext()) { - userIds.add(iterator.next()); - } + List userIds = iteratorToList(iterator); return userIds; } @@ -315,10 +317,7 @@ public class KeyRingInfo { public List getSelfSignaturesOnKey(long subkeyId) { PGPPublicKey publicKey = KeyRingUtils.requirePublicKeyFrom(keys, subkeyId); Iterator it = publicKey.getSignaturesForKeyID(keys.getPublicKey().getKeyID()); - List signatures = new ArrayList<>(); - while (it.hasNext()) { - signatures.add(it.next()); - } + List signatures = iteratorToList(it); sortByCreationTimeAscending(signatures); return signatures; } @@ -337,6 +336,13 @@ public class KeyRingInfo { return getLatestValidSignature(publicKey, signatures, keys); } + public PGPSignature getLatestValidSignatureOnUserId(String userId) throws PGPException { + PGPPublicKey publicKey = KeyRingUtils.requirePrimaryPublicKeyFrom(keys); + Iterator iterator = publicKey.getSignaturesForID(userId); + List signatures = iteratorToList(iterator); + return getLatestValidSignature(publicKey, signatures, keys); + } + public List getBindingSignaturesOnKey(OpenPgpV4Fingerprint fingerprint) { return getBindingSignaturesOnKey(fingerprint.getKeyId()); } @@ -371,5 +377,12 @@ public class KeyRingInfo { return self.getCreationTime().after(binding.getCreationTime()) ? self : binding; } - + private static List iteratorToList(Iterator iterator) { + List items = new ArrayList<>(); + while (iterator.hasNext()) { + Object o = iterator.next(); + items.add((I) o); + } + return items; + } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/info/PrimaryUserIdTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/info/PrimaryUserIdTest.java new file mode 100644 index 00000000..88719aec --- /dev/null +++ b/pgpainless-core/src/test/java/org/pgpainless/key/info/PrimaryUserIdTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2021 Paul Schaub. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pgpainless.key.info; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.junit.jupiter.api.Test; +import org.pgpainless.PGPainless; +import org.pgpainless.key.protection.SecretKeyRingProtector; + +public class PrimaryUserIdTest { + + @Test + public void testGetPrimaryUserId() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException { + PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing("alice@wonderland.lit"); + secretKeys = PGPainless.modifyKeyRing(secretKeys) + .addUserId("mad_alice@wonderland.lit", SecretKeyRingProtector.unprotectedKeys()) + .done(); + + KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys); + assertEquals("alice@wonderland.lit", info.getPrimaryUserId()); + } +}