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:
parent
4c180bbd59
commit
221d329254
16 changed files with 125 additions and 348 deletions
|
@ -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 } }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue