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

Remove SignerUserId check, Policy setting only via constructor parameter

This commit is contained in:
Paul Schaub 2025-03-24 12:40:43 +01:00
parent 4c180bbd59
commit 221d329254
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
16 changed files with 125 additions and 348 deletions

View file

@ -17,7 +17,6 @@ import org.bouncycastle.openpgp.api.OpenPGPKey
import org.bouncycastle.openpgp.api.OpenPGPKeyGenerator
import org.bouncycastle.openpgp.api.OpenPGPKeyReader
import org.bouncycastle.openpgp.api.bc.BcOpenPGPApi
import org.bouncycastle.openpgp.api.bc.BcOpenPGPImplementation
import org.pgpainless.algorithm.OpenPGPKeyVersion
import org.pgpainless.bouncycastle.PolicyAdapter
import org.pgpainless.bouncycastle.extensions.setAlgorithmSuite
@ -35,10 +34,14 @@ import org.pgpainless.util.ArmorUtils
class PGPainless(
val implementation: OpenPGPImplementation = OpenPGPImplementation.getInstance(),
var algorithmPolicy: Policy = Policy()
val algorithmPolicy: Policy = Policy()
) {
private var api: OpenPGPApi
constructor(
algorithmPolicy: Policy
) : this(OpenPGPImplementation.getInstance(), algorithmPolicy)
private val api: OpenPGPApi
init {
implementation.setPolicy(
@ -53,7 +56,11 @@ class PGPainless(
): KeyRingTemplates = KeyRingTemplates(version, creationTime, this)
@JvmOverloads
fun buildKey(
fun buildKey(version: OpenPGPKeyVersion = OpenPGPKeyVersion.v4): KeyRingBuilder =
KeyRingBuilder(version, this)
@JvmOverloads
fun _buildKey(
version: OpenPGPKeyVersion = OpenPGPKeyVersion.v4,
creationTime: Date = Date()
): OpenPGPKeyGenerator =
@ -108,8 +115,6 @@ class PGPainless(
@Volatile private var instance: PGPainless? = null
@JvmStatic fun newInstance(): PGPainless = PGPainless(BcOpenPGPImplementation(), Policy())
@JvmStatic
fun getInstance(): PGPainless =
instance ?: synchronized(this) { instance ?: PGPainless().also { instance = it } }

View file

@ -26,6 +26,7 @@ import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData
import org.bouncycastle.openpgp.PGPSessionKey
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.PGPSignatureException
import org.bouncycastle.openpgp.api.OpenPGPCertificate
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.bouncycastle.openpgp.api.OpenPGPKey.OpenPGPPrivateKey
@ -870,6 +871,10 @@ class OpenPgpMessageInputStream(
} catch (e: SignatureValidationException) {
layer.addRejectedOnePassSignature(
SignatureVerification.Failure(verification, e))
} catch (e: PGPSignatureException) {
layer.addRejectedOnePassSignature(
SignatureVerification.Failure(
verification, SignatureValidationException(e.message, e)))
}
break
}
@ -973,10 +978,12 @@ class OpenPgpMessageInputStream(
SignatureValidator.signatureWasCreatedInBounds(
options.getVerifyNotBefore(), options.getVerifyNotAfter())
.verify(detached.signature)
if (detached.verify() && detached.isValid(api.implementation.policy())) {
layer.addVerifiedDetachedSignature(verification)
} else {
if (!detached.verify()) {
throw SignatureValidationException("Incorrect detached signature.")
} else if (!detached.isValid(api.implementation.policy())) {
throw SignatureValidationException("Detached signature is not valid.")
} else {
layer.addVerifiedDetachedSignature(verification)
}
} catch (e: MalformedOpenPGPSignatureException) {
throw SignatureValidationException("Malformed detached signature.", e)

View file

@ -7,7 +7,6 @@ package org.pgpainless.key.generation
import java.util.*
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.pgpainless.PGPainless
import org.pgpainless.PGPainless.Companion.buildKeyRing
import org.pgpainless.algorithm.KeyFlag
import org.pgpainless.algorithm.OpenPGPKeyVersion
import org.pgpainless.key.generation.KeySpec.Companion.getBuilder
@ -38,7 +37,7 @@ class KeyRingTemplates(
length: RsaLength,
passphrase: Passphrase = Passphrase.emptyPassphrase()
): OpenPGPKey =
buildKeyRing(version, api)
api.buildKey(version)
.apply {
setPrimaryKey(
getBuilder(KeyType.RSA(length), KeyFlag.CERTIFY_OTHER)
@ -90,7 +89,7 @@ class KeyRingTemplates(
length: RsaLength,
passphrase: Passphrase = Passphrase.emptyPassphrase()
): OpenPGPKey =
buildKeyRing(version)
api.buildKey(version)
.apply {
setPrimaryKey(
getBuilder(
@ -144,7 +143,7 @@ class KeyRingTemplates(
val encryptionKeyType =
if (version == OpenPGPKeyVersion.v6) KeyType.X25519()
else KeyType.XDH_LEGACY(XDHLegacySpec._X25519)
return buildKeyRing(version)
return api.buildKey(version)
.apply {
setPrimaryKey(
getBuilder(signingKeyType, KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
@ -197,7 +196,7 @@ class KeyRingTemplates(
val encryptionKeyType =
if (version == OpenPGPKeyVersion.v6) KeyType.X25519()
else KeyType.XDH_LEGACY(XDHLegacySpec._X25519)
return buildKeyRing(version)
return api.buildKey(version)
.apply {
setPrimaryKey(
getBuilder(signingKeyType, KeyFlag.CERTIFY_OTHER)

View file

@ -36,7 +36,6 @@ class Policy(
NotationRegistry(),
AlgorithmSuite.defaultAlgorithmSuite)
var signerUserIdValidationLevel = SignerUserIdValidationLevel.DISABLED
var enableKeyParameterValidation = false
fun copy() = Builder(this)
@ -493,9 +492,6 @@ class Policy(
keyProtectionSettings,
notationRegistry,
keyGenerationAlgorithmSuite)
.apply {
enableKeyParameterValidation = origin.enableKeyParameterValidation
signerUserIdValidationLevel = origin.signerUserIdValidationLevel
}
.apply { enableKeyParameterValidation = origin.enableKeyParameterValidation }
}
}

View file

@ -211,7 +211,7 @@ public class ModifiedPublicKeysInvestigation {
@Test
public void assertModifiedDSAKeyThrowsKeyIntegrityException() throws IOException {
PGPainless api = PGPainless.newInstance();
PGPainless api = PGPainless.getInstance();
Policy policy = api.getAlgorithmPolicy();
policy.setEnableKeyParameterValidation(true);
@ -226,7 +226,7 @@ public class ModifiedPublicKeysInvestigation {
@Test
public void assertModifiedElGamalKeyThrowsKeyIntegrityException() throws IOException {
PGPainless api = PGPainless.newInstance();
PGPainless api = PGPainless.getInstance();
Policy policy = api.getAlgorithmPolicy();
policy.setEnableKeyParameterValidation(true);
@ -239,7 +239,7 @@ public class ModifiedPublicKeysInvestigation {
@Test
public void assertInjectedKeyRingFailsToUnlockPrimaryKey() throws IOException {
PGPainless api = PGPainless.newInstance();
PGPainless api = PGPainless.getInstance();
Policy policy = api.getAlgorithmPolicy();
policy.setEnableKeyParameterValidation(true);
@ -252,7 +252,7 @@ public class ModifiedPublicKeysInvestigation {
@Test
public void assertCannotUnlockElGamalPrimaryKeyDueToDummyS2K() throws IOException {
PGPainless api = PGPainless.newInstance();
PGPainless api = PGPainless.getInstance();
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword("12345678"));
OpenPGPKey elgamal = api.readKey().parseKey(ELGAMAL);

View file

@ -1,174 +0,0 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.decryption_verification;
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.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Iterator;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.bcpg.BCPGOutputStream;
import org.bouncycastle.bcpg.CompressionAlgorithmTags;
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
import org.bouncycastle.openpgp.PGPCompressedDataGenerator;
import org.bouncycastle.openpgp.PGPEncryptedDataGenerator;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPLiteralDataGenerator;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureGenerator;
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.bouncycastle.openpgp.operator.PGPDataEncryptorBuilder;
import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder;
import org.bouncycastle.openpgp.operator.bc.BcPGPDataEncryptorBuilder;
import org.bouncycastle.openpgp.operator.bc.BcPublicKeyKeyEncryptionMethodGenerator;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.key.protection.UnlockSecretKey;
import org.pgpainless.policy.Policy;
import org.pgpainless.util.Passphrase;
public class WrongSignerUserIdTest {
private static final String KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
" Comment: Alice's OpenPGP Transferable Secret Key\n" +
" Comment: https://www.ietf.org/id/draft-bre-openpgp-samples-01.html\n" +
"\n" +
" lFgEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/U\n" +
" b7O1u10AAP9XBeW6lzGOLx7zHH9AsUDUTb2pggYGMzd0P3ulJ2AfvQ4RtCZBbGlj\n" +
" ZSBMb3ZlbGFjZSA8YWxpY2VAb3BlbnBncC5leGFtcGxlPoiQBBMWCAA4AhsDBQsJ\n" +
" CAcCBhUKCQgLAgQWAgMBAh4BAheAFiEE64W7X6M6deFelE5j8jFVDE9H444FAl2l\n" +
" nzoACgkQ8jFVDE9H447pKwD6A5xwUqIDprBzrHfahrImaYEZzncqb25vkLV2arYf\n" +
" a78A/R3AwtLQvjxwLDuzk4dUtUwvUYibL2sAHwj2kGaHnfICnF0EXEcE6RIKKwYB\n" +
" BAGXVQEFAQEHQEL/BiGtq0k84Km1wqQw2DIikVYrQrMttN8d7BPfnr4iAwEIBwAA\n" +
" /3/xFPG6U17rhTuq+07gmEvaFYKfxRB6sgAYiW6TMTpQEK6IeAQYFggAIBYhBOuF\n" +
" u1+jOnXhXpROY/IxVQxPR+OOBQJcRwTpAhsMAAoJEPIxVQxPR+OOWdABAMUdSzpM\n" +
" hzGs1O0RkWNQWbUzQ8nUOeD9wNbjE3zR+yfRAQDbYqvtWQKN4AQLTxVJN5X5AWyb\n" +
" Pnn+We1aTBhaGa86AQ==\n" +
" =n8OM\n" +
" -----END PGP PRIVATE KEY BLOCK-----";
private static final String USER_ID = "Alice Lovelace <alice@openpgp.example>";
@Test
public void verificationSucceedsWithDisabledCheck() throws PGPException, IOException {
executeTest(false, true);
}
@Test
public void verificationFailsWithEnabledCheck() throws PGPException, IOException {
executeTest(true, false);
}
@AfterAll
public static void resetDefault() {
PGPainless.getPolicy().setSignerUserIdValidationLevel(Policy.SignerUserIdValidationLevel.DISABLED);
}
public void executeTest(boolean enableCheck, boolean expectSucessfulVerification) throws IOException, PGPException {
PGPainless.getPolicy().setSignerUserIdValidationLevel(enableCheck ? Policy.SignerUserIdValidationLevel.STRICT : Policy.SignerUserIdValidationLevel.DISABLED);
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(KEY);
assertEquals(USER_ID, secretKeys.getPublicKey().getUserIDs().next());
String messageWithWrongUserId = generateTestMessage(secretKeys);
verifyTestMessage(messageWithWrongUserId, secretKeys, expectSucessfulVerification);
}
private void verifyTestMessage(String messageWithWrongUserId, PGPSecretKeyRing secretKeys, boolean expectSuccessfulVerification) throws IOException, PGPException {
PGPPublicKeyRing certificate = PGPainless.extractCertificate(secretKeys);
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify().onInputStream(
new ByteArrayInputStream(messageWithWrongUserId.getBytes(StandardCharsets.UTF_8)))
.withOptions(ConsumerOptions.get()
.addDecryptionKey(secretKeys)
.addVerificationCert(certificate));
ByteArrayOutputStream out = new ByteArrayOutputStream();
Streams.pipeAll(decryptionStream, out);
decryptionStream.close();
MessageMetadata metadata = decryptionStream.getMetadata();
if (expectSuccessfulVerification) {
assertTrue(metadata.isVerifiedSigned());
} else {
assertFalse(metadata.isVerifiedSigned());
}
}
private String generateTestMessage(PGPSecretKeyRing secretKeys) throws PGPException, IOException {
PGPPublicKeyRing certificate = PGPainless.extractCertificate(secretKeys);
assertEquals(USER_ID, certificate.getPublicKey().getUserIDs().next());
Iterator<PGPSecretKey> keys = secretKeys.getSecretKeys();
PGPSecretKey signingKey = keys.next();
PGPSecretKey encryptionKey = keys.next();
PGPPrivateKey signingPrivKey = UnlockSecretKey.unlockSecretKey(signingKey, Passphrase.emptyPassphrase());
// ARMOR
ByteArrayOutputStream cipherText = new ByteArrayOutputStream();
ArmoredOutputStream armorOut = new ArmoredOutputStream(cipherText);
// ENCRYPTION
PGPDataEncryptorBuilder dataEncryptorBuilder = new BcPGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_256);
dataEncryptorBuilder.setWithIntegrityPacket(true);
PGPEncryptedDataGenerator encDataGenerator = new PGPEncryptedDataGenerator(dataEncryptorBuilder);
encDataGenerator.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(encryptionKey.getPublicKey()));
OutputStream encStream = encDataGenerator.open(armorOut, new byte[4096]);
// COMPRESSION
PGPCompressedDataGenerator compressedDataGenerator = new PGPCompressedDataGenerator(CompressionAlgorithmTags.ZLIB);
BCPGOutputStream bOut = new BCPGOutputStream(compressedDataGenerator.open(encStream));
// SIGNING
PGPSignatureGenerator sigGen = new PGPSignatureGenerator(
new BcPGPContentSignerBuilder(signingKey.getPublicKey().getAlgorithm(), HashAlgorithm.SHA512.getAlgorithmId()));
sigGen.init(PGPSignature.BINARY_DOCUMENT, signingPrivKey);
PGPSignatureSubpacketGenerator subpacketGenerator = new PGPSignatureSubpacketGenerator();
subpacketGenerator.addSignerUserID(false, "Albert Lovelace <albert@openpgp.example>");
sigGen.setHashedSubpackets(subpacketGenerator.generate());
sigGen.generateOnePassVersion(false).encode(bOut);
// LITERAL DATA
PGPLiteralDataGenerator literalDataGenerator = new PGPLiteralDataGenerator();
OutputStream lOut = literalDataGenerator.open(bOut, PGPLiteralDataGenerator.BINARY,
PGPLiteralDataGenerator.CONSOLE, new Date(), new byte[4096]);
// write msg
ByteArrayInputStream msgIn = new ByteArrayInputStream("Hello, World!\n".getBytes(StandardCharsets.UTF_8));
int ch;
while ((ch = msgIn.read()) >= 0) {
lOut.write(ch);
sigGen.update((byte) ch);
}
lOut.close();
sigGen.generate().encode(bOut);
compressedDataGenerator.close();
encStream.close();
armorOut.close();
return cipherText.toString();
}
}

View file

@ -23,7 +23,6 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;
import org.pgpainless.PGPainless;
@ -39,7 +38,6 @@ import org.pgpainless.key.generation.type.rsa.RsaLength;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.key.protection.UnprotectedKeysProtector;
import org.pgpainless.key.util.KeyRingUtils;
import org.pgpainless.policy.Policy;
import org.pgpainless.util.ArmoredOutputStreamFactory;
import org.pgpainless.util.TestAllImplementations;
@ -57,18 +55,14 @@ public class EncryptDecryptTest {
"Unfold the imagined happiness that both\n" +
"Receive in either by this dear encounter.";
@BeforeEach
public void setDefaultPolicy() {
PGPainless.getInstance().setAlgorithmPolicy(new Policy());
}
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void freshKeysRsaToRsaTest()
throws PGPException, IOException {
PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("romeo@montague.lit", RsaLength._3072)
PGPainless api = PGPainless.getInstance();
PGPSecretKeyRing sender = api.generateKey().simpleRsaKeyRing("romeo@montague.lit", RsaLength._3072)
.getPGPSecretKeyRing();
PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("juliet@capulet.lit", RsaLength._3072)
PGPSecretKeyRing recipient = api.generateKey().simpleRsaKeyRing("juliet@capulet.lit", RsaLength._3072)
.getPGPSecretKeyRing();
encryptDecryptForSecretKeyRings(sender, recipient);
@ -78,9 +72,10 @@ public class EncryptDecryptTest {
@ExtendWith(TestAllImplementations.class)
public void freshKeysEcToEcTest()
throws IOException, PGPException {
PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleEcKeyRing("romeo@montague.lit")
PGPainless api = PGPainless.getInstance();
PGPSecretKeyRing sender = api.generateKey().simpleEcKeyRing("romeo@montague.lit")
.getPGPSecretKeyRing();
PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleEcKeyRing("juliet@capulet.lit")
PGPSecretKeyRing recipient = api.generateKey().simpleEcKeyRing("juliet@capulet.lit")
.getPGPSecretKeyRing();
encryptDecryptForSecretKeyRings(sender, recipient);
@ -90,9 +85,10 @@ public class EncryptDecryptTest {
@ExtendWith(TestAllImplementations.class)
public void freshKeysEcToRsaTest()
throws PGPException, IOException {
PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleEcKeyRing("romeo@montague.lit")
PGPainless api = PGPainless.getInstance();
PGPSecretKeyRing sender = api.generateKey().simpleEcKeyRing("romeo@montague.lit")
.getPGPSecretKeyRing();
PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("juliet@capulet.lit", RsaLength._3072)
PGPSecretKeyRing recipient = api.generateKey().simpleRsaKeyRing("juliet@capulet.lit", RsaLength._3072)
.getPGPSecretKeyRing();
encryptDecryptForSecretKeyRings(sender, recipient);
@ -102,9 +98,10 @@ public class EncryptDecryptTest {
@ExtendWith(TestAllImplementations.class)
public void freshKeysRsaToEcTest()
throws PGPException, IOException {
PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("romeo@montague.lit", RsaLength._3072)
PGPainless api = PGPainless.getInstance();
PGPSecretKeyRing sender = api.generateKey().simpleRsaKeyRing("romeo@montague.lit", RsaLength._3072)
.getPGPSecretKeyRing();
PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleEcKeyRing("juliet@capulet.lit")
PGPSecretKeyRing recipient = api.generateKey().simpleEcKeyRing("juliet@capulet.lit")
.getPGPSecretKeyRing();
encryptDecryptForSecretKeyRings(sender, recipient);

View file

@ -10,8 +10,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Arrays;
import java.util.HashMap;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.HashAlgorithm;
@ -36,16 +34,6 @@ import org.pgpainless.util.NotationRegistry;
*/
public class ManagePolicy {
/**
* Reset PGPainless' policy class to default values.
*/
@BeforeEach
@AfterEach
public void resetPolicy() {
// Policy for hash algorithms in non-revocation signatures
PGPainless.getInstance().setAlgorithmPolicy(new Policy());
}
/**
* {@link HashAlgorithm Hash Algorithms} may get outdated with time. {@link HashAlgorithm#SHA1} is a prominent
* example for an algorithm that is nowadays considered unsafe to use and which shall be avoided.
@ -62,8 +50,9 @@ public class ManagePolicy {
*/
@Test
public void setCustomSignatureHashPolicy() {
PGPainless api = PGPainless.getInstance();
// Get PGPainless' policy
Policy oldPolicy = PGPainless.getInstance().getAlgorithmPolicy();
Policy oldPolicy = api.getAlgorithmPolicy();
Policy.HashAlgorithmPolicy sigHashAlgoPolicy = oldPolicy.getDataSignatureHashAlgorithmPolicy();
assertTrue(sigHashAlgoPolicy.isAcceptable(HashAlgorithm.SHA512));
@ -77,17 +66,12 @@ public class ManagePolicy {
// List of acceptable hash algorithms
Arrays.asList(HashAlgorithm.SHA512, HashAlgorithm.SHA384, HashAlgorithm.SHA256, HashAlgorithm.SHA224, HashAlgorithm.SHA1));
// Set the hash algo policy as policy for non-revocation signatures
PGPainless.getInstance().setAlgorithmPolicy(
oldPolicy.copy().withDataSignatureHashAlgorithmPolicy(customPolicy).build()
);
api = new PGPainless(oldPolicy.copy().withDataSignatureHashAlgorithmPolicy(customPolicy).build());
sigHashAlgoPolicy = PGPainless.getInstance().getAlgorithmPolicy().getDataSignatureHashAlgorithmPolicy();
sigHashAlgoPolicy = api.getAlgorithmPolicy().getDataSignatureHashAlgorithmPolicy();
assertTrue(sigHashAlgoPolicy.isAcceptable(HashAlgorithm.SHA512));
// SHA-1 is now acceptable as well
assertTrue(sigHashAlgoPolicy.isAcceptable(HashAlgorithm.SHA1));
// reset old policy
PGPainless.getInstance().setAlgorithmPolicy(oldPolicy);
}
/**
@ -100,7 +84,8 @@ public class ManagePolicy {
*/
@Test
public void setCustomPublicKeyAlgorithmPolicy() {
Policy oldPolicy = PGPainless.getInstance().getAlgorithmPolicy();
PGPainless api = PGPainless.getInstance();
Policy oldPolicy = api.getAlgorithmPolicy();
Policy.PublicKeyAlgorithmPolicy pkAlgorithmPolicy = oldPolicy.getPublicKeyAlgorithmPolicy();
assertTrue(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 4096));
assertTrue(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 2048));
@ -115,17 +100,15 @@ public class ManagePolicy {
put(PublicKeyAlgorithm.RSA_GENERAL, 3000);
}}
);
PGPainless.getInstance().setAlgorithmPolicy(oldPolicy.copy().withPublicKeyAlgorithmPolicy(customPolicy).build());
pkAlgorithmPolicy = PGPainless.getInstance().getAlgorithmPolicy().getPublicKeyAlgorithmPolicy();
api = new PGPainless(oldPolicy.copy().withPublicKeyAlgorithmPolicy(customPolicy).build());
pkAlgorithmPolicy = api.getAlgorithmPolicy().getPublicKeyAlgorithmPolicy();
assertTrue(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 4096));
// RSA 2048 is no longer acceptable
assertFalse(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 2048));
// ECDSA is no longer acceptable, since it is no longer included in the policy at all
assertFalse(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.ECDSA, 256));
// Reset policy
PGPainless.getInstance().setAlgorithmPolicy(oldPolicy);
}
/**

View file

@ -15,8 +15,8 @@ import java.nio.charset.StandardCharsets;
import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
@ -42,15 +42,15 @@ public class GenerateKeyWithoutPrimaryKeyFlagsTest {
@Test
public void generateKeyWithoutCertifyKeyFlag_cannotCertifyThirdParties() throws PGPException, IOException {
PGPSecretKeyRing secretKeys = PGPainless.buildKeyRing().setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519)))
PGPainless api = PGPainless.getInstance();
OpenPGPKey key = api.buildKey().setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519)))
.addSubkey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.SIGN_DATA))
.addSubkey(KeySpec.getBuilder(KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS))
.addUserId("Alice")
.build()
.getPGPSecretKeyRing();
PGPPublicKeyRing cert = PGPainless.extractCertificate(secretKeys);
.build();
OpenPGPCertificate cert = key.toCertificate();
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
KeyRingInfo info = api.inspect(key);
assertTrue(info.getValidUserIds().contains("Alice"));
KeyIdentifier primaryKeyIdentifier = info.getKeyIdentifier();
@ -59,18 +59,18 @@ public class GenerateKeyWithoutPrimaryKeyFlagsTest {
assertFalse(info.isUsableForThirdPartyCertification());
// Key without CERTIFY_OTHER flag cannot be used to certify other keys
PGPPublicKeyRing thirdPartyCert = TestKeys.getCryptiePublicKeyRing();
OpenPGPCertificate thirdPartyCert = TestKeys.getCryptieCertificate();
assertThrows(KeyException.UnacceptableThirdPartyCertificationKeyException.class, () ->
PGPainless.certify().certificate(thirdPartyCert)
.withKey(secretKeys, SecretKeyRingProtector.unprotectedKeys()));
api.generateCertification().certificate(thirdPartyCert)
.withKey(key, SecretKeyRingProtector.unprotectedKeys()));
// Key without CERTIFY_OTHER flags is usable for encryption and signing
ByteArrayOutputStream ciphertext = new ByteArrayOutputStream();
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
EncryptionStream encryptionStream = api.generateMessage()
.onOutputStream(ciphertext)
.withOptions(ProducerOptions.signAndEncrypt(
EncryptionOptions.get().addRecipient(cert),
SigningOptions.get().addInlineSignature(SecretKeyRingProtector.unprotectedKeys(), secretKeys, DocumentSignatureType.BINARY_DOCUMENT)
SigningOptions.get().addInlineSignature(SecretKeyRingProtector.unprotectedKeys(), key, DocumentSignatureType.BINARY_DOCUMENT)
));
encryptionStream.write("Hello, World!\n".getBytes(StandardCharsets.UTF_8));
encryptionStream.close();
@ -79,7 +79,7 @@ public class GenerateKeyWithoutPrimaryKeyFlagsTest {
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(ciphertext.toByteArray()))
.withOptions(ConsumerOptions.get().addDecryptionKey(secretKeys)
.withOptions(ConsumerOptions.get().addDecryptionKey(key)
.addVerificationCert(cert));
ByteArrayOutputStream plaintext = new ByteArrayOutputStream();

View file

@ -18,7 +18,6 @@ import org.pgpainless.algorithm.OpenPGPKeyVersion;
import org.pgpainless.algorithm.PublicKeyAlgorithm;
import org.pgpainless.key.generation.type.rsa.RsaLength;
import org.pgpainless.key.protection.KeyRingProtectionSettings;
import org.pgpainless.policy.Policy;
import java.io.IOException;
@ -31,7 +30,8 @@ public class GenerateV6KeyTest {
@Test
public void generateModernV6Key() {
OpenPGPKey key = PGPainless.generateKeyRing(OpenPGPKeyVersion.v6)
PGPainless api = PGPainless.getInstance();
OpenPGPKey key = api.generateKey(OpenPGPKeyVersion.v6)
.modernKeyRing("Alice <alice@example.org>");
assertEquals(3, key.getKeys().size());
@ -54,7 +54,7 @@ public class GenerateV6KeyTest {
@Test
public void buildMinimalEd25519V6Key() throws PGPException {
OpenPGPKey key = PGPainless.getInstance().buildKey(OpenPGPKeyVersion.v6)
OpenPGPKey key = PGPainless.getInstance()._buildKey(OpenPGPKeyVersion.v6)
.withPrimaryKey(PGPKeyPairGenerator::generateEd25519KeyPair, new SignatureParameters.Callback() {
@Override
public SignatureParameters apply(SignatureParameters parameters) {
@ -87,7 +87,7 @@ public class GenerateV6KeyTest {
@Test
public void buildCompositeCurve25519V6Key()
throws PGPException, IOException {
OpenPGPKey key = PGPainless.getInstance().buildKey(OpenPGPKeyVersion.v6)
OpenPGPKey key = PGPainless.getInstance()._buildKey(OpenPGPKeyVersion.v6)
.withPrimaryKey(PGPKeyPairGenerator::generateEd25519KeyPair)
.addSigningSubkey(PGPKeyPairGenerator::generateEd25519KeyPair)
.addEncryptionSubkey(PGPKeyPairGenerator::generateX25519KeyPair)
@ -138,20 +138,19 @@ public class GenerateV6KeyTest {
@Test
public void generateAEADProtectedModernKey()
throws IOException, PGPException {
Policy oldPolicy = PGPainless.getInstance().getAlgorithmPolicy();
PGPainless api = PGPainless.getInstance();
// Change Policy to use AEAD for secret key protection
PGPainless.getInstance().setAlgorithmPolicy(
oldPolicy.copy().withKeyProtectionSettings(KeyRingProtectionSettings.aead()).build()
);
api = new PGPainless(api.getAlgorithmPolicy().copy()
.withKeyProtectionSettings(KeyRingProtectionSettings.aead()).build());
OpenPGPKey key = PGPainless.getInstance()
OpenPGPKey key = api
.generateKey(OpenPGPKeyVersion.v6)
.modernKeyRing("Alice <alice@example.com>", "p455w0rd");
String armored = key.toAsciiArmoredString();
OpenPGPKey parsed = PGPainless.getInstance().readKey().parseKey(armored);
OpenPGPKey parsed = api.readKey().parseKey(armored);
OpenPGPKey.OpenPGPSecretKey primaryKey = key.getPrimarySecretKey();
assertEquals(SecretKeyPacket.USAGE_AEAD, primaryKey.getPGPSecretKey().getS2KUsage());
@ -160,7 +159,5 @@ public class GenerateV6KeyTest {
assertNotNull(privateKey);
assertEquals(armored, parsed.toAsciiArmoredString());
PGPainless.getInstance().setAlgorithmPolicy(oldPolicy);
}
}

View file

@ -21,20 +21,15 @@ public class GeneratingWeakKeyThrowsTest {
@Test
public void refuseToGenerateWeakPrimaryKeyTest() {
// ensure we have default public key algorithm policy set
PGPainless.getInstance().setAlgorithmPolicy(new Policy());
assertThrows(IllegalArgumentException.class, () ->
PGPainless.buildKeyRing()
PGPainless.getInstance().buildKey()
.setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._1024),
KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)));
}
@Test
public void refuseToAddWeakSubkeyDuringGenerationTest() {
// ensure we have default public key algorithm policy set
PGPainless.getInstance().setAlgorithmPolicy(new Policy());
KeyRingBuilder kb = PGPainless.buildKeyRing()
KeyRingBuilder kb = PGPainless.getInstance().buildKey()
.setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._4096),
KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA));
@ -46,23 +41,19 @@ public class GeneratingWeakKeyThrowsTest {
@Test
public void allowToAddWeakKeysWithWeakPolicy() {
// set a weak algorithm policy
PGPainless api = PGPainless.getInstance();
Map<PublicKeyAlgorithm, Integer> bitStrengths = new HashMap<>();
bitStrengths.put(PublicKeyAlgorithm.RSA_GENERAL, 512);
Policy oldPolicy = PGPainless.getPolicy();
PGPainless.getInstance().setAlgorithmPolicy(oldPolicy.copy()
.withPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(bitStrengths))
.build());
Policy oldPolicy = api.getAlgorithmPolicy();
api = new PGPainless(oldPolicy.copy().withPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(bitStrengths)).build());
PGPainless.buildKeyRing()
api.buildKey()
.setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._4096),
KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA))
.addSubkey(KeySpec.getBuilder(KeyType.RSA(RsaLength._1024),
KeyFlag.ENCRYPT_COMMS))
.addUserId("Henry")
.build();
// reset public key algorithm policy
PGPainless.getInstance().setAlgorithmPolicy(oldPolicy);
}
}

View file

@ -34,7 +34,7 @@ public class RefuseToAddWeakSubkeyTest {
Policy adjusted = oldPolicy.copy().withPublicKeyAlgorithmPolicy(
Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy()
).build();
api.setAlgorithmPolicy(adjusted);
api = new PGPainless(adjusted);
OpenPGPKey secretKeys = api.generateKey()
.modernKeyRing("Alice");
@ -43,7 +43,6 @@ public class RefuseToAddWeakSubkeyTest {
assertThrows(IllegalArgumentException.class, () ->
editor.addSubKey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys()));
api.setAlgorithmPolicy(oldPolicy);
}
@Test
@ -75,7 +74,7 @@ public class RefuseToAddWeakSubkeyTest {
minimalBitStrengths.put(PublicKeyAlgorithm.DIFFIE_HELLMAN, 2000);
// §7.2.2
minimalBitStrengths.put(PublicKeyAlgorithm.ECDH, 250);
api.setAlgorithmPolicy(oldPolicy.copy()
api = new PGPainless(oldPolicy.copy()
.withPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(minimalBitStrengths))
.build());
@ -88,8 +87,5 @@ public class RefuseToAddWeakSubkeyTest {
.done();
assertEquals(2, api.inspect(secretKeys).getEncryptionSubkeys(EncryptionPurpose.ANY).size());
// reset default policy
api.setAlgorithmPolicy(oldPolicy);
}
}

View file

@ -6,7 +6,6 @@ package org.pgpainless.policy;
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.util.Arrays;
@ -205,9 +204,4 @@ public class PolicyTest {
public void testUnknownPublicKeyAlgorithmIsNotAcceptable() {
assertFalse(policy.getPublicKeyAlgorithmPolicy().isAcceptable(-1, 4096));
}
@Test
public void setNullSignerUserIdValidationLevelThrows() {
assertThrows(NullPointerException.class, () -> policy.setSignerUserIdValidationLevel(null));
}
}

View file

@ -12,7 +12,6 @@ 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;
@ -27,7 +26,6 @@ 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.policy.Policy;
import org.pgpainless.util.TestAllImplementations;
public class CertificateValidatorTest {
@ -166,21 +164,19 @@ public class CertificateValidatorTest {
PGPSignature primaryKeyRevoked = SignatureUtils.readSignatures(sigPrimaryKeyRevoked).get(0);
PGPSignature primaryKeyRevalidated = SignatureUtils.readSignatures(sigPrimaryKeyRevalidated).get(0);
Policy policy = PGPainless.getPolicy();
Date validationDate = new Date();
String data = "Hello, World";
assertThrows(SignatureValidationException.class, () -> verify(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
predatesPrimaryKey, getSignedData(data), publicKeys),
"Signature predates primary key");
assertThrows(SignatureValidationException.class, () -> verify(
unboundSubkey, getSignedData(data), publicKeys, policy, validationDate),
unboundSubkey, getSignedData(data), publicKeys),
"Primary key hard revoked");
assertThrows(SignatureValidationException.class, () -> verify(
primaryKeyRevoked, getSignedData(data), publicKeys, policy, validationDate),
primaryKeyRevoked, getSignedData(data), publicKeys),
"Primary key hard revoked");
assertThrows(SignatureValidationException.class, () -> verify(
primaryKeyRevalidated, getSignedData(data), publicKeys, policy, validationDate),
primaryKeyRevalidated, getSignedData(data), publicKeys),
"Primary key hard revoked");
}
@ -317,21 +313,19 @@ public class CertificateValidatorTest {
PGPSignature revokedSubkey = SignatureUtils.readSignatures(sigSubkeyRevoked).get(0);
PGPSignature revalidatedSubkey = SignatureUtils.readSignatures(sigSubkeyRevalidated).get(0);
Policy policy = PGPainless.getPolicy();
Date validationDate = new Date();
String data = "Hello, World";
assertThrows(SignatureValidationException.class, () -> verify(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
predatesPrimaryKey, getSignedData(data), publicKeys),
"Signature predates primary key");
assertThrows(SignatureValidationException.class, () -> verify(
unboundSubkey, getSignedData(data), publicKeys, policy, validationDate),
unboundSubkey, getSignedData(data), publicKeys),
"Signing key unbound + hard revocation");
assertThrows(SignatureValidationException.class, () -> verify(
revokedSubkey, getSignedData(data), publicKeys, policy, validationDate),
revokedSubkey, getSignedData(data), publicKeys),
"Primary key is hard revoked");
assertThrows(SignatureValidationException.class, () -> verify(
revalidatedSubkey, getSignedData(data), publicKeys, policy, validationDate),
revalidatedSubkey, getSignedData(data), publicKeys),
"Primary key is hard revoked");
}
@ -469,21 +463,19 @@ public class CertificateValidatorTest {
PGPSignature afterHardRevocation = SignatureUtils.readSignatures(sigAfterHardRevocation).get(0);
PGPSignature afterRevalidation = SignatureUtils.readSignatures(sigAfterRevalidation).get(0);
Policy policy = PGPainless.getPolicy();
Date validationDate = new Date();
String data = "Hello World :)";
assertThrows(SignatureValidationException.class, () -> verify(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
predatesPrimaryKey, getSignedData(data), publicKeys),
"Signature predates primary key");
assertThrows(SignatureValidationException.class, () -> verify(
unboundKey, getSignedData(data), publicKeys, policy, validationDate),
unboundKey, getSignedData(data), publicKeys),
"Signing key unbound + hard revocation");
assertThrows(SignatureValidationException.class, () -> verify(
afterHardRevocation, getSignedData(data), publicKeys, policy, validationDate),
afterHardRevocation, getSignedData(data), publicKeys),
"Hard revocation invalidates key at all times");
assertThrows(SignatureValidationException.class, () -> verify(
afterRevalidation, getSignedData(data), publicKeys, policy, validationDate),
afterRevalidation, getSignedData(data), publicKeys),
"Hard revocation invalidates key at all times");
}
@ -620,27 +612,26 @@ public class CertificateValidatorTest {
PGPSignature keyIsValid = SignatureUtils.readSignatures(sigKeyIsValid).get(0);
PGPSignature keyIsRevoked = SignatureUtils.readSignatures(sigKeyIsRevoked).get(0);
PGPSignature keyIsRevalidated = SignatureUtils.readSignatures(sigKeyIsRevalidated).get(0);
Policy policy = PGPainless.getPolicy();
String data = "Hello, World";
// Sig not valid, as it predates the signing key creation time
assertThrows(SignatureValidationException.class, () -> verify(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, predatesPrimaryKey.getCreationTime()),
predatesPrimaryKey, getSignedData(data), publicKeys),
"Signature predates primary key creation date");
// Sig valid
assertDoesNotThrow(() -> verify(
keyIsValid, getSignedData(data), publicKeys, policy, keyIsValid.getCreationTime()),
keyIsValid, getSignedData(data), publicKeys),
"Signature is valid");
// Sig not valid, as the signing key is revoked
assertThrows(SignatureValidationException.class, () -> verify(
keyIsRevoked, getSignedData(data), publicKeys, policy, keyIsRevoked.getCreationTime()),
keyIsRevoked, getSignedData(data), publicKeys),
"Signing key is revoked at this point");
// Sig valid, as the signing key is revalidated
assertDoesNotThrow(() -> verify(
keyIsRevalidated, getSignedData(data), publicKeys, policy, keyIsRevalidated.getCreationTime()),
keyIsRevalidated, getSignedData(data), publicKeys),
"Signature is valid, as signing key is revalidated");
}
@ -778,22 +769,20 @@ public class CertificateValidatorTest {
PGPSignature keyRevoked = SignatureUtils.readSignatures(sigKeyRevoked).get(0);
PGPSignature valid = SignatureUtils.readSignatures(sigKeyValid).get(0);
Policy policy = PGPainless.getPolicy();
String data = "Hello, World";
Date validationDate = new Date();
assertThrows(SignatureValidationException.class, () -> verify(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
predatesPrimaryKey, getSignedData(data), publicKeys),
"Signature predates primary key creation date");
assertThrows(SignatureValidationException.class, () -> verify(
keyNotBound, getSignedData(data), publicKeys, policy, validationDate),
keyNotBound, getSignedData(data), publicKeys),
"Signing key is not bound at this point");
assertThrows(SignatureValidationException.class, () -> verify(
keyRevoked, getSignedData(data), publicKeys, policy, validationDate),
keyRevoked, getSignedData(data), publicKeys),
"Signing key is revoked at this point");
assertDoesNotThrow(() ->
verify(
valid, getSignedData(data), publicKeys, policy, validationDate),
valid, getSignedData(data), publicKeys),
"Signing key is revalidated");
}
@ -931,22 +920,20 @@ public class CertificateValidatorTest {
PGPSignature revoked = SignatureUtils.readSignatures(sigRevoked).get(0);
PGPSignature revalidated = SignatureUtils.readSignatures(sigReLegitimized).get(0);
Policy policy = PGPainless.getPolicy();
Date validationDate = new Date();
String data = "Hello, World";
assertThrows(SignatureValidationException.class, () -> verify(
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
predatesPrimaryKey, getSignedData(data), publicKeys),
"Signature predates primary key creation date");
assertDoesNotThrow(() -> verify(
valid, getSignedData(data), publicKeys, policy, validationDate),
valid, getSignedData(data), publicKeys),
"Signature is valid");
assertThrows(SignatureValidationException.class, () ->
verify(
revoked, getSignedData(data), publicKeys, policy, validationDate),
revoked, getSignedData(data), publicKeys),
"Primary key is revoked");
assertDoesNotThrow(() -> verify(
revalidated, getSignedData(data), publicKeys, policy, validationDate),
revalidated, getSignedData(data), publicKeys),
"Primary key is re-legitimized");
}
@ -1271,52 +1258,50 @@ public class CertificateValidatorTest {
PGPSignature sigCT2_T3 = SignatureUtils.readSignatures(keyCSigT2_T3).get(0);
PGPSignature sigCT3_now = SignatureUtils.readSignatures(keyCSigT3_now).get(0);
Policy policy = PGPainless.getPolicy();
Date validationDate = new Date();
String data = "Hello World :)";
assertThrows(SignatureValidationException.class, () -> verify(
sigAT0, getSignedData(data), keysA, policy, validationDate),
sigAT0, getSignedData(data), keysA),
"Signature predates key creation time");
assertDoesNotThrow(() -> verify(
sigAT1_T2, getSignedData(data), keysA, policy, validationDate),
sigAT1_T2, getSignedData(data), keysA),
"Key valid");
assertThrows(SignatureValidationException.class, () ->
verify(
sigAT2_T3, getSignedData(data), keysA, policy, validationDate),
sigAT2_T3, getSignedData(data), keysA),
"Key is not valid, as subkey binding expired");
assertDoesNotThrow(() -> verify(
sigAT3_now, getSignedData(data), keysA, policy, validationDate),
sigAT3_now, getSignedData(data), keysA),
"Key is valid again");
assertThrows(SignatureValidationException.class, () -> verify(
sigBT0, getSignedData(data), keysB, policy, validationDate),
sigBT0, getSignedData(data), keysB),
"Signature predates key creation time");
assertDoesNotThrow(() -> verify(
sigBT1_T2, getSignedData(data), keysB, policy, validationDate),
sigBT1_T2, getSignedData(data), keysB),
"Key is valid");
assertThrows(SignatureValidationException.class, () -> verify(
sigBT2_T3, getSignedData(data), keysB, policy, validationDate),
sigBT2_T3, getSignedData(data), keysB),
"Primary key is not signing-capable");
assertDoesNotThrow(() -> verify(
sigBT3_now, getSignedData(data), keysB, policy, validationDate),
sigBT3_now, getSignedData(data), keysB),
"Key is valid again");
assertThrows(SignatureValidationException.class, () -> verify(
sigCT0, getSignedData(data), keysC, policy, validationDate),
sigCT0, getSignedData(data), keysC),
"Signature predates key creation time");
assertDoesNotThrow(() -> verify(
sigCT1_T2, getSignedData(data), keysC, policy, validationDate),
sigCT1_T2, getSignedData(data), keysC),
"Key is valid");
assertThrows(SignatureValidationException.class, () -> verify(
sigCT2_T3, getSignedData(data), keysC, policy, validationDate),
sigCT2_T3, getSignedData(data), keysC),
"Key is revoked");
assertDoesNotThrow(() -> verify(
sigCT3_now, getSignedData(data), keysC, policy, validationDate),
sigCT3_now, getSignedData(data), keysC),
"Key is valid again");
}
private void verify(PGPSignature signature, InputStream dataIn, PGPPublicKeyRing cert, Policy policy, Date validationDate) throws PGPException, IOException {
private void verify(PGPSignature signature, InputStream dataIn, PGPPublicKeyRing cert) throws PGPException, IOException {
PGPainless api = PGPainless.getInstance();
OpenPGPCertificate certificate = api.toCertificate(cert);

View file

@ -28,6 +28,8 @@ class SOPImpl(
private val sopv: SOPV = SOPVImpl(api)
) : SOP {
constructor(api: PGPainless) : this(api, SOPVImpl(api))
override fun armor(): Armor = ArmorImpl(api)
override fun changeKeyPassword(): ChangeKeyPassword = ChangeKeyPasswordImpl(api)

View file

@ -123,7 +123,8 @@ public class VerifyLegacySignatureTest {
"=TtKx\n" +
"-----END PGP MESSAGE-----";
SOPImpl sop = new SOPImpl();
PGPainless api = PGPainless.getInstance();
SOPImpl sop = new SOPImpl(api);
byte[] cert = sop.extractCert().key(KEY.getBytes(StandardCharsets.UTF_8))
.getBytes();
ByteArrayAndResult<List<Verification>> result = sop.inlineVerify()
@ -134,12 +135,13 @@ public class VerifyLegacySignatureTest {
assertFalse(result.getResult().isEmpty());
// Adjust data signature hash policy to accept new SHA-1 sigs
Policy policy = PGPainless.getPolicy();
Policy policy = api.getAlgorithmPolicy();
Policy adjusted = policy.copy()
.withDataSignatureHashAlgorithmPolicy(
Policy.HashAlgorithmPolicy.static2022RevocationSignatureHashAlgorithmPolicy()
).build();
PGPainless.getInstance().setAlgorithmPolicy(adjusted);
api = new PGPainless(adjusted);
sop = new SOPImpl(api);
// Sig generated in 2024 using SHA1
String newSig = "-----BEGIN PGP MESSAGE-----\n" +
@ -164,8 +166,5 @@ public class VerifyLegacySignatureTest {
.toByteArrayAndResult();
assertFalse(result.getResult().isEmpty());
// Reset old policy
PGPainless.getInstance().setAlgorithmPolicy(policy);
}
}