mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-09-10 02:39:39 +02:00
Remove SignerUserId check, Policy setting only via constructor parameter
This commit is contained in:
parent
b97ff5bc4e
commit
8f3049602f
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.OpenPGPKeyGenerator
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPKeyReader
|
import org.bouncycastle.openpgp.api.OpenPGPKeyReader
|
||||||
import org.bouncycastle.openpgp.api.bc.BcOpenPGPApi
|
import org.bouncycastle.openpgp.api.bc.BcOpenPGPApi
|
||||||
import org.bouncycastle.openpgp.api.bc.BcOpenPGPImplementation
|
|
||||||
import org.pgpainless.algorithm.OpenPGPKeyVersion
|
import org.pgpainless.algorithm.OpenPGPKeyVersion
|
||||||
import org.pgpainless.bouncycastle.PolicyAdapter
|
import org.pgpainless.bouncycastle.PolicyAdapter
|
||||||
import org.pgpainless.bouncycastle.extensions.setAlgorithmSuite
|
import org.pgpainless.bouncycastle.extensions.setAlgorithmSuite
|
||||||
|
@ -35,10 +34,14 @@ import org.pgpainless.util.ArmorUtils
|
||||||
|
|
||||||
class PGPainless(
|
class PGPainless(
|
||||||
val implementation: OpenPGPImplementation = OpenPGPImplementation.getInstance(),
|
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 {
|
init {
|
||||||
implementation.setPolicy(
|
implementation.setPolicy(
|
||||||
|
@ -53,7 +56,11 @@ class PGPainless(
|
||||||
): KeyRingTemplates = KeyRingTemplates(version, creationTime, this)
|
): KeyRingTemplates = KeyRingTemplates(version, creationTime, this)
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun buildKey(
|
fun buildKey(version: OpenPGPKeyVersion = OpenPGPKeyVersion.v4): KeyRingBuilder =
|
||||||
|
KeyRingBuilder(version, this)
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
fun _buildKey(
|
||||||
version: OpenPGPKeyVersion = OpenPGPKeyVersion.v4,
|
version: OpenPGPKeyVersion = OpenPGPKeyVersion.v4,
|
||||||
creationTime: Date = Date()
|
creationTime: Date = Date()
|
||||||
): OpenPGPKeyGenerator =
|
): OpenPGPKeyGenerator =
|
||||||
|
@ -108,8 +115,6 @@ class PGPainless(
|
||||||
|
|
||||||
@Volatile private var instance: PGPainless? = null
|
@Volatile private var instance: PGPainless? = null
|
||||||
|
|
||||||
@JvmStatic fun newInstance(): PGPainless = PGPainless(BcOpenPGPImplementation(), Policy())
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getInstance(): PGPainless =
|
fun getInstance(): PGPainless =
|
||||||
instance ?: synchronized(this) { instance ?: PGPainless().also { instance = it } }
|
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.PGPPublicKeyEncryptedData
|
||||||
import org.bouncycastle.openpgp.PGPSessionKey
|
import org.bouncycastle.openpgp.PGPSessionKey
|
||||||
import org.bouncycastle.openpgp.PGPSignature
|
import org.bouncycastle.openpgp.PGPSignature
|
||||||
|
import org.bouncycastle.openpgp.PGPSignatureException
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPCertificate
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPKey
|
import org.bouncycastle.openpgp.api.OpenPGPKey
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPKey.OpenPGPPrivateKey
|
import org.bouncycastle.openpgp.api.OpenPGPKey.OpenPGPPrivateKey
|
||||||
|
@ -870,6 +871,10 @@ class OpenPgpMessageInputStream(
|
||||||
} catch (e: SignatureValidationException) {
|
} catch (e: SignatureValidationException) {
|
||||||
layer.addRejectedOnePassSignature(
|
layer.addRejectedOnePassSignature(
|
||||||
SignatureVerification.Failure(verification, e))
|
SignatureVerification.Failure(verification, e))
|
||||||
|
} catch (e: PGPSignatureException) {
|
||||||
|
layer.addRejectedOnePassSignature(
|
||||||
|
SignatureVerification.Failure(
|
||||||
|
verification, SignatureValidationException(e.message, e)))
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -973,10 +978,12 @@ class OpenPgpMessageInputStream(
|
||||||
SignatureValidator.signatureWasCreatedInBounds(
|
SignatureValidator.signatureWasCreatedInBounds(
|
||||||
options.getVerifyNotBefore(), options.getVerifyNotAfter())
|
options.getVerifyNotBefore(), options.getVerifyNotAfter())
|
||||||
.verify(detached.signature)
|
.verify(detached.signature)
|
||||||
if (detached.verify() && detached.isValid(api.implementation.policy())) {
|
if (!detached.verify()) {
|
||||||
layer.addVerifiedDetachedSignature(verification)
|
|
||||||
} else {
|
|
||||||
throw SignatureValidationException("Incorrect detached signature.")
|
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) {
|
} catch (e: MalformedOpenPGPSignatureException) {
|
||||||
throw SignatureValidationException("Malformed detached signature.", e)
|
throw SignatureValidationException("Malformed detached signature.", e)
|
||||||
|
|
|
@ -7,7 +7,6 @@ package org.pgpainless.key.generation
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import org.bouncycastle.openpgp.api.OpenPGPKey
|
import org.bouncycastle.openpgp.api.OpenPGPKey
|
||||||
import org.pgpainless.PGPainless
|
import org.pgpainless.PGPainless
|
||||||
import org.pgpainless.PGPainless.Companion.buildKeyRing
|
|
||||||
import org.pgpainless.algorithm.KeyFlag
|
import org.pgpainless.algorithm.KeyFlag
|
||||||
import org.pgpainless.algorithm.OpenPGPKeyVersion
|
import org.pgpainless.algorithm.OpenPGPKeyVersion
|
||||||
import org.pgpainless.key.generation.KeySpec.Companion.getBuilder
|
import org.pgpainless.key.generation.KeySpec.Companion.getBuilder
|
||||||
|
@ -38,7 +37,7 @@ class KeyRingTemplates(
|
||||||
length: RsaLength,
|
length: RsaLength,
|
||||||
passphrase: Passphrase = Passphrase.emptyPassphrase()
|
passphrase: Passphrase = Passphrase.emptyPassphrase()
|
||||||
): OpenPGPKey =
|
): OpenPGPKey =
|
||||||
buildKeyRing(version, api)
|
api.buildKey(version)
|
||||||
.apply {
|
.apply {
|
||||||
setPrimaryKey(
|
setPrimaryKey(
|
||||||
getBuilder(KeyType.RSA(length), KeyFlag.CERTIFY_OTHER)
|
getBuilder(KeyType.RSA(length), KeyFlag.CERTIFY_OTHER)
|
||||||
|
@ -90,7 +89,7 @@ class KeyRingTemplates(
|
||||||
length: RsaLength,
|
length: RsaLength,
|
||||||
passphrase: Passphrase = Passphrase.emptyPassphrase()
|
passphrase: Passphrase = Passphrase.emptyPassphrase()
|
||||||
): OpenPGPKey =
|
): OpenPGPKey =
|
||||||
buildKeyRing(version)
|
api.buildKey(version)
|
||||||
.apply {
|
.apply {
|
||||||
setPrimaryKey(
|
setPrimaryKey(
|
||||||
getBuilder(
|
getBuilder(
|
||||||
|
@ -144,7 +143,7 @@ class KeyRingTemplates(
|
||||||
val encryptionKeyType =
|
val encryptionKeyType =
|
||||||
if (version == OpenPGPKeyVersion.v6) KeyType.X25519()
|
if (version == OpenPGPKeyVersion.v6) KeyType.X25519()
|
||||||
else KeyType.XDH_LEGACY(XDHLegacySpec._X25519)
|
else KeyType.XDH_LEGACY(XDHLegacySpec._X25519)
|
||||||
return buildKeyRing(version)
|
return api.buildKey(version)
|
||||||
.apply {
|
.apply {
|
||||||
setPrimaryKey(
|
setPrimaryKey(
|
||||||
getBuilder(signingKeyType, KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
|
getBuilder(signingKeyType, KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
|
||||||
|
@ -197,7 +196,7 @@ class KeyRingTemplates(
|
||||||
val encryptionKeyType =
|
val encryptionKeyType =
|
||||||
if (version == OpenPGPKeyVersion.v6) KeyType.X25519()
|
if (version == OpenPGPKeyVersion.v6) KeyType.X25519()
|
||||||
else KeyType.XDH_LEGACY(XDHLegacySpec._X25519)
|
else KeyType.XDH_LEGACY(XDHLegacySpec._X25519)
|
||||||
return buildKeyRing(version)
|
return api.buildKey(version)
|
||||||
.apply {
|
.apply {
|
||||||
setPrimaryKey(
|
setPrimaryKey(
|
||||||
getBuilder(signingKeyType, KeyFlag.CERTIFY_OTHER)
|
getBuilder(signingKeyType, KeyFlag.CERTIFY_OTHER)
|
||||||
|
|
|
@ -36,7 +36,6 @@ class Policy(
|
||||||
NotationRegistry(),
|
NotationRegistry(),
|
||||||
AlgorithmSuite.defaultAlgorithmSuite)
|
AlgorithmSuite.defaultAlgorithmSuite)
|
||||||
|
|
||||||
var signerUserIdValidationLevel = SignerUserIdValidationLevel.DISABLED
|
|
||||||
var enableKeyParameterValidation = false
|
var enableKeyParameterValidation = false
|
||||||
|
|
||||||
fun copy() = Builder(this)
|
fun copy() = Builder(this)
|
||||||
|
@ -493,9 +492,6 @@ class Policy(
|
||||||
keyProtectionSettings,
|
keyProtectionSettings,
|
||||||
notationRegistry,
|
notationRegistry,
|
||||||
keyGenerationAlgorithmSuite)
|
keyGenerationAlgorithmSuite)
|
||||||
.apply {
|
.apply { enableKeyParameterValidation = origin.enableKeyParameterValidation }
|
||||||
enableKeyParameterValidation = origin.enableKeyParameterValidation
|
|
||||||
signerUserIdValidationLevel = origin.signerUserIdValidationLevel
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,7 +211,7 @@ public class ModifiedPublicKeysInvestigation {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void assertModifiedDSAKeyThrowsKeyIntegrityException() throws IOException {
|
public void assertModifiedDSAKeyThrowsKeyIntegrityException() throws IOException {
|
||||||
PGPainless api = PGPainless.newInstance();
|
PGPainless api = PGPainless.getInstance();
|
||||||
Policy policy = api.getAlgorithmPolicy();
|
Policy policy = api.getAlgorithmPolicy();
|
||||||
policy.setEnableKeyParameterValidation(true);
|
policy.setEnableKeyParameterValidation(true);
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ public class ModifiedPublicKeysInvestigation {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void assertModifiedElGamalKeyThrowsKeyIntegrityException() throws IOException {
|
public void assertModifiedElGamalKeyThrowsKeyIntegrityException() throws IOException {
|
||||||
PGPainless api = PGPainless.newInstance();
|
PGPainless api = PGPainless.getInstance();
|
||||||
Policy policy = api.getAlgorithmPolicy();
|
Policy policy = api.getAlgorithmPolicy();
|
||||||
policy.setEnableKeyParameterValidation(true);
|
policy.setEnableKeyParameterValidation(true);
|
||||||
|
|
||||||
|
@ -239,7 +239,7 @@ public class ModifiedPublicKeysInvestigation {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void assertInjectedKeyRingFailsToUnlockPrimaryKey() throws IOException {
|
public void assertInjectedKeyRingFailsToUnlockPrimaryKey() throws IOException {
|
||||||
PGPainless api = PGPainless.newInstance();
|
PGPainless api = PGPainless.getInstance();
|
||||||
Policy policy = api.getAlgorithmPolicy();
|
Policy policy = api.getAlgorithmPolicy();
|
||||||
policy.setEnableKeyParameterValidation(true);
|
policy.setEnableKeyParameterValidation(true);
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ public class ModifiedPublicKeysInvestigation {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void assertCannotUnlockElGamalPrimaryKeyDueToDummyS2K() throws IOException {
|
public void assertCannotUnlockElGamalPrimaryKeyDueToDummyS2K() throws IOException {
|
||||||
PGPainless api = PGPainless.newInstance();
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
|
||||||
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword("12345678"));
|
SecretKeyRingProtector protector = SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword("12345678"));
|
||||||
OpenPGPKey elgamal = api.readKey().parseKey(ELGAMAL);
|
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.PGPSecretKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.bouncycastle.util.io.Streams;
|
import org.bouncycastle.util.io.Streams;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.TestTemplate;
|
import org.junit.jupiter.api.TestTemplate;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.pgpainless.PGPainless;
|
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.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.protection.UnprotectedKeysProtector;
|
import org.pgpainless.key.protection.UnprotectedKeysProtector;
|
||||||
import org.pgpainless.key.util.KeyRingUtils;
|
import org.pgpainless.key.util.KeyRingUtils;
|
||||||
import org.pgpainless.policy.Policy;
|
|
||||||
import org.pgpainless.util.ArmoredOutputStreamFactory;
|
import org.pgpainless.util.ArmoredOutputStreamFactory;
|
||||||
import org.pgpainless.util.TestAllImplementations;
|
import org.pgpainless.util.TestAllImplementations;
|
||||||
|
|
||||||
|
@ -57,18 +55,14 @@ public class EncryptDecryptTest {
|
||||||
"Unfold the imagined happiness that both\n" +
|
"Unfold the imagined happiness that both\n" +
|
||||||
"Receive in either by this dear encounter.";
|
"Receive in either by this dear encounter.";
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
public void setDefaultPolicy() {
|
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(new Policy());
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestTemplate
|
@TestTemplate
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void freshKeysRsaToRsaTest()
|
public void freshKeysRsaToRsaTest()
|
||||||
throws PGPException, IOException {
|
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();
|
.getPGPSecretKeyRing();
|
||||||
PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("juliet@capulet.lit", RsaLength._3072)
|
PGPSecretKeyRing recipient = api.generateKey().simpleRsaKeyRing("juliet@capulet.lit", RsaLength._3072)
|
||||||
.getPGPSecretKeyRing();
|
.getPGPSecretKeyRing();
|
||||||
|
|
||||||
encryptDecryptForSecretKeyRings(sender, recipient);
|
encryptDecryptForSecretKeyRings(sender, recipient);
|
||||||
|
@ -78,9 +72,10 @@ public class EncryptDecryptTest {
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void freshKeysEcToEcTest()
|
public void freshKeysEcToEcTest()
|
||||||
throws IOException, PGPException {
|
throws IOException, PGPException {
|
||||||
PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleEcKeyRing("romeo@montague.lit")
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
PGPSecretKeyRing sender = api.generateKey().simpleEcKeyRing("romeo@montague.lit")
|
||||||
.getPGPSecretKeyRing();
|
.getPGPSecretKeyRing();
|
||||||
PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleEcKeyRing("juliet@capulet.lit")
|
PGPSecretKeyRing recipient = api.generateKey().simpleEcKeyRing("juliet@capulet.lit")
|
||||||
.getPGPSecretKeyRing();
|
.getPGPSecretKeyRing();
|
||||||
|
|
||||||
encryptDecryptForSecretKeyRings(sender, recipient);
|
encryptDecryptForSecretKeyRings(sender, recipient);
|
||||||
|
@ -90,9 +85,10 @@ public class EncryptDecryptTest {
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void freshKeysEcToRsaTest()
|
public void freshKeysEcToRsaTest()
|
||||||
throws PGPException, IOException {
|
throws PGPException, IOException {
|
||||||
PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleEcKeyRing("romeo@montague.lit")
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
PGPSecretKeyRing sender = api.generateKey().simpleEcKeyRing("romeo@montague.lit")
|
||||||
.getPGPSecretKeyRing();
|
.getPGPSecretKeyRing();
|
||||||
PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleRsaKeyRing("juliet@capulet.lit", RsaLength._3072)
|
PGPSecretKeyRing recipient = api.generateKey().simpleRsaKeyRing("juliet@capulet.lit", RsaLength._3072)
|
||||||
.getPGPSecretKeyRing();
|
.getPGPSecretKeyRing();
|
||||||
|
|
||||||
encryptDecryptForSecretKeyRings(sender, recipient);
|
encryptDecryptForSecretKeyRings(sender, recipient);
|
||||||
|
@ -102,9 +98,10 @@ public class EncryptDecryptTest {
|
||||||
@ExtendWith(TestAllImplementations.class)
|
@ExtendWith(TestAllImplementations.class)
|
||||||
public void freshKeysRsaToEcTest()
|
public void freshKeysRsaToEcTest()
|
||||||
throws PGPException, IOException {
|
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();
|
.getPGPSecretKeyRing();
|
||||||
PGPSecretKeyRing recipient = PGPainless.generateKeyRing().simpleEcKeyRing("juliet@capulet.lit")
|
PGPSecretKeyRing recipient = api.generateKey().simpleEcKeyRing("juliet@capulet.lit")
|
||||||
.getPGPSecretKeyRing();
|
.getPGPSecretKeyRing();
|
||||||
|
|
||||||
encryptDecryptForSecretKeyRings(sender, recipient);
|
encryptDecryptForSecretKeyRings(sender, recipient);
|
||||||
|
|
|
@ -10,8 +10,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.algorithm.HashAlgorithm;
|
import org.pgpainless.algorithm.HashAlgorithm;
|
||||||
|
@ -36,16 +34,6 @@ import org.pgpainless.util.NotationRegistry;
|
||||||
*/
|
*/
|
||||||
public class ManagePolicy {
|
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
|
* {@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.
|
* example for an algorithm that is nowadays considered unsafe to use and which shall be avoided.
|
||||||
|
@ -62,8 +50,9 @@ public class ManagePolicy {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void setCustomSignatureHashPolicy() {
|
public void setCustomSignatureHashPolicy() {
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
// Get PGPainless' policy
|
// Get PGPainless' policy
|
||||||
Policy oldPolicy = PGPainless.getInstance().getAlgorithmPolicy();
|
Policy oldPolicy = api.getAlgorithmPolicy();
|
||||||
|
|
||||||
Policy.HashAlgorithmPolicy sigHashAlgoPolicy = oldPolicy.getDataSignatureHashAlgorithmPolicy();
|
Policy.HashAlgorithmPolicy sigHashAlgoPolicy = oldPolicy.getDataSignatureHashAlgorithmPolicy();
|
||||||
assertTrue(sigHashAlgoPolicy.isAcceptable(HashAlgorithm.SHA512));
|
assertTrue(sigHashAlgoPolicy.isAcceptable(HashAlgorithm.SHA512));
|
||||||
|
@ -77,17 +66,12 @@ public class ManagePolicy {
|
||||||
// List of acceptable hash algorithms
|
// List of acceptable hash algorithms
|
||||||
Arrays.asList(HashAlgorithm.SHA512, HashAlgorithm.SHA384, HashAlgorithm.SHA256, HashAlgorithm.SHA224, HashAlgorithm.SHA1));
|
Arrays.asList(HashAlgorithm.SHA512, HashAlgorithm.SHA384, HashAlgorithm.SHA256, HashAlgorithm.SHA224, HashAlgorithm.SHA1));
|
||||||
// Set the hash algo policy as policy for non-revocation signatures
|
// Set the hash algo policy as policy for non-revocation signatures
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(
|
api = new PGPainless(oldPolicy.copy().withDataSignatureHashAlgorithmPolicy(customPolicy).build());
|
||||||
oldPolicy.copy().withDataSignatureHashAlgorithmPolicy(customPolicy).build()
|
|
||||||
);
|
|
||||||
|
|
||||||
sigHashAlgoPolicy = PGPainless.getInstance().getAlgorithmPolicy().getDataSignatureHashAlgorithmPolicy();
|
sigHashAlgoPolicy = api.getAlgorithmPolicy().getDataSignatureHashAlgorithmPolicy();
|
||||||
assertTrue(sigHashAlgoPolicy.isAcceptable(HashAlgorithm.SHA512));
|
assertTrue(sigHashAlgoPolicy.isAcceptable(HashAlgorithm.SHA512));
|
||||||
// SHA-1 is now acceptable as well
|
// SHA-1 is now acceptable as well
|
||||||
assertTrue(sigHashAlgoPolicy.isAcceptable(HashAlgorithm.SHA1));
|
assertTrue(sigHashAlgoPolicy.isAcceptable(HashAlgorithm.SHA1));
|
||||||
|
|
||||||
// reset old policy
|
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(oldPolicy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,7 +84,8 @@ public class ManagePolicy {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void setCustomPublicKeyAlgorithmPolicy() {
|
public void setCustomPublicKeyAlgorithmPolicy() {
|
||||||
Policy oldPolicy = PGPainless.getInstance().getAlgorithmPolicy();
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
Policy oldPolicy = api.getAlgorithmPolicy();
|
||||||
Policy.PublicKeyAlgorithmPolicy pkAlgorithmPolicy = oldPolicy.getPublicKeyAlgorithmPolicy();
|
Policy.PublicKeyAlgorithmPolicy pkAlgorithmPolicy = oldPolicy.getPublicKeyAlgorithmPolicy();
|
||||||
assertTrue(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 4096));
|
assertTrue(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 4096));
|
||||||
assertTrue(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 2048));
|
assertTrue(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 2048));
|
||||||
|
@ -115,17 +100,15 @@ public class ManagePolicy {
|
||||||
put(PublicKeyAlgorithm.RSA_GENERAL, 3000);
|
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));
|
assertTrue(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 4096));
|
||||||
// RSA 2048 is no longer acceptable
|
// RSA 2048 is no longer acceptable
|
||||||
assertFalse(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 2048));
|
assertFalse(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 2048));
|
||||||
// ECDSA is no longer acceptable, since it is no longer included in the policy at all
|
// ECDSA is no longer acceptable, since it is no longer included in the policy at all
|
||||||
assertFalse(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.ECDSA, 256));
|
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.bcpg.KeyIdentifier;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.api.OpenPGPKey;
|
||||||
import org.bouncycastle.util.io.Streams;
|
import org.bouncycastle.util.io.Streams;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
|
@ -42,15 +42,15 @@ public class GenerateKeyWithoutPrimaryKeyFlagsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void generateKeyWithoutCertifyKeyFlag_cannotCertifyThirdParties() throws PGPException, IOException {
|
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.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.SIGN_DATA))
|
||||||
.addSubkey(KeySpec.getBuilder(KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS))
|
.addSubkey(KeySpec.getBuilder(KeyType.XDH_LEGACY(XDHLegacySpec._X25519), KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS))
|
||||||
.addUserId("Alice")
|
.addUserId("Alice")
|
||||||
.build()
|
.build();
|
||||||
.getPGPSecretKeyRing();
|
OpenPGPCertificate cert = key.toCertificate();
|
||||||
PGPPublicKeyRing cert = PGPainless.extractCertificate(secretKeys);
|
|
||||||
|
|
||||||
KeyRingInfo info = PGPainless.inspectKeyRing(secretKeys);
|
KeyRingInfo info = api.inspect(key);
|
||||||
assertTrue(info.getValidUserIds().contains("Alice"));
|
assertTrue(info.getValidUserIds().contains("Alice"));
|
||||||
|
|
||||||
KeyIdentifier primaryKeyIdentifier = info.getKeyIdentifier();
|
KeyIdentifier primaryKeyIdentifier = info.getKeyIdentifier();
|
||||||
|
@ -59,18 +59,18 @@ public class GenerateKeyWithoutPrimaryKeyFlagsTest {
|
||||||
assertFalse(info.isUsableForThirdPartyCertification());
|
assertFalse(info.isUsableForThirdPartyCertification());
|
||||||
|
|
||||||
// Key without CERTIFY_OTHER flag cannot be used to certify other keys
|
// Key without CERTIFY_OTHER flag cannot be used to certify other keys
|
||||||
PGPPublicKeyRing thirdPartyCert = TestKeys.getCryptiePublicKeyRing();
|
OpenPGPCertificate thirdPartyCert = TestKeys.getCryptieCertificate();
|
||||||
assertThrows(KeyException.UnacceptableThirdPartyCertificationKeyException.class, () ->
|
assertThrows(KeyException.UnacceptableThirdPartyCertificationKeyException.class, () ->
|
||||||
PGPainless.certify().certificate(thirdPartyCert)
|
api.generateCertification().certificate(thirdPartyCert)
|
||||||
.withKey(secretKeys, SecretKeyRingProtector.unprotectedKeys()));
|
.withKey(key, SecretKeyRingProtector.unprotectedKeys()));
|
||||||
|
|
||||||
// Key without CERTIFY_OTHER flags is usable for encryption and signing
|
// Key without CERTIFY_OTHER flags is usable for encryption and signing
|
||||||
ByteArrayOutputStream ciphertext = new ByteArrayOutputStream();
|
ByteArrayOutputStream ciphertext = new ByteArrayOutputStream();
|
||||||
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
|
EncryptionStream encryptionStream = api.generateMessage()
|
||||||
.onOutputStream(ciphertext)
|
.onOutputStream(ciphertext)
|
||||||
.withOptions(ProducerOptions.signAndEncrypt(
|
.withOptions(ProducerOptions.signAndEncrypt(
|
||||||
EncryptionOptions.get().addRecipient(cert),
|
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.write("Hello, World!\n".getBytes(StandardCharsets.UTF_8));
|
||||||
encryptionStream.close();
|
encryptionStream.close();
|
||||||
|
@ -79,7 +79,7 @@ public class GenerateKeyWithoutPrimaryKeyFlagsTest {
|
||||||
|
|
||||||
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
|
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
|
||||||
.onInputStream(new ByteArrayInputStream(ciphertext.toByteArray()))
|
.onInputStream(new ByteArrayInputStream(ciphertext.toByteArray()))
|
||||||
.withOptions(ConsumerOptions.get().addDecryptionKey(secretKeys)
|
.withOptions(ConsumerOptions.get().addDecryptionKey(key)
|
||||||
.addVerificationCert(cert));
|
.addVerificationCert(cert));
|
||||||
|
|
||||||
ByteArrayOutputStream plaintext = new ByteArrayOutputStream();
|
ByteArrayOutputStream plaintext = new ByteArrayOutputStream();
|
||||||
|
|
|
@ -18,7 +18,6 @@ import org.pgpainless.algorithm.OpenPGPKeyVersion;
|
||||||
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
||||||
import org.pgpainless.key.generation.type.rsa.RsaLength;
|
import org.pgpainless.key.generation.type.rsa.RsaLength;
|
||||||
import org.pgpainless.key.protection.KeyRingProtectionSettings;
|
import org.pgpainless.key.protection.KeyRingProtectionSettings;
|
||||||
import org.pgpainless.policy.Policy;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -31,7 +30,8 @@ public class GenerateV6KeyTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void generateModernV6Key() {
|
public void generateModernV6Key() {
|
||||||
OpenPGPKey key = PGPainless.generateKeyRing(OpenPGPKeyVersion.v6)
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
OpenPGPKey key = api.generateKey(OpenPGPKeyVersion.v6)
|
||||||
.modernKeyRing("Alice <alice@example.org>");
|
.modernKeyRing("Alice <alice@example.org>");
|
||||||
assertEquals(3, key.getKeys().size());
|
assertEquals(3, key.getKeys().size());
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ public class GenerateV6KeyTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildMinimalEd25519V6Key() throws PGPException {
|
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() {
|
.withPrimaryKey(PGPKeyPairGenerator::generateEd25519KeyPair, new SignatureParameters.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public SignatureParameters apply(SignatureParameters parameters) {
|
public SignatureParameters apply(SignatureParameters parameters) {
|
||||||
|
@ -87,7 +87,7 @@ public class GenerateV6KeyTest {
|
||||||
@Test
|
@Test
|
||||||
public void buildCompositeCurve25519V6Key()
|
public void buildCompositeCurve25519V6Key()
|
||||||
throws PGPException, IOException {
|
throws PGPException, IOException {
|
||||||
OpenPGPKey key = PGPainless.getInstance().buildKey(OpenPGPKeyVersion.v6)
|
OpenPGPKey key = PGPainless.getInstance()._buildKey(OpenPGPKeyVersion.v6)
|
||||||
.withPrimaryKey(PGPKeyPairGenerator::generateEd25519KeyPair)
|
.withPrimaryKey(PGPKeyPairGenerator::generateEd25519KeyPair)
|
||||||
.addSigningSubkey(PGPKeyPairGenerator::generateEd25519KeyPair)
|
.addSigningSubkey(PGPKeyPairGenerator::generateEd25519KeyPair)
|
||||||
.addEncryptionSubkey(PGPKeyPairGenerator::generateX25519KeyPair)
|
.addEncryptionSubkey(PGPKeyPairGenerator::generateX25519KeyPair)
|
||||||
|
@ -138,20 +138,19 @@ public class GenerateV6KeyTest {
|
||||||
@Test
|
@Test
|
||||||
public void generateAEADProtectedModernKey()
|
public void generateAEADProtectedModernKey()
|
||||||
throws IOException, PGPException {
|
throws IOException, PGPException {
|
||||||
Policy oldPolicy = PGPainless.getInstance().getAlgorithmPolicy();
|
PGPainless api = PGPainless.getInstance();
|
||||||
|
|
||||||
// Change Policy to use AEAD for secret key protection
|
// Change Policy to use AEAD for secret key protection
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(
|
api = new PGPainless(api.getAlgorithmPolicy().copy()
|
||||||
oldPolicy.copy().withKeyProtectionSettings(KeyRingProtectionSettings.aead()).build()
|
.withKeyProtectionSettings(KeyRingProtectionSettings.aead()).build());
|
||||||
);
|
|
||||||
|
|
||||||
OpenPGPKey key = PGPainless.getInstance()
|
OpenPGPKey key = api
|
||||||
.generateKey(OpenPGPKeyVersion.v6)
|
.generateKey(OpenPGPKeyVersion.v6)
|
||||||
.modernKeyRing("Alice <alice@example.com>", "p455w0rd");
|
.modernKeyRing("Alice <alice@example.com>", "p455w0rd");
|
||||||
|
|
||||||
String armored = key.toAsciiArmoredString();
|
String armored = key.toAsciiArmoredString();
|
||||||
|
|
||||||
OpenPGPKey parsed = PGPainless.getInstance().readKey().parseKey(armored);
|
OpenPGPKey parsed = api.readKey().parseKey(armored);
|
||||||
|
|
||||||
OpenPGPKey.OpenPGPSecretKey primaryKey = key.getPrimarySecretKey();
|
OpenPGPKey.OpenPGPSecretKey primaryKey = key.getPrimarySecretKey();
|
||||||
assertEquals(SecretKeyPacket.USAGE_AEAD, primaryKey.getPGPSecretKey().getS2KUsage());
|
assertEquals(SecretKeyPacket.USAGE_AEAD, primaryKey.getPGPSecretKey().getS2KUsage());
|
||||||
|
@ -160,7 +159,5 @@ public class GenerateV6KeyTest {
|
||||||
assertNotNull(privateKey);
|
assertNotNull(privateKey);
|
||||||
|
|
||||||
assertEquals(armored, parsed.toAsciiArmoredString());
|
assertEquals(armored, parsed.toAsciiArmoredString());
|
||||||
|
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(oldPolicy);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,20 +21,15 @@ public class GeneratingWeakKeyThrowsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void refuseToGenerateWeakPrimaryKeyTest() {
|
public void refuseToGenerateWeakPrimaryKeyTest() {
|
||||||
// ensure we have default public key algorithm policy set
|
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(new Policy());
|
|
||||||
assertThrows(IllegalArgumentException.class, () ->
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
PGPainless.buildKeyRing()
|
PGPainless.getInstance().buildKey()
|
||||||
.setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._1024),
|
.setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._1024),
|
||||||
KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)));
|
KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void refuseToAddWeakSubkeyDuringGenerationTest() {
|
public void refuseToAddWeakSubkeyDuringGenerationTest() {
|
||||||
// ensure we have default public key algorithm policy set
|
KeyRingBuilder kb = PGPainless.getInstance().buildKey()
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(new Policy());
|
|
||||||
|
|
||||||
KeyRingBuilder kb = PGPainless.buildKeyRing()
|
|
||||||
.setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._4096),
|
.setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._4096),
|
||||||
KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA));
|
KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA));
|
||||||
|
|
||||||
|
@ -46,23 +41,19 @@ public class GeneratingWeakKeyThrowsTest {
|
||||||
@Test
|
@Test
|
||||||
public void allowToAddWeakKeysWithWeakPolicy() {
|
public void allowToAddWeakKeysWithWeakPolicy() {
|
||||||
// set a weak algorithm policy
|
// set a weak algorithm policy
|
||||||
|
PGPainless api = PGPainless.getInstance();
|
||||||
Map<PublicKeyAlgorithm, Integer> bitStrengths = new HashMap<>();
|
Map<PublicKeyAlgorithm, Integer> bitStrengths = new HashMap<>();
|
||||||
bitStrengths.put(PublicKeyAlgorithm.RSA_GENERAL, 512);
|
bitStrengths.put(PublicKeyAlgorithm.RSA_GENERAL, 512);
|
||||||
|
|
||||||
Policy oldPolicy = PGPainless.getPolicy();
|
Policy oldPolicy = api.getAlgorithmPolicy();
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(oldPolicy.copy()
|
api = new PGPainless(oldPolicy.copy().withPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(bitStrengths)).build());
|
||||||
.withPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(bitStrengths))
|
|
||||||
.build());
|
|
||||||
|
|
||||||
PGPainless.buildKeyRing()
|
api.buildKey()
|
||||||
.setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._4096),
|
.setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._4096),
|
||||||
KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA))
|
KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA))
|
||||||
.addSubkey(KeySpec.getBuilder(KeyType.RSA(RsaLength._1024),
|
.addSubkey(KeySpec.getBuilder(KeyType.RSA(RsaLength._1024),
|
||||||
KeyFlag.ENCRYPT_COMMS))
|
KeyFlag.ENCRYPT_COMMS))
|
||||||
.addUserId("Henry")
|
.addUserId("Henry")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// reset public key algorithm policy
|
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(oldPolicy);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class RefuseToAddWeakSubkeyTest {
|
||||||
Policy adjusted = oldPolicy.copy().withPublicKeyAlgorithmPolicy(
|
Policy adjusted = oldPolicy.copy().withPublicKeyAlgorithmPolicy(
|
||||||
Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy()
|
Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy()
|
||||||
).build();
|
).build();
|
||||||
api.setAlgorithmPolicy(adjusted);
|
api = new PGPainless(adjusted);
|
||||||
|
|
||||||
OpenPGPKey secretKeys = api.generateKey()
|
OpenPGPKey secretKeys = api.generateKey()
|
||||||
.modernKeyRing("Alice");
|
.modernKeyRing("Alice");
|
||||||
|
@ -43,7 +43,6 @@ public class RefuseToAddWeakSubkeyTest {
|
||||||
|
|
||||||
assertThrows(IllegalArgumentException.class, () ->
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
editor.addSubKey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys()));
|
editor.addSubKey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys()));
|
||||||
api.setAlgorithmPolicy(oldPolicy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -75,7 +74,7 @@ public class RefuseToAddWeakSubkeyTest {
|
||||||
minimalBitStrengths.put(PublicKeyAlgorithm.DIFFIE_HELLMAN, 2000);
|
minimalBitStrengths.put(PublicKeyAlgorithm.DIFFIE_HELLMAN, 2000);
|
||||||
// §7.2.2
|
// §7.2.2
|
||||||
minimalBitStrengths.put(PublicKeyAlgorithm.ECDH, 250);
|
minimalBitStrengths.put(PublicKeyAlgorithm.ECDH, 250);
|
||||||
api.setAlgorithmPolicy(oldPolicy.copy()
|
api = new PGPainless(oldPolicy.copy()
|
||||||
.withPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(minimalBitStrengths))
|
.withPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(minimalBitStrengths))
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
|
@ -88,8 +87,5 @@ public class RefuseToAddWeakSubkeyTest {
|
||||||
.done();
|
.done();
|
||||||
|
|
||||||
assertEquals(2, api.inspect(secretKeys).getEncryptionSubkeys(EncryptionPurpose.ANY).size());
|
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.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
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 static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -205,9 +204,4 @@ public class PolicyTest {
|
||||||
public void testUnknownPublicKeyAlgorithmIsNotAcceptable() {
|
public void testUnknownPublicKeyAlgorithmIsNotAcceptable() {
|
||||||
assertFalse(policy.getPublicKeyAlgorithmPolicy().isAcceptable(-1, 4096));
|
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.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
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.DecryptionStream;
|
||||||
import org.pgpainless.decryption_verification.MessageMetadata;
|
import org.pgpainless.decryption_verification.MessageMetadata;
|
||||||
import org.pgpainless.exception.SignatureValidationException;
|
import org.pgpainless.exception.SignatureValidationException;
|
||||||
import org.pgpainless.policy.Policy;
|
|
||||||
import org.pgpainless.util.TestAllImplementations;
|
import org.pgpainless.util.TestAllImplementations;
|
||||||
|
|
||||||
public class CertificateValidatorTest {
|
public class CertificateValidatorTest {
|
||||||
|
@ -166,21 +164,19 @@ public class CertificateValidatorTest {
|
||||||
PGPSignature primaryKeyRevoked = SignatureUtils.readSignatures(sigPrimaryKeyRevoked).get(0);
|
PGPSignature primaryKeyRevoked = SignatureUtils.readSignatures(sigPrimaryKeyRevoked).get(0);
|
||||||
PGPSignature primaryKeyRevalidated = SignatureUtils.readSignatures(sigPrimaryKeyRevalidated).get(0);
|
PGPSignature primaryKeyRevalidated = SignatureUtils.readSignatures(sigPrimaryKeyRevalidated).get(0);
|
||||||
|
|
||||||
Policy policy = PGPainless.getPolicy();
|
|
||||||
Date validationDate = new Date();
|
|
||||||
String data = "Hello, World";
|
String data = "Hello, World";
|
||||||
|
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
|
predatesPrimaryKey, getSignedData(data), publicKeys),
|
||||||
"Signature predates primary key");
|
"Signature predates primary key");
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
unboundSubkey, getSignedData(data), publicKeys, policy, validationDate),
|
unboundSubkey, getSignedData(data), publicKeys),
|
||||||
"Primary key hard revoked");
|
"Primary key hard revoked");
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
primaryKeyRevoked, getSignedData(data), publicKeys, policy, validationDate),
|
primaryKeyRevoked, getSignedData(data), publicKeys),
|
||||||
"Primary key hard revoked");
|
"Primary key hard revoked");
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
primaryKeyRevalidated, getSignedData(data), publicKeys, policy, validationDate),
|
primaryKeyRevalidated, getSignedData(data), publicKeys),
|
||||||
"Primary key hard revoked");
|
"Primary key hard revoked");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,21 +313,19 @@ public class CertificateValidatorTest {
|
||||||
PGPSignature revokedSubkey = SignatureUtils.readSignatures(sigSubkeyRevoked).get(0);
|
PGPSignature revokedSubkey = SignatureUtils.readSignatures(sigSubkeyRevoked).get(0);
|
||||||
PGPSignature revalidatedSubkey = SignatureUtils.readSignatures(sigSubkeyRevalidated).get(0);
|
PGPSignature revalidatedSubkey = SignatureUtils.readSignatures(sigSubkeyRevalidated).get(0);
|
||||||
|
|
||||||
Policy policy = PGPainless.getPolicy();
|
|
||||||
Date validationDate = new Date();
|
|
||||||
String data = "Hello, World";
|
String data = "Hello, World";
|
||||||
|
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
|
predatesPrimaryKey, getSignedData(data), publicKeys),
|
||||||
"Signature predates primary key");
|
"Signature predates primary key");
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
unboundSubkey, getSignedData(data), publicKeys, policy, validationDate),
|
unboundSubkey, getSignedData(data), publicKeys),
|
||||||
"Signing key unbound + hard revocation");
|
"Signing key unbound + hard revocation");
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
revokedSubkey, getSignedData(data), publicKeys, policy, validationDate),
|
revokedSubkey, getSignedData(data), publicKeys),
|
||||||
"Primary key is hard revoked");
|
"Primary key is hard revoked");
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
revalidatedSubkey, getSignedData(data), publicKeys, policy, validationDate),
|
revalidatedSubkey, getSignedData(data), publicKeys),
|
||||||
"Primary key is hard revoked");
|
"Primary key is hard revoked");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,21 +463,19 @@ public class CertificateValidatorTest {
|
||||||
PGPSignature afterHardRevocation = SignatureUtils.readSignatures(sigAfterHardRevocation).get(0);
|
PGPSignature afterHardRevocation = SignatureUtils.readSignatures(sigAfterHardRevocation).get(0);
|
||||||
PGPSignature afterRevalidation = SignatureUtils.readSignatures(sigAfterRevalidation).get(0);
|
PGPSignature afterRevalidation = SignatureUtils.readSignatures(sigAfterRevalidation).get(0);
|
||||||
|
|
||||||
Policy policy = PGPainless.getPolicy();
|
|
||||||
Date validationDate = new Date();
|
|
||||||
String data = "Hello World :)";
|
String data = "Hello World :)";
|
||||||
|
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
|
predatesPrimaryKey, getSignedData(data), publicKeys),
|
||||||
"Signature predates primary key");
|
"Signature predates primary key");
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
unboundKey, getSignedData(data), publicKeys, policy, validationDate),
|
unboundKey, getSignedData(data), publicKeys),
|
||||||
"Signing key unbound + hard revocation");
|
"Signing key unbound + hard revocation");
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
afterHardRevocation, getSignedData(data), publicKeys, policy, validationDate),
|
afterHardRevocation, getSignedData(data), publicKeys),
|
||||||
"Hard revocation invalidates key at all times");
|
"Hard revocation invalidates key at all times");
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
afterRevalidation, getSignedData(data), publicKeys, policy, validationDate),
|
afterRevalidation, getSignedData(data), publicKeys),
|
||||||
"Hard revocation invalidates key at all times");
|
"Hard revocation invalidates key at all times");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,27 +612,26 @@ public class CertificateValidatorTest {
|
||||||
PGPSignature keyIsValid = SignatureUtils.readSignatures(sigKeyIsValid).get(0);
|
PGPSignature keyIsValid = SignatureUtils.readSignatures(sigKeyIsValid).get(0);
|
||||||
PGPSignature keyIsRevoked = SignatureUtils.readSignatures(sigKeyIsRevoked).get(0);
|
PGPSignature keyIsRevoked = SignatureUtils.readSignatures(sigKeyIsRevoked).get(0);
|
||||||
PGPSignature keyIsRevalidated = SignatureUtils.readSignatures(sigKeyIsRevalidated).get(0);
|
PGPSignature keyIsRevalidated = SignatureUtils.readSignatures(sigKeyIsRevalidated).get(0);
|
||||||
Policy policy = PGPainless.getPolicy();
|
|
||||||
String data = "Hello, World";
|
String data = "Hello, World";
|
||||||
|
|
||||||
// Sig not valid, as it predates the signing key creation time
|
// Sig not valid, as it predates the signing key creation time
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
predatesPrimaryKey, getSignedData(data), publicKeys, policy, predatesPrimaryKey.getCreationTime()),
|
predatesPrimaryKey, getSignedData(data), publicKeys),
|
||||||
"Signature predates primary key creation date");
|
"Signature predates primary key creation date");
|
||||||
|
|
||||||
// Sig valid
|
// Sig valid
|
||||||
assertDoesNotThrow(() -> verify(
|
assertDoesNotThrow(() -> verify(
|
||||||
keyIsValid, getSignedData(data), publicKeys, policy, keyIsValid.getCreationTime()),
|
keyIsValid, getSignedData(data), publicKeys),
|
||||||
"Signature is valid");
|
"Signature is valid");
|
||||||
|
|
||||||
// Sig not valid, as the signing key is revoked
|
// Sig not valid, as the signing key is revoked
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
keyIsRevoked, getSignedData(data), publicKeys, policy, keyIsRevoked.getCreationTime()),
|
keyIsRevoked, getSignedData(data), publicKeys),
|
||||||
"Signing key is revoked at this point");
|
"Signing key is revoked at this point");
|
||||||
|
|
||||||
// Sig valid, as the signing key is revalidated
|
// Sig valid, as the signing key is revalidated
|
||||||
assertDoesNotThrow(() -> verify(
|
assertDoesNotThrow(() -> verify(
|
||||||
keyIsRevalidated, getSignedData(data), publicKeys, policy, keyIsRevalidated.getCreationTime()),
|
keyIsRevalidated, getSignedData(data), publicKeys),
|
||||||
"Signature is valid, as signing key is revalidated");
|
"Signature is valid, as signing key is revalidated");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,22 +769,20 @@ public class CertificateValidatorTest {
|
||||||
PGPSignature keyRevoked = SignatureUtils.readSignatures(sigKeyRevoked).get(0);
|
PGPSignature keyRevoked = SignatureUtils.readSignatures(sigKeyRevoked).get(0);
|
||||||
PGPSignature valid = SignatureUtils.readSignatures(sigKeyValid).get(0);
|
PGPSignature valid = SignatureUtils.readSignatures(sigKeyValid).get(0);
|
||||||
|
|
||||||
Policy policy = PGPainless.getPolicy();
|
|
||||||
String data = "Hello, World";
|
String data = "Hello, World";
|
||||||
Date validationDate = new Date();
|
|
||||||
|
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
|
predatesPrimaryKey, getSignedData(data), publicKeys),
|
||||||
"Signature predates primary key creation date");
|
"Signature predates primary key creation date");
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
keyNotBound, getSignedData(data), publicKeys, policy, validationDate),
|
keyNotBound, getSignedData(data), publicKeys),
|
||||||
"Signing key is not bound at this point");
|
"Signing key is not bound at this point");
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
keyRevoked, getSignedData(data), publicKeys, policy, validationDate),
|
keyRevoked, getSignedData(data), publicKeys),
|
||||||
"Signing key is revoked at this point");
|
"Signing key is revoked at this point");
|
||||||
assertDoesNotThrow(() ->
|
assertDoesNotThrow(() ->
|
||||||
verify(
|
verify(
|
||||||
valid, getSignedData(data), publicKeys, policy, validationDate),
|
valid, getSignedData(data), publicKeys),
|
||||||
"Signing key is revalidated");
|
"Signing key is revalidated");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -931,22 +920,20 @@ public class CertificateValidatorTest {
|
||||||
PGPSignature revoked = SignatureUtils.readSignatures(sigRevoked).get(0);
|
PGPSignature revoked = SignatureUtils.readSignatures(sigRevoked).get(0);
|
||||||
PGPSignature revalidated = SignatureUtils.readSignatures(sigReLegitimized).get(0);
|
PGPSignature revalidated = SignatureUtils.readSignatures(sigReLegitimized).get(0);
|
||||||
|
|
||||||
Policy policy = PGPainless.getPolicy();
|
|
||||||
Date validationDate = new Date();
|
|
||||||
String data = "Hello, World";
|
String data = "Hello, World";
|
||||||
|
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
predatesPrimaryKey, getSignedData(data), publicKeys, policy, validationDate),
|
predatesPrimaryKey, getSignedData(data), publicKeys),
|
||||||
"Signature predates primary key creation date");
|
"Signature predates primary key creation date");
|
||||||
assertDoesNotThrow(() -> verify(
|
assertDoesNotThrow(() -> verify(
|
||||||
valid, getSignedData(data), publicKeys, policy, validationDate),
|
valid, getSignedData(data), publicKeys),
|
||||||
"Signature is valid");
|
"Signature is valid");
|
||||||
assertThrows(SignatureValidationException.class, () ->
|
assertThrows(SignatureValidationException.class, () ->
|
||||||
verify(
|
verify(
|
||||||
revoked, getSignedData(data), publicKeys, policy, validationDate),
|
revoked, getSignedData(data), publicKeys),
|
||||||
"Primary key is revoked");
|
"Primary key is revoked");
|
||||||
assertDoesNotThrow(() -> verify(
|
assertDoesNotThrow(() -> verify(
|
||||||
revalidated, getSignedData(data), publicKeys, policy, validationDate),
|
revalidated, getSignedData(data), publicKeys),
|
||||||
"Primary key is re-legitimized");
|
"Primary key is re-legitimized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1271,52 +1258,50 @@ public class CertificateValidatorTest {
|
||||||
PGPSignature sigCT2_T3 = SignatureUtils.readSignatures(keyCSigT2_T3).get(0);
|
PGPSignature sigCT2_T3 = SignatureUtils.readSignatures(keyCSigT2_T3).get(0);
|
||||||
PGPSignature sigCT3_now = SignatureUtils.readSignatures(keyCSigT3_now).get(0);
|
PGPSignature sigCT3_now = SignatureUtils.readSignatures(keyCSigT3_now).get(0);
|
||||||
|
|
||||||
Policy policy = PGPainless.getPolicy();
|
|
||||||
Date validationDate = new Date();
|
|
||||||
String data = "Hello World :)";
|
String data = "Hello World :)";
|
||||||
|
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
sigAT0, getSignedData(data), keysA, policy, validationDate),
|
sigAT0, getSignedData(data), keysA),
|
||||||
"Signature predates key creation time");
|
"Signature predates key creation time");
|
||||||
assertDoesNotThrow(() -> verify(
|
assertDoesNotThrow(() -> verify(
|
||||||
sigAT1_T2, getSignedData(data), keysA, policy, validationDate),
|
sigAT1_T2, getSignedData(data), keysA),
|
||||||
"Key valid");
|
"Key valid");
|
||||||
assertThrows(SignatureValidationException.class, () ->
|
assertThrows(SignatureValidationException.class, () ->
|
||||||
verify(
|
verify(
|
||||||
sigAT2_T3, getSignedData(data), keysA, policy, validationDate),
|
sigAT2_T3, getSignedData(data), keysA),
|
||||||
"Key is not valid, as subkey binding expired");
|
"Key is not valid, as subkey binding expired");
|
||||||
assertDoesNotThrow(() -> verify(
|
assertDoesNotThrow(() -> verify(
|
||||||
sigAT3_now, getSignedData(data), keysA, policy, validationDate),
|
sigAT3_now, getSignedData(data), keysA),
|
||||||
"Key is valid again");
|
"Key is valid again");
|
||||||
|
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
sigBT0, getSignedData(data), keysB, policy, validationDate),
|
sigBT0, getSignedData(data), keysB),
|
||||||
"Signature predates key creation time");
|
"Signature predates key creation time");
|
||||||
assertDoesNotThrow(() -> verify(
|
assertDoesNotThrow(() -> verify(
|
||||||
sigBT1_T2, getSignedData(data), keysB, policy, validationDate),
|
sigBT1_T2, getSignedData(data), keysB),
|
||||||
"Key is valid");
|
"Key is valid");
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
sigBT2_T3, getSignedData(data), keysB, policy, validationDate),
|
sigBT2_T3, getSignedData(data), keysB),
|
||||||
"Primary key is not signing-capable");
|
"Primary key is not signing-capable");
|
||||||
assertDoesNotThrow(() -> verify(
|
assertDoesNotThrow(() -> verify(
|
||||||
sigBT3_now, getSignedData(data), keysB, policy, validationDate),
|
sigBT3_now, getSignedData(data), keysB),
|
||||||
"Key is valid again");
|
"Key is valid again");
|
||||||
|
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
sigCT0, getSignedData(data), keysC, policy, validationDate),
|
sigCT0, getSignedData(data), keysC),
|
||||||
"Signature predates key creation time");
|
"Signature predates key creation time");
|
||||||
assertDoesNotThrow(() -> verify(
|
assertDoesNotThrow(() -> verify(
|
||||||
sigCT1_T2, getSignedData(data), keysC, policy, validationDate),
|
sigCT1_T2, getSignedData(data), keysC),
|
||||||
"Key is valid");
|
"Key is valid");
|
||||||
assertThrows(SignatureValidationException.class, () -> verify(
|
assertThrows(SignatureValidationException.class, () -> verify(
|
||||||
sigCT2_T3, getSignedData(data), keysC, policy, validationDate),
|
sigCT2_T3, getSignedData(data), keysC),
|
||||||
"Key is revoked");
|
"Key is revoked");
|
||||||
assertDoesNotThrow(() -> verify(
|
assertDoesNotThrow(() -> verify(
|
||||||
sigCT3_now, getSignedData(data), keysC, policy, validationDate),
|
sigCT3_now, getSignedData(data), keysC),
|
||||||
"Key is valid again");
|
"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();
|
PGPainless api = PGPainless.getInstance();
|
||||||
OpenPGPCertificate certificate = api.toCertificate(cert);
|
OpenPGPCertificate certificate = api.toCertificate(cert);
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ class SOPImpl(
|
||||||
private val sopv: SOPV = SOPVImpl(api)
|
private val sopv: SOPV = SOPVImpl(api)
|
||||||
) : SOP {
|
) : SOP {
|
||||||
|
|
||||||
|
constructor(api: PGPainless) : this(api, SOPVImpl(api))
|
||||||
|
|
||||||
override fun armor(): Armor = ArmorImpl(api)
|
override fun armor(): Armor = ArmorImpl(api)
|
||||||
|
|
||||||
override fun changeKeyPassword(): ChangeKeyPassword = ChangeKeyPasswordImpl(api)
|
override fun changeKeyPassword(): ChangeKeyPassword = ChangeKeyPasswordImpl(api)
|
||||||
|
|
|
@ -123,7 +123,8 @@ public class VerifyLegacySignatureTest {
|
||||||
"=TtKx\n" +
|
"=TtKx\n" +
|
||||||
"-----END PGP MESSAGE-----";
|
"-----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))
|
byte[] cert = sop.extractCert().key(KEY.getBytes(StandardCharsets.UTF_8))
|
||||||
.getBytes();
|
.getBytes();
|
||||||
ByteArrayAndResult<List<Verification>> result = sop.inlineVerify()
|
ByteArrayAndResult<List<Verification>> result = sop.inlineVerify()
|
||||||
|
@ -134,12 +135,13 @@ public class VerifyLegacySignatureTest {
|
||||||
assertFalse(result.getResult().isEmpty());
|
assertFalse(result.getResult().isEmpty());
|
||||||
|
|
||||||
// Adjust data signature hash policy to accept new SHA-1 sigs
|
// Adjust data signature hash policy to accept new SHA-1 sigs
|
||||||
Policy policy = PGPainless.getPolicy();
|
Policy policy = api.getAlgorithmPolicy();
|
||||||
Policy adjusted = policy.copy()
|
Policy adjusted = policy.copy()
|
||||||
.withDataSignatureHashAlgorithmPolicy(
|
.withDataSignatureHashAlgorithmPolicy(
|
||||||
Policy.HashAlgorithmPolicy.static2022RevocationSignatureHashAlgorithmPolicy()
|
Policy.HashAlgorithmPolicy.static2022RevocationSignatureHashAlgorithmPolicy()
|
||||||
).build();
|
).build();
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(adjusted);
|
api = new PGPainless(adjusted);
|
||||||
|
sop = new SOPImpl(api);
|
||||||
|
|
||||||
// Sig generated in 2024 using SHA1
|
// Sig generated in 2024 using SHA1
|
||||||
String newSig = "-----BEGIN PGP MESSAGE-----\n" +
|
String newSig = "-----BEGIN PGP MESSAGE-----\n" +
|
||||||
|
@ -164,8 +166,5 @@ public class VerifyLegacySignatureTest {
|
||||||
.toByteArrayAndResult();
|
.toByteArrayAndResult();
|
||||||
|
|
||||||
assertFalse(result.getResult().isEmpty());
|
assertFalse(result.getResult().isEmpty());
|
||||||
|
|
||||||
// Reset old policy
|
|
||||||
PGPainless.getInstance().setAlgorithmPolicy(policy);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue