From 635de19fb828526a3b7875ecd0713285f271b33e Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sun, 28 Nov 2021 14:15:01 +0100 Subject: [PATCH] Add tests for KeyRingUtils.injectCertification and render keysPlusPublicKey unusable --- .../org/pgpainless/key/util/KeyRingUtils.java | 8 ++++ .../pgpainless/key/util/KeyRingUtilTest.java | 45 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/pgpainless-core/src/main/java/org/pgpainless/key/util/KeyRingUtils.java b/pgpainless-core/src/main/java/org/pgpainless/key/util/KeyRingUtils.java index 4afbfd6a..9848ced9 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/key/util/KeyRingUtils.java +++ b/pgpainless-core/src/main/java/org/pgpainless/key/util/KeyRingUtils.java @@ -24,6 +24,7 @@ import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.openpgp.PGPSignature; import org.bouncycastle.openpgp.PGPUserAttributeSubpacketVector; import org.pgpainless.PGPainless; +import org.pgpainless.exception.NotYetImplementedException; import org.pgpainless.key.protection.SecretKeyRingProtector; import org.pgpainless.key.protection.UnlockSecretKey; @@ -299,6 +300,10 @@ public final class KeyRingUtils { } public static T keysPlusPublicKey(T keyRing, PGPPublicKey publicKey) { + if (true) + // Is currently broken beyond repair + throw new NotYetImplementedException(); + PGPSecretKeyRing secretKeys = null; PGPPublicKeyRing publicKeys; if (keyRing instanceof PGPSecretKeyRing) { @@ -312,6 +317,9 @@ public final class KeyRingUtils { if (secretKeys == null) { return (T) publicKeys; } else { + // TODO: Replace with PGPSecretKeyRing.insertOrReplacePublicKey() once available + // Right now replacePublicKeys looses extra public keys. + // See https://github.com/bcgit/bc-java/pull/1068 for a possible fix secretKeys = PGPSecretKeyRing.replacePublicKeys(secretKeys, publicKeys); return (T) secretKeys; } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/util/KeyRingUtilTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/util/KeyRingUtilTest.java index 8312bd28..9f2546ae 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/util/KeyRingUtilTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/util/KeyRingUtilTest.java @@ -5,18 +5,30 @@ package org.pgpainless.key.util; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.util.NoSuchElementException; +import java.util.Random; +import org.bouncycastle.bcpg.attr.ImageAttribute; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.PGPSignatureGenerator; +import org.bouncycastle.openpgp.PGPUserAttributeSubpacketVector; +import org.bouncycastle.openpgp.PGPUserAttributeSubpacketVectorGenerator; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; +import org.pgpainless.algorithm.HashAlgorithm; +import org.pgpainless.algorithm.SignatureType; +import org.pgpainless.implementation.ImplementationFactory; import org.pgpainless.key.protection.SecretKeyRingProtector; +import org.pgpainless.key.protection.UnlockSecretKey; import org.pgpainless.util.CollectionUtils; public class KeyRingUtilTest { @@ -63,4 +75,37 @@ public class KeyRingUtilTest { assertThrows(NoSuchElementException.class, () -> KeyRingUtils.deleteUserId(secretKeys, "Charlie")); } + + @Test + public void testInjectCertification() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { + PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() + .modernKeyRing("Alice", null); + + // test preconditions + assertFalse(secretKeys.getPublicKey().getUserAttributes().hasNext()); + int sigCount = CollectionUtils.iteratorToList(secretKeys.getPublicKey().getSignatures()).size(); + + // Create "image" + byte[] image = new byte[512]; + new Random().nextBytes(image); + PGPUserAttributeSubpacketVectorGenerator userAttrGen = new PGPUserAttributeSubpacketVectorGenerator(); + userAttrGen.setImageAttribute(ImageAttribute.JPEG, image); + PGPUserAttributeSubpacketVector userAttr = userAttrGen.generate(); + + // create sig + PGPSignatureGenerator sigGen = new PGPSignatureGenerator( + ImplementationFactory.getInstance().getPGPContentSignerBuilder( + secretKeys.getPublicKey().getAlgorithm(), HashAlgorithm.SHA512.getAlgorithmId() + )); + sigGen.init( + SignatureType.POSITIVE_CERTIFICATION.getCode(), + UnlockSecretKey.unlockSecretKey(secretKeys.getSecretKey(), SecretKeyRingProtector.unprotectedKeys())); + PGPSignature signature = sigGen.generateCertification(userAttr, secretKeys.getPublicKey()); + // inject sig + secretKeys = KeyRingUtils.injectCertification(secretKeys, userAttr, signature); + + assertTrue(secretKeys.getPublicKey().getUserAttributes().hasNext()); + assertEquals(userAttr, secretKeys.getPublicKey().getUserAttributes().next()); + assertEquals(sigCount + 1, CollectionUtils.iteratorToList(secretKeys.getPublicKey().getSignatures()).size()); + } }