1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-11-14 00:12:06 +01:00

ArmorUtils now prints out the primary user-id and brief information about other user-ids

This commit is contained in:
Simon Frankenberger 2022-03-03 11:56:28 +01:00
parent d6cf1c6609
commit e569c2c991
No known key found for this signature in database
GPG key ID: 2F4A3C302FD2ECAE
2 changed files with 83 additions and 3 deletions

View file

@ -24,6 +24,7 @@ import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPUtil; import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator; import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
import org.bouncycastle.util.io.Streams; import org.bouncycastle.util.io.Streams;
@ -106,14 +107,38 @@ public final class ArmorUtils {
return sb.toString(); return sb.toString();
} }
private static Tuple<String, Integer> getPrimaryUserIdAndUserIdCount(PGPPublicKey publicKey) {
Iterator<String> userIds = publicKey.getUserIDs();
int countIdentities = 0;
String primary = null;
while (userIds.hasNext()) {
countIdentities++;
String userId = userIds.next();
if (primary == null) {
Iterator<PGPSignature> signatures = publicKey.getSignaturesForID(userId);
while (signatures.hasNext()) {
PGPSignature signature = signatures.next();
if (signature.getHashedSubPackets().isPrimaryUserID()) {
primary = userId;
break;
}
}
}
}
return new Tuple<>(primary, countIdentities);
}
private static MultiMap<String, String> keyToHeader(PGPPublicKey publicKey) { private static MultiMap<String, String> keyToHeader(PGPPublicKey publicKey) {
MultiMap<String, String> header = new MultiMap<>(); MultiMap<String, String> header = new MultiMap<>();
OpenPgpFingerprint fingerprint = OpenPgpFingerprint.of(publicKey); OpenPgpFingerprint fingerprint = OpenPgpFingerprint.of(publicKey);
Iterator<String> userIds = publicKey.getUserIDs();
header.put(HEADER_COMMENT, fingerprint.prettyPrint()); header.put(HEADER_COMMENT, fingerprint.prettyPrint());
if (userIds.hasNext()) { Tuple<String, Integer> idCount = getPrimaryUserIdAndUserIdCount(publicKey);
header.put(HEADER_COMMENT, userIds.next()); if (idCount.getA() != null) {
header.put(HEADER_COMMENT, idCount.getA() + " (Primary)");
}
if (idCount.getB() != 1) {
header.put(HEADER_COMMENT, String.format("Public key contains %d identities", idCount.getB()));
} }
return header; return header;
} }

View file

@ -21,16 +21,24 @@ import org.bouncycastle.openpgp.PGPCompressedData;
import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPLiteralData; import org.bouncycastle.openpgp.PGPLiteralData;
import org.bouncycastle.openpgp.PGPObjectFactory; import org.bouncycastle.openpgp.PGPObjectFactory;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPUtil; import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.util.io.Streams; import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.HashAlgorithm; import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.implementation.ImplementationFactory; import org.pgpainless.implementation.ImplementationFactory;
import org.pgpainless.key.TestKeys; import org.pgpainless.key.TestKeys;
import org.pgpainless.key.generation.KeySpec;
import org.pgpainless.key.generation.type.ecc.EllipticCurve;
import org.pgpainless.key.generation.type.ecc.ecdsa.ECDSA;
public class ArmorUtilsTest { public class ArmorUtilsTest {
@ -144,6 +152,53 @@ public class ArmorUtilsTest {
"-----END PGP MESSAGE-----\n", out.toString()); "-----END PGP MESSAGE-----\n", out.toString());
} }
@Test
public void testMultipleIdentitiesInHeader() throws Exception {
PGPSecretKeyRing secretKeyRing = PGPainless.buildKeyRing()
.setPrimaryKey(KeySpec.getBuilder(ECDSA.fromCurve(EllipticCurve._P256), KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER))
.addUserId("Juliet <juliet@montague.lit>")
.addUserId("xmpp:juliet@capulet.lit")
.setPassphrase(Passphrase.fromPassword("test"))
.build();
PGPPublicKey publicKey = secretKeyRing.getPublicKey();
PGPPublicKeyRing publicKeyRing = PGPainless.readKeyRing().publicKeyRing(publicKey.getEncoded());
String armored = PGPainless.asciiArmor(publicKeyRing);
Assertions.assertTrue(armored.contains("Comment: Juliet <juliet@montague.lit> (Primary)"));
Assertions.assertTrue(armored.contains("Comment: Public key contains 2 identities"));
}
@Test
public void testSingleIdentityInHeader() throws Exception {
PGPSecretKeyRing secretKeyRing = PGPainless.buildKeyRing()
.setPrimaryKey(KeySpec.getBuilder(ECDSA.fromCurve(EllipticCurve._P256), KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER))
.addUserId("Juliet <juliet@montague.lit>")
.setPassphrase(Passphrase.fromPassword("test"))
.build();
PGPPublicKey publicKey = secretKeyRing.getPublicKey();
PGPPublicKeyRing publicKeyRing = PGPainless.readKeyRing().publicKeyRing(publicKey.getEncoded());
String armored = PGPainless.asciiArmor(publicKeyRing);
Assertions.assertTrue(armored.contains("Comment: Juliet <juliet@montague.lit> (Primary)"));
Assertions.assertFalse(armored.contains("Comment: Public key contains 1 identities"));
}
@Test
public void testWithoutIdentityInHeader() throws Exception {
PGPPublicKeyRing publicKeys = PGPainless.readKeyRing().publicKeyRing("-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
"xsBNBGIgzE0BCACwxaYg6bpmp0POq1T6yalGE9XaL2IG9d9khDBweZ63s3Pu1pHB\n" +
"JtmjgN7Tx3ts6hLzQm3YKYA6zu1MXQ8k2vqtdtGUpZPp18Pbars7yUDqh8QIdFjO\n" +
"GeE+c8So0MQgTgoBuyZiSmslwp1WO78ozf/0rCayFdy73dPUntuLE6c2ZKO8nw/g\n" +
"uyk2ozsqLN/TBpgbuJUyMedJtXV10DdT9QxH/66LmdjFKXTkc74qI8YAm/pmJeOh\n" +
"36qZ5ehAgz9MthPQINnZKpnqidqkGFvjwVFlCMlVSmNCNJmpgGDH3gvkklZHzGsf\n" +
"dfzQswd/BQjPsFH9cK+QFYMG6q2zrvM0X9mdABEBAAE=\n" +
"=njg8\n" +
"-----END PGP PUBLIC KEY BLOCK-----\n");
PGPPublicKey publicKey = publicKeys.getPublicKey();
PGPPublicKeyRing publicKeyRing = PGPainless.readKeyRing().publicKeyRing(publicKey.getEncoded());
String armored = PGPainless.asciiArmor(publicKeyRing);
Assertions.assertTrue(armored.contains("Comment: Public key contains 0 identities"));
}
@TestTemplate @TestTemplate
@ExtendWith(TestAllImplementations.class) @ExtendWith(TestAllImplementations.class)
public void decodeExampleTest() throws IOException, PGPException { public void decodeExampleTest() throws IOException, PGPException {