1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-12-08 05:11:08 +01:00

Port signature validation to BC

This commit is contained in:
Paul Schaub 2025-03-21 13:44:24 +01:00
parent b248882f72
commit f707d87c67
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
8 changed files with 191 additions and 490 deletions

View file

@ -211,7 +211,6 @@ public class ModifiedPublicKeysInvestigation {
@Test
public void assertModifiedDSAKeyThrowsKeyIntegrityException() throws IOException {
System.out.println(DSA);
PGPainless api = PGPainless.newInstance();
Policy policy = api.getAlgorithmPolicy();
policy.setEnableKeyParameterValidation(true);

View file

@ -19,7 +19,6 @@ import java.nio.charset.StandardCharsets;
import java.util.Random;
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;
@ -36,9 +35,7 @@ import org.pgpainless.encryption_signing.SigningOptions;
import org.pgpainless.exception.WrongConsumingMethodException;
import org.pgpainless.key.TestKeys;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.signature.consumer.CertificateValidator;
import org.pgpainless.signature.SignatureUtils;
import org.pgpainless.signature.consumer.SignatureVerifier;
import org.pgpainless.util.ArmorUtils;
import org.pgpainless.util.TestUtils;
@ -136,19 +133,6 @@ public class CleartextSignatureVerificationTest {
assertArrayEquals(MESSAGE_BODY, bytes.toByteArray());
}
@Test
public void verifySignatureDetached()
throws IOException, PGPException {
PGPPublicKeyRing signingKeys = TestKeys.getEmilPublicKeyRing();
PGPSignature signature = SignatureUtils.readSignatures(SIGNATURE).get(0);
PGPPublicKey signingKey = signingKeys.getPublicKey(signature.getKeyID());
SignatureVerifier.initializeSignatureAndUpdateWithSignedData(signature, new ByteArrayInputStream(MESSAGE_BODY), signingKey);
CertificateValidator.validateCertificateAndVerifyInitializedSignature(signature, signingKeys, PGPainless.getPolicy());
}
public static void main(String[] args) throws IOException {
// CHECKSTYLE:OFF
PGPPublicKeyRing keys = TestKeys.getEmilPublicKeyRing();

View file

@ -4,23 +4,23 @@
package org.pgpainless.signature;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;
import org.pgpainless.PGPainless;
import org.pgpainless.exception.SignatureValidationException;
import org.pgpainless.policy.Policy;
import org.pgpainless.signature.consumer.CertificateValidator;
import org.pgpainless.decryption_verification.ConsumerOptions;
import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.decryption_verification.MessageMetadata;
import org.pgpainless.util.TestAllImplementations;
/**
@ -47,12 +47,9 @@ public class BindingSignatureSubpacketsTest {
"-----END PGP SIGNATURE-----\n";
private static final String data = "Hello World :)";
private Date validationDate = new Date();
private Policy policy = PGPainless.getPolicy();
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void baseCase() throws IOException {
public void baseCase() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -113,7 +110,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingIssuerFpOnly() throws IOException {
public void subkeyBindingIssuerFpOnly() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -174,7 +171,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingIssuerV6IssuerFp() throws IOException {
public void subkeyBindingIssuerV6IssuerFp() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -235,7 +232,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingIssuerFakeIssuer() throws IOException {
public void subkeyBindingIssuerFakeIssuer() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -296,7 +293,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingFakeIssuerIssuer() throws IOException {
public void subkeyBindingFakeIssuerIssuer() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -357,7 +354,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingFakeIssuer() throws IOException {
public void subkeyBindingFakeIssuer() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -418,7 +415,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingNoIssuer() throws IOException {
public void subkeyBindingNoIssuer() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -478,7 +475,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void unknownSubpacketHashed() throws IOException {
public void unknownSubpacketHashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -539,7 +536,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingUnknownCriticalSubpacket() throws IOException {
public void subkeyBindingUnknownCriticalSubpacket() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -600,7 +597,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingUnknownSubpacketUnhashed() throws IOException {
public void subkeyBindingUnknownSubpacketUnhashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -661,7 +658,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingUnknownCriticalSubpacketUnhashed() throws IOException {
public void subkeyBindingUnknownCriticalSubpacketUnhashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -722,7 +719,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingUnknownNotationHashed() throws IOException {
public void subkeyBindingUnknownNotationHashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -784,7 +781,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingCriticalUnknownNotationHashed() throws IOException {
public void subkeyBindingCriticalUnknownNotationHashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -846,7 +843,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingUnknownNotationUnhashed() throws IOException {
public void subkeyBindingUnknownNotationUnhashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -908,7 +905,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingCriticalUnknownNotationUnhashed() throws IOException {
public void subkeyBindingCriticalUnknownNotationUnhashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -970,7 +967,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingBackSigFakeBackSig() throws IOException {
public void subkeyBindingBackSigFakeBackSig() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1042,7 +1039,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void subkeyBindingFakeBackSigBackSig() throws IOException {
public void subkeyBindingFakeBackSigBackSig() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1114,7 +1111,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingIssuerFpOnly() throws IOException {
public void primaryBindingIssuerFpOnly() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1175,7 +1172,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingIssuerV6IssuerFp() throws IOException {
public void primaryBindingIssuerV6IssuerFp() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1236,7 +1233,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingIssuerFakeIssuer() throws IOException {
public void primaryBindingIssuerFakeIssuer() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1297,7 +1294,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingFakeIssuerIssuer() throws IOException {
public void primaryBindingFakeIssuerIssuer() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1358,7 +1355,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingFakeIssuer() throws IOException {
public void primaryBindingFakeIssuer() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1419,7 +1416,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingNoIssuer() throws IOException {
public void primaryBindingNoIssuer() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1479,7 +1476,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingUnknownSubpacketHashed() throws IOException {
public void primaryBindingUnknownSubpacketHashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1540,7 +1537,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingCriticalUnknownSubpacketHashed() throws IOException {
public void primaryBindingCriticalUnknownSubpacketHashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1601,7 +1598,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingUnknownSubpacketUnhashed() throws IOException {
public void primaryBindingUnknownSubpacketUnhashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1662,7 +1659,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingCriticalUnknownSubpacketUnhashed() throws IOException {
public void primaryBindingCriticalUnknownSubpacketUnhashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1723,7 +1720,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingUnknownNotationHashed() throws IOException {
public void primaryBindingUnknownNotationHashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1785,7 +1782,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingCriticalUnknownNotationHashed() throws IOException {
public void primaryBindingCriticalUnknownNotationHashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1847,7 +1844,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingUnknownNotationUnhashed() throws IOException {
public void primaryBindingUnknownNotationUnhashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1909,7 +1906,7 @@ public class BindingSignatureSubpacketsTest {
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void primaryBindingCriticalUnknownNotationUnhashed() throws IOException {
public void primaryBindingCriticalUnknownNotationUnhashed() throws IOException, PGPException {
String key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" +
"\n" +
@ -1969,27 +1966,38 @@ public class BindingSignatureSubpacketsTest {
expectSignatureValidationSucceeds(key, "Critical unknown notation is acceptable in unhashed area of primary key binding sig.");
}
private void expectSignatureValidationSucceeds(String key, String message) throws IOException {
PGPPublicKeyRing publicKeys = PGPainless.readKeyRing().publicKeyRing(key);
PGPSignature signature = SignatureUtils.readSignatures(sig).get(0);
private void expectSignatureValidationSucceeds(String key, String message) throws IOException, PGPException {
PGPainless api = PGPainless.getInstance();
OpenPGPCertificate certificate = api.readKey().parseCertificate(key);
try {
CertificateValidator.validateCertificateAndVerifyUninitializedSignature(signature, getSignedData(data), publicKeys, policy, validationDate);
} catch (SignatureValidationException e) {
// CHECKSTYLE:OFF
e.printStackTrace();
// CHECKSTYLE:ON
fail(message + ": " + e.getMessage());
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify().onInputStream(getSignedData(data))
.withOptions(ConsumerOptions.get(api)
.addVerificationCert(certificate)
.addVerificationOfDetachedSignatures(SignatureUtils.readSignatures(sig)));
Streams.drain(decryptionStream);
decryptionStream.close();
MessageMetadata metadata = decryptionStream.getMetadata();
if (!metadata.getRejectedSignatures().isEmpty()) {
throw metadata.getRejectedSignatures().get(0).getValidationException();
}
assertTrue(decryptionStream.getMetadata().isVerifiedSignedBy(certificate),
message);
}
private void expectSignatureValidationFails(String key, String message) throws IOException {
PGPPublicKeyRing publicKeys = PGPainless.readKeyRing().publicKeyRing(key);
PGPSignature signature = SignatureUtils.readSignatures(sig).get(0);
private void expectSignatureValidationFails(String key, String message) throws IOException, PGPException {
PGPainless api = PGPainless.getInstance();
OpenPGPCertificate certificate = api.readKey().parseCertificate(key);
assertThrows(SignatureValidationException.class, () ->
CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
signature, getSignedData(data), publicKeys, policy, validationDate),
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify().onInputStream(getSignedData(data))
.withOptions(ConsumerOptions.get(api)
.addVerificationCert(certificate)
.addVerificationOfDetachedSignatures(SignatureUtils.readSignatures(sig)));
Streams.drain(decryptionStream);
decryptionStream.close();
assertFalse(decryptionStream.getMetadata().isVerifiedSignedBy(certificate),
message);
}

View file

@ -17,6 +17,7 @@ import java.util.Date;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestTemplate;
@ -27,7 +28,6 @@ import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.decryption_verification.MessageMetadata;
import org.pgpainless.exception.SignatureValidationException;
import org.pgpainless.policy.Policy;
import org.pgpainless.signature.consumer.CertificateValidator;
import org.pgpainless.util.TestAllImplementations;
public class CertificateValidatorTest {
@ -170,16 +170,16 @@ public class CertificateValidatorTest {
Date validationDate = new Date();
String data = "Hello, World";
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
"Signature predates primary key");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
unboundSubkey, getSignedData(data), publicKeys, policy, validationDate),
"Primary key hard revoked");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
primaryKeyRevoked, getSignedData(data), publicKeys, policy, validationDate),
"Primary key hard revoked");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
primaryKeyRevalidated, getSignedData(data), publicKeys, policy, validationDate),
"Primary key hard revoked");
}
@ -321,16 +321,16 @@ public class CertificateValidatorTest {
Date validationDate = new Date();
String data = "Hello, World";
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
"Signature predates primary key");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
unboundSubkey, getSignedData(data), publicKeys, policy, validationDate),
"Signing key unbound + hard revocation");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
revokedSubkey, getSignedData(data), publicKeys, policy, validationDate),
"Primary key is hard revoked");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
revalidatedSubkey, getSignedData(data), publicKeys, policy, validationDate),
"Primary key is hard revoked");
}
@ -473,16 +473,16 @@ public class CertificateValidatorTest {
Date validationDate = new Date();
String data = "Hello World :)";
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
"Signature predates primary key");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
unboundKey, getSignedData(data), publicKeys, policy, validationDate),
"Signing key unbound + hard revocation");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
afterHardRevocation, getSignedData(data), publicKeys, policy, validationDate),
"Hard revocation invalidates key at all times");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
afterRevalidation, getSignedData(data), publicKeys, policy, validationDate),
"Hard revocation invalidates key at all times");
}
@ -624,22 +624,22 @@ public class CertificateValidatorTest {
String data = "Hello, World";
// Sig not valid, as it predates the signing key creation time
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, predatesPrimaryKey.getCreationTime()),
"Signature predates primary key creation date");
// Sig valid
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertDoesNotThrow(() -> verify(
keyIsValid, getSignedData(data), publicKeys, policy, keyIsValid.getCreationTime()),
"Signature is valid");
// Sig not valid, as the signing key is revoked
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
keyIsRevoked, getSignedData(data), publicKeys, policy, keyIsRevoked.getCreationTime()),
"Signing key is revoked at this point");
// Sig valid, as the signing key is revalidated
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertDoesNotThrow(() -> verify(
keyIsRevalidated, getSignedData(data), publicKeys, policy, keyIsRevalidated.getCreationTime()),
"Signature is valid, as signing key is revalidated");
}
@ -782,17 +782,17 @@ public class CertificateValidatorTest {
String data = "Hello, World";
Date validationDate = new Date();
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
"Signature predates primary key creation date");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
keyNotBound, getSignedData(data), publicKeys, policy, validationDate),
"Signing key is not bound at this point");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
keyRevoked, getSignedData(data), publicKeys, policy, validationDate),
"Signing key is revoked at this point");
assertDoesNotThrow(() ->
CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
verify(
valid, getSignedData(data), publicKeys, policy, validationDate),
"Signing key is revalidated");
}
@ -935,17 +935,17 @@ public class CertificateValidatorTest {
Date validationDate = new Date();
String data = "Hello, World";
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
"Signature predates primary key creation date");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertDoesNotThrow(() -> verify(
valid, getSignedData(data), publicKeys, policy, validationDate),
"Signature is valid");
assertThrows(SignatureValidationException.class, () ->
CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
verify(
revoked, getSignedData(data), publicKeys, policy, validationDate),
"Primary key is revoked");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertDoesNotThrow(() -> verify(
revalidated, getSignedData(data), publicKeys, policy, validationDate),
"Primary key is re-legitimized");
}
@ -1275,47 +1275,66 @@ public class CertificateValidatorTest {
Date validationDate = new Date();
String data = "Hello World :)";
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
sigAT0, getSignedData(data), keysA, policy, validationDate),
"Signature predates key creation time");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertDoesNotThrow(() -> verify(
sigAT1_T2, getSignedData(data), keysA, policy, validationDate),
"Key valid");
assertThrows(SignatureValidationException.class, () ->
CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
verify(
sigAT2_T3, getSignedData(data), keysA, policy, validationDate),
"Key is not valid, as subkey binding expired");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertDoesNotThrow(() -> verify(
sigAT3_now, getSignedData(data), keysA, policy, validationDate),
"Key is valid again");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
sigBT0, getSignedData(data), keysB, policy, validationDate),
"Signature predates key creation time");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertDoesNotThrow(() -> verify(
sigBT1_T2, getSignedData(data), keysB, policy, validationDate),
"Key is valid");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
sigBT2_T3, getSignedData(data), keysB, policy, validationDate),
"Primary key is not signing-capable");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertDoesNotThrow(() -> verify(
sigBT3_now, getSignedData(data), keysB, policy, validationDate),
"Key is valid again");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
sigCT0, getSignedData(data), keysC, policy, validationDate),
"Signature predates key creation time");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertDoesNotThrow(() -> verify(
sigCT1_T2, getSignedData(data), keysC, policy, validationDate),
"Key is valid");
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertThrows(SignatureValidationException.class, () -> verify(
sigCT2_T3, getSignedData(data), keysC, policy, validationDate),
"Key is revoked");
assertDoesNotThrow(() -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(
assertDoesNotThrow(() -> verify(
sigCT3_now, getSignedData(data), keysC, policy, validationDate),
"Key is valid again");
}
private void verify(PGPSignature signature, InputStream dataIn, PGPPublicKeyRing cert, Policy policy, Date validationDate) throws PGPException, IOException {
PGPainless api = PGPainless.getInstance();
OpenPGPCertificate certificate = api.toCertificate(cert);
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(dataIn)
.withOptions(ConsumerOptions.get(api)
.addVerificationOfDetachedSignature(signature)
.addVerificationCert(certificate));
Streams.drain(decryptionStream);
decryptionStream.close();
MessageMetadata metadata = decryptionStream.getMetadata();
if (metadata.hasRejectedSignatures()) {
throw metadata.getRejectedSignatures().get(0).getValidationException();
}
}
private static InputStream getSignedData(String data) {
return new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
}

View file

@ -8,17 +8,23 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;
import org.pgpainless.PGPainless;
import org.pgpainless.decryption_verification.ConsumerOptions;
import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.decryption_verification.MessageMetadata;
import org.pgpainless.exception.SignatureValidationException;
import org.pgpainless.signature.consumer.CertificateValidator;
import org.pgpainless.policy.Policy;
import org.pgpainless.util.TestAllImplementations;
public class KeyRevocationTest {
@ -153,16 +159,16 @@ public class KeyRevocationTest {
PGPSignature t2t3 = SignatureUtils.readSignatures(sigT2T3).get(0);
PGPSignature t3now = SignatureUtils.readSignatures(sigT3Now).get(0);
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(t0,
assertThrows(SignatureValidationException.class, () -> verify(t0,
new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8)),
publicKeys, PGPainless.getPolicy(), new Date()));
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(t1t2,
assertThrows(SignatureValidationException.class, () -> verify(t1t2,
new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8)),
publicKeys, PGPainless.getPolicy(), new Date()));
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(t2t3,
assertThrows(SignatureValidationException.class, () -> verify(t2t3,
new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8)),
publicKeys, PGPainless.getPolicy(), new Date()));
assertThrows(SignatureValidationException.class, () -> CertificateValidator.validateCertificateAndVerifyUninitializedSignature(t3now,
assertThrows(SignatureValidationException.class, () -> verify(t3now,
new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8)),
publicKeys, PGPainless.getPolicy(), new Date()));
}
@ -255,8 +261,29 @@ public class KeyRevocationTest {
PGPPublicKeyRing publicKeys = PGPainless.readKeyRing().publicKeyRing(key);
PGPSignature signature = SignatureUtils.readSignatures(sig).get(0);
CertificateValidator.validateCertificateAndVerifyUninitializedSignature(signature,
verify(signature,
new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8)),
publicKeys, PGPainless.getPolicy(), new Date());
}
private void verify(PGPSignature signature, InputStream dataIn, PGPPublicKeyRing cert, Policy policy, Date validationDate) throws PGPException, IOException {
PGPainless api = PGPainless.getInstance();
OpenPGPCertificate certificate = api.toCertificate(cert);
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(dataIn)
.withOptions(ConsumerOptions.get(api)
.addVerificationOfDetachedSignature(signature)
.addVerificationCert(certificate));
Streams.drain(decryptionStream);
decryptionStream.close();
MessageMetadata metadata = decryptionStream.getMetadata();
if (metadata.hasRejectedSignatures()) {
throw metadata.getRejectedSignatures().get(0).getValidationException();
}
}
}