1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-09-10 10:49:39 +02:00

Port SignatureBuilders over to new classes

This commit is contained in:
Paul Schaub 2025-02-19 12:43:38 +01:00
parent 94dc25aa8b
commit 3feaf9134b
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
18 changed files with 398 additions and 246 deletions

View file

@ -15,9 +15,10 @@ import java.util.List;
import org.bouncycastle.bcpg.sig.TrustSignature;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.bouncycastle.openpgp.api.OpenPGPSignature;
import org.bouncycastle.util.Arrays;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
@ -36,13 +37,11 @@ public class CertifyCertificateTest {
@Test
public void testUserIdCertification() throws PGPException, IOException {
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
PGPSecretKeyRing alice = PGPainless.generateKeyRing().modernKeyRing("Alice <alice@pgpainless.org>")
.getPGPSecretKeyRing();
OpenPGPKey alice = PGPainless.generateKeyRing().modernKeyRing("Alice <alice@pgpainless.org>");
String bobUserId = "Bob <bob@pgpainless.org>";
PGPSecretKeyRing bob = PGPainless.generateKeyRing().modernKeyRing(bobUserId)
.getPGPSecretKeyRing();
OpenPGPKey bob = PGPainless.generateKeyRing().modernKeyRing(bobUserId);
PGPPublicKeyRing bobCertificate = PGPainless.extractCertificate(bob);
OpenPGPCertificate bobCertificate = bob.toCertificate();
CertifyCertificate.CertificationResult result = PGPainless.certify()
.userIdOnCertificate(bobUserId, bobCertificate)
@ -50,35 +49,33 @@ public class CertifyCertificateTest {
.build();
assertNotNull(result);
PGPSignature signature = result.getCertification();
PGPSignature signature = result.getPgpSignature();
assertNotNull(signature);
assertEquals(SignatureType.GENERIC_CERTIFICATION, SignatureType.valueOf(signature.getSignatureType()));
assertEquals(alice.getPublicKey().getKeyID(), signature.getKeyID());
assertEquals(alice.getPrimaryKey().getPGPPublicKey().getKeyID(), signature.getKeyID());
assertTrue(SignatureVerifier.verifyUserIdCertification(
bobUserId, signature, alice.getPublicKey(), bob.getPublicKey(), PGPainless.getPolicy(), DateUtil.now()));
bobUserId, signature, alice.getPrimaryKey().getPGPPublicKey(), bob.getPrimaryKey().getPGPPublicKey(), PGPainless.getPolicy(), DateUtil.now()));
PGPPublicKeyRing bobCertified = result.getCertifiedCertificate();
PGPPublicKey bobCertifiedKey = bobCertified.getPublicKey();
OpenPGPCertificate bobCertified = result.getCertifiedCertificate();
PGPPublicKey bobCertifiedKey = bobCertified.getPrimaryKey().getPGPPublicKey();
// There are 2 sigs now, bobs own and alice'
assertEquals(2, CollectionUtils.iteratorToList(bobCertifiedKey.getSignaturesForID(bobUserId)).size());
List<PGPSignature> sigsByAlice = CollectionUtils.iteratorToList(
bobCertifiedKey.getSignaturesForKeyID(alice.getPublicKey().getKeyID()));
bobCertifiedKey.getSignaturesForKeyID(alice.getPrimaryKey().getPGPPublicKey().getKeyID()));
assertEquals(1, sigsByAlice.size());
assertEquals(signature, sigsByAlice.get(0));
assertFalse(Arrays.areEqual(bobCertificate.getEncoded(), bobCertified.getEncoded()));
assertFalse(Arrays.areEqual(bobCertificate.getPGPPublicKeyRing().getEncoded(), bobCertified.getPGPPublicKeyRing().getEncoded()));
}
@Test
public void testKeyDelegation() throws PGPException, IOException {
SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
PGPSecretKeyRing alice = PGPainless.generateKeyRing().modernKeyRing("Alice <alice@pgpainless.org>")
.getPGPSecretKeyRing();
PGPSecretKeyRing bob = PGPainless.generateKeyRing().modernKeyRing("Bob <bob@pgpainless.org>")
.getPGPSecretKeyRing();
OpenPGPKey alice = PGPainless.generateKeyRing().modernKeyRing("Alice <alice@pgpainless.org>");
OpenPGPKey bob = PGPainless.generateKeyRing().modernKeyRing("Bob <bob@pgpainless.org>");
PGPPublicKeyRing bobCertificate = PGPainless.extractCertificate(bob);
OpenPGPCertificate bobCertificate = bob.toCertificate();
CertifyCertificate.CertificationResult result = PGPainless.certify()
.certificate(bobCertificate, Trustworthiness.fullyTrusted().introducer())
@ -86,11 +83,12 @@ public class CertifyCertificateTest {
.build();
assertNotNull(result);
PGPSignature signature = result.getCertification();
OpenPGPSignature signature = result.getCertification();
PGPSignature pgpSignature = signature.getSignature();
assertNotNull(signature);
assertEquals(SignatureType.DIRECT_KEY, SignatureType.valueOf(signature.getSignatureType()));
assertEquals(alice.getPublicKey().getKeyID(), signature.getKeyID());
TrustSignature trustSignaturePacket = signature.getHashedSubPackets().getTrust();
assertEquals(SignatureType.DIRECT_KEY, SignatureType.valueOf(pgpSignature.getSignatureType()));
assertEquals(alice.getPrimaryKey().getPGPPublicKey().getKeyID(), pgpSignature.getKeyID());
TrustSignature trustSignaturePacket = pgpSignature.getHashedSubPackets().getTrust();
assertNotNull(trustSignaturePacket);
Trustworthiness trustworthiness = new Trustworthiness(trustSignaturePacket.getTrustAmount(), trustSignaturePacket.getDepth());
assertTrue(trustworthiness.isFullyTrusted());
@ -98,29 +96,27 @@ public class CertifyCertificateTest {
assertFalse(trustworthiness.canIntroduce(1));
assertTrue(SignatureVerifier.verifyDirectKeySignature(
signature, alice.getPublicKey(), bob.getPublicKey(), PGPainless.getPolicy(), DateUtil.now()));
pgpSignature, alice.getPrimaryKey().getPGPPublicKey(), bob.getPrimaryKey().getPGPPublicKey(), PGPainless.getPolicy(), DateUtil.now()));
PGPPublicKeyRing bobCertified = result.getCertifiedCertificate();
PGPPublicKey bobCertifiedKey = bobCertified.getPublicKey();
OpenPGPCertificate bobCertified = result.getCertifiedCertificate();
PGPPublicKey bobCertifiedKey = bobCertified.getPrimaryKey().getPGPPublicKey();
List<PGPSignature> sigsByAlice = CollectionUtils.iteratorToList(
bobCertifiedKey.getSignaturesForKeyID(alice.getPublicKey().getKeyID()));
bobCertifiedKey.getSignaturesForKeyID(alice.getPrimaryKey().getPGPPublicKey().getKeyID()));
assertEquals(1, sigsByAlice.size());
assertEquals(signature, sigsByAlice.get(0));
assertEquals(signature.getSignature(), sigsByAlice.get(0));
assertFalse(Arrays.areEqual(bobCertificate.getEncoded(), bobCertified.getEncoded()));
assertFalse(Arrays.areEqual(bobCertificate.getPGPPublicKeyRing().getEncoded(), bobCertified.getPGPPublicKeyRing().getEncoded()));
}
@Test
public void testPetNameCertification() {
PGPSecretKeyRing aliceKey = PGPainless.generateKeyRing()
.modernKeyRing("Alice <alice@pgpainless.org>")
.getPGPSecretKeyRing();
PGPSecretKeyRing bobKey = PGPainless.generateKeyRing()
.modernKeyRing("Bob <bob@pgpainless.org>")
.getPGPSecretKeyRing();
OpenPGPKey aliceKey = PGPainless.generateKeyRing()
.modernKeyRing("Alice <alice@pgpainless.org>");
OpenPGPKey bobKey = PGPainless.generateKeyRing()
.modernKeyRing("Bob <bob@pgpainless.org>");
PGPPublicKeyRing bobCert = PGPainless.extractCertificate(bobKey);
OpenPGPCertificate bobCert = bobKey.toCertificate();
String petName = "Bobby";
CertifyCertificate.CertificationResult result = PGPainless.certify()
@ -133,11 +129,12 @@ public class CertifyCertificateTest {
}
});
PGPSignature certification = result.getCertification();
assertEquals(aliceKey.getPublicKey().getKeyID(), certification.getKeyID());
assertEquals(CertificationType.GENERIC.asSignatureType().getCode(), certification.getSignatureType());
OpenPGPSignature certification = result.getCertification();
PGPSignature signature = certification.getSignature();
assertEquals(aliceKey.getPrimaryKey().getPGPPublicKey().getKeyID(), signature.getKeyID());
assertEquals(CertificationType.GENERIC.asSignatureType().getCode(), signature.getSignatureType());
PGPPublicKeyRing certWithPetName = result.getCertifiedCertificate();
OpenPGPCertificate certWithPetName = result.getCertifiedCertificate();
KeyRingInfo info = PGPainless.inspectKeyRing(certWithPetName);
assertTrue(info.getUserIds().contains(petName));
assertFalse(info.getValidUserIds().contains(petName));
@ -145,13 +142,11 @@ public class CertifyCertificateTest {
@Test
public void testScopedDelegation() {
PGPSecretKeyRing aliceKey = PGPainless.generateKeyRing()
.modernKeyRing("Alice <alice@pgpainless.org>")
.getPGPSecretKeyRing();
PGPSecretKeyRing caKey = PGPainless.generateKeyRing()
.modernKeyRing("CA <ca@example.com>")
.getPGPSecretKeyRing();
PGPPublicKeyRing caCert = PGPainless.extractCertificate(caKey);
OpenPGPKey aliceKey = PGPainless.generateKeyRing()
.modernKeyRing("Alice <alice@pgpainless.org>");
OpenPGPKey caKey = PGPainless.generateKeyRing()
.modernKeyRing("CA <ca@example.com>");
OpenPGPCertificate caCert = caKey.toCertificate();
CertifyCertificate.CertificationResult result = PGPainless.certify()
.certificate(caCert, Trustworthiness.fullyTrusted().introducer())
@ -163,9 +158,10 @@ public class CertifyCertificateTest {
}
});
PGPSignature certification = result.getCertification();
assertEquals(SignatureType.DIRECT_KEY.getCode(), certification.getSignatureType());
OpenPGPSignature certification = result.getCertification();
PGPSignature signature = certification.getSignature();
assertEquals(SignatureType.DIRECT_KEY.getCode(), signature.getSignatureType());
assertEquals("^.*<.+@example.com>.*$",
certification.getHashedSubPackets().getRegularExpression().getRegex());
signature.getHashedSubPackets().getRegularExpression().getRegex());
}
}

View file

@ -14,10 +14,10 @@ import java.util.HashSet;
import java.util.Set;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.EncryptionPurpose;
@ -33,10 +33,10 @@ public class SubkeyAndPrimaryKeyBindingSignatureTest {
@Test
public void testRebindSubkey() throws PGPException, IOException {
PGPSecretKeyRing secretKeys = TestKeys.getEmilSecretKeyRing();
OpenPGPKey secretKeys = PGPainless.getInstance().toKey(TestKeys.getEmilSecretKeyRing());
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
PGPSecretKey primaryKey = secretKeys.getSecretKey();
OpenPGPKey.OpenPGPSecretKey primaryKey = secretKeys.getPrimarySecretKey();
OpenPGPCertificate.OpenPGPComponentKey encryptionSubkey =
info.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0);
assertNotNull(encryptionSubkey);
@ -57,9 +57,9 @@ public class SubkeyAndPrimaryKeyBindingSignatureTest {
});
PGPSignature binding = sbb.build(encryptionSubkey.getPGPPublicKey());
secretKeys = KeyRingUtils.injectCertification(secretKeys, encryptionSubkey.getPGPPublicKey(), binding);
PGPSecretKeyRing secretKeyRing = KeyRingUtils.injectCertification(secretKeys.getPGPKeyRing(), encryptionSubkey.getPGPPublicKey(), binding);
info = PGPainless.inspectKeyRing(secretKeys);
info = PGPainless.inspectKeyRing(secretKeyRing);
assertEquals(Collections.singleton(HashAlgorithm.SHA512), info.getPreferredHashAlgorithms(encryptionSubkey.getKeyIdentifier()));
}
}

View file

@ -4,11 +4,13 @@
package org.pgpainless.signature.builder;
import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.bcpg.sig.Exportable;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.bouncycastle.openpgp.api.OpenPGPSignature;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.SignatureType;
@ -28,28 +30,25 @@ public class ThirdPartyCertificationSignatureBuilderTest {
@Test
public void testInvalidSignatureTypeThrows() {
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.modernKeyRing("Alice")
.getPGPSecretKeyRing();
OpenPGPKey secretKeys = PGPainless.generateKeyRing()
.modernKeyRing("Alice");
assertThrows(IllegalArgumentException.class, () ->
new ThirdPartyCertificationSignatureBuilder(
SignatureType.BINARY_DOCUMENT, // invalid type
secretKeys.getSecretKey(),
secretKeys.getPrimarySecretKey(),
SecretKeyRingProtector.unprotectedKeys()));
}
@Test
public void testUserIdCertification() throws PGPException {
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.modernKeyRing("Alice")
.getPGPSecretKeyRing();
OpenPGPKey secretKeys = PGPainless.generateKeyRing()
.modernKeyRing("Alice");
PGPPublicKeyRing bobsPublicKeys = PGPainless.extractCertificate(
PGPainless.generateKeyRing().modernKeyRing("Bob")
.getPGPSecretKeyRing());
OpenPGPCertificate bobsPublicKeys = PGPainless.generateKeyRing().modernKeyRing("Bob")
.toCertificate();
ThirdPartyCertificationSignatureBuilder signatureBuilder = new ThirdPartyCertificationSignatureBuilder(
secretKeys.getSecretKey(),
secretKeys.getPrimarySecretKey(),
SecretKeyRingProtector.unprotectedKeys());
signatureBuilder.applyCallback(new CertificationSubpackets.Callback() {
@ -59,16 +58,20 @@ public class ThirdPartyCertificationSignatureBuilderTest {
}
});
PGPSignature certification = signatureBuilder.build(bobsPublicKeys, "Bob");
assertEquals(SignatureType.GENERIC_CERTIFICATION, SignatureType.valueOf(certification.getSignatureType()));
assertEquals(secretKeys.getPublicKey().getKeyID(), certification.getKeyID());
assertArrayEquals(secretKeys.getPublicKey().getFingerprint(), certification.getHashedSubPackets().getIssuerFingerprint().getFingerprint());
Exportable exportable = SignatureSubpacketsUtil.getExportableCertification(certification);
OpenPGPSignature certification = signatureBuilder.build(bobsPublicKeys, "Bob");
PGPSignature signature = certification.getSignature();
assertEquals(SignatureType.GENERIC_CERTIFICATION, SignatureType.valueOf(signature.getSignatureType()));
assertTrue(KeyIdentifier.matches(signature.getKeyIdentifiers(), secretKeys.getKeyIdentifier(), true));
assertArrayEquals(
secretKeys.getPrimaryKey().getPGPPublicKey().getFingerprint(),
signature.getHashedSubPackets().getIssuerFingerprint().getFingerprint());
Exportable exportable = SignatureSubpacketsUtil.getExportableCertification(signature);
assertNotNull(exportable);
assertFalse(exportable.isExportable());
// test sig correctness
certification.init(ImplementationFactory.getInstance().getPgpContentVerifierBuilderProvider(), secretKeys.getPublicKey());
assertTrue(certification.verifyCertification("Bob", bobsPublicKeys.getPublicKey()));
signature.init(ImplementationFactory.getInstance().getPgpContentVerifierBuilderProvider(),
secretKeys.getPrimaryKey().getPGPPublicKey());
assertTrue(signature.verifyCertification("Bob", bobsPublicKeys.getPrimaryKey().getPGPPublicKey()));
}
}

View file

@ -14,6 +14,8 @@ import java.util.Date;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.bouncycastle.openpgp.api.OpenPGPSignature;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.CompressionAlgorithm;
@ -32,12 +34,11 @@ public class ThirdPartyDirectKeySignatureBuilderTest {
@Test
public void testDirectKeySignatureBuilding() throws PGPException {
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.modernKeyRing("Alice")
.getPGPSecretKeyRing();
OpenPGPKey secretKeys = PGPainless.generateKeyRing()
.modernKeyRing("Alice");
DirectKeySelfSignatureBuilder dsb = new DirectKeySelfSignatureBuilder(
secretKeys.getSecretKey(),
secretKeys.getPrimarySecretKey(),
SecretKeyRingProtector.unprotectedKeys());
Date now = new Date();
@ -54,11 +55,14 @@ public class ThirdPartyDirectKeySignatureBuilderTest {
}
});
PGPSignature directKeySig = dsb.build();
OpenPGPSignature directKeySig = dsb.build();
assertNotNull(directKeySig);
secretKeys = KeyRingUtils.injectCertification(secretKeys, secretKeys.getPublicKey(), directKeySig);
PGPSecretKeyRing secretKeyRing = KeyRingUtils.injectCertification(
secretKeys.getPGPSecretKeyRing(),
secretKeys.getPrimaryKey().getPGPPublicKey(),
directKeySig.getSignature());
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys, t1);
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeyRing, t1);
PGPSignature signature = info.getLatestDirectKeySelfSignature();
assertNotNull(signature);
@ -69,7 +73,7 @@ public class ThirdPartyDirectKeySignatureBuilderTest {
assertEquals(Collections.singleton(HashAlgorithm.SHA512), SignatureSubpacketsUtil.parsePreferredHashAlgorithms(signature));
assertEquals(Collections.singleton(CompressionAlgorithm.ZIP), SignatureSubpacketsUtil.parsePreferredCompressionAlgorithms(signature));
assertEquals(Collections.singleton(SymmetricKeyAlgorithm.AES_256), SignatureSubpacketsUtil.parsePreferredSymmetricKeyAlgorithms(signature));
assertEquals(secretKeys.getPublicKey().getKeyID(), signature.getKeyID());
assertArrayEquals(secretKeys.getPublicKey().getFingerprint(), signature.getHashedSubPackets().getIssuerFingerprint().getFingerprint());
assertEquals(secretKeyRing.getPublicKey().getKeyID(), signature.getKeyID());
assertArrayEquals(secretKeyRing.getPublicKey().getFingerprint(), signature.getHashedSubPackets().getIssuerFingerprint().getFingerprint());
}
}

View file

@ -6,15 +6,16 @@ package org.pgpainless.signature.builder;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.bcpg.sig.PrimaryUserID;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureGenerator;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
@ -51,18 +52,18 @@ public class UniversalSignatureBuilderTest {
"=Dqbd\n" +
"-----END PGP PRIVATE KEY BLOCK-----";
private PGPSecretKeyRing secretKeys;
private OpenPGPKey secretKeys;
private final SecretKeyRingProtector protector = SecretKeyRingProtector.unprotectedKeys();
@BeforeEach
public void parseKey() throws IOException {
secretKeys = PGPainless.readKeyRing().secretKeyRing(KEY);
secretKeys = PGPainless.getInstance().readKey().parseKey(KEY);
}
@Test
public void createPetNameSignature() throws PGPException {
PGPSecretKey signingKey = secretKeys.getSecretKey();
PGPSignature archetype = signingKey.getPublicKey().getSignatures().next();
OpenPGPKey.OpenPGPSecretKey signingKey = secretKeys.getPrimarySecretKey();
PGPSignature archetype = signingKey.getPublicKey().getPGPPublicKey().getSignatures().next();
UniversalSignatureBuilder builder = new UniversalSignatureBuilder(
signingKey, protector, archetype);
@ -77,11 +78,11 @@ public class UniversalSignatureBuilderTest {
PGPSignatureGenerator generator = builder.getSignatureGenerator();
String petName = "mykey";
PGPSignature petNameSig = generator.generateCertification(petName, secretKeys.getPublicKey());
PGPSignature petNameSig = generator.generateCertification(petName, secretKeys.getPrimarySecretKey().getPublicKey().getPGPPublicKey());
assertEquals(SignatureType.POSITIVE_CERTIFICATION.getCode(), petNameSig.getSignatureType());
assertEquals(4, petNameSig.getVersion());
assertEquals(signingKey.getKeyID(), petNameSig.getKeyID());
assertTrue(KeyIdentifier.matches(petNameSig.getKeyIdentifiers(), signingKey.getKeyIdentifier(), true));
assertEquals(HashAlgorithm.SHA512.getAlgorithmId(), petNameSig.getHashAlgorithm());
assertEquals(KeyFlag.toBitmask(KeyFlag.CERTIFY_OTHER), petNameSig.getHashedSubPackets().getKeyFlags());
assertFalse(petNameSig.getHashedSubPackets().isExportable());