From e46e9fa1f5a6a1278ba737a69f459e8c7bce1d89 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sun, 16 Mar 2025 22:01:59 +0100 Subject: [PATCH] Rework Policy to be immutable. Changes are now done by calling policy.copy().withXYZ().build() --- .../main/kotlin/org/pgpainless/PGPainless.kt | 8 +- .../kotlin/org/pgpainless/policy/Policy.kt | 113 ++++++++++++++++-- .../EncryptDecryptTest.java | 5 +- .../org/pgpainless/example/ManagePolicy.java | 69 +++++------ .../GeneratingWeakKeyThrowsTest.java | 16 ++- .../RefuseToAddWeakSubkeyTest.java | 15 ++- .../pgpainless/policy/PolicySetterTest.java | 16 +-- .../org/pgpainless/policy/PolicyTest.java | 33 ++--- .../sop/VerifyLegacySignatureTest.java | 11 +- 9 files changed, 192 insertions(+), 94 deletions(-) diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/PGPainless.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/PGPainless.kt index 98ff0603..c5768e99 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/PGPainless.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/PGPainless.kt @@ -34,7 +34,7 @@ import org.pgpainless.util.ArmorUtils class PGPainless( val implementation: OpenPGPImplementation = OpenPGPImplementation.getInstance(), - val algorithmPolicy: Policy = Policy.getInstance() + var algorithmPolicy: Policy = Policy.getInstance() ) { private var api: OpenPGPApi @@ -230,7 +230,11 @@ class PGPainless( * * @return policy */ - @JvmStatic fun getPolicy() = getInstance().algorithmPolicy + @Deprecated( + "Use PGPainless.getInstance().getAlgorithmPolicy() instead.", + replaceWith = ReplaceWith("getInstance().algorithmPolicy")) + @JvmStatic + fun getPolicy() = getInstance().algorithmPolicy /** * Create different kinds of signatures on other keys. diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/policy/Policy.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/policy/Policy.kt index 61978792..eb875e21 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/policy/Policy.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/policy/Policy.kt @@ -11,15 +11,16 @@ import org.pgpainless.util.DateUtil import org.pgpainless.util.NotationRegistry class Policy( - var certificationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy, - var revocationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy, - var dataSignatureHashAlgorithmPolicy: HashAlgorithmPolicy, - var symmetricKeyEncryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy, - var symmetricKeyDecryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy, - var compressionAlgorithmPolicy: CompressionAlgorithmPolicy, - var publicKeyAlgorithmPolicy: PublicKeyAlgorithmPolicy, - var keyProtectionSettings: KeyRingProtectionSettings, - var notationRegistry: NotationRegistry + val certificationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy, + val revocationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy, + val dataSignatureHashAlgorithmPolicy: HashAlgorithmPolicy, + val symmetricKeyEncryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy, + val symmetricKeyDecryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy, + val compressionAlgorithmPolicy: CompressionAlgorithmPolicy, + val publicKeyAlgorithmPolicy: PublicKeyAlgorithmPolicy, + val keyProtectionSettings: KeyRingProtectionSettings, + val notationRegistry: NotationRegistry, + val keyGenerationAlgorithmSuite: AlgorithmSuite ) { constructor() : @@ -32,12 +33,14 @@ class Policy( CompressionAlgorithmPolicy.anyCompressionAlgorithmPolicy(), PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy(), KeyRingProtectionSettings.secureDefaultSettings(), - NotationRegistry()) + NotationRegistry(), + AlgorithmSuite.defaultAlgorithmSuite) - var keyGenerationAlgorithmSuite = AlgorithmSuite.defaultAlgorithmSuite var signerUserIdValidationLevel = SignerUserIdValidationLevel.DISABLED var enableKeyParameterValidation = false + fun copy() = Builder(this) + fun isEnableKeyParameterValidation() = enableKeyParameterValidation /** @@ -415,4 +418,92 @@ class Policy( fun getInstance() = INSTANCE ?: synchronized(this) { INSTANCE ?: Policy().also { INSTANCE = it } } } + + class Builder(private val origin: Policy) { + private var certificationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy = + origin.certificationSignatureHashAlgorithmPolicy + private var revocationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy = + origin.revocationSignatureHashAlgorithmPolicy + private var dataSignatureHashAlgorithmPolicy: HashAlgorithmPolicy = + origin.dataSignatureHashAlgorithmPolicy + private var symmetricKeyEncryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy = + origin.symmetricKeyEncryptionAlgorithmPolicy + private var symmetricKeyDecryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy = + origin.symmetricKeyDecryptionAlgorithmPolicy + private var compressionAlgorithmPolicy: CompressionAlgorithmPolicy = + origin.compressionAlgorithmPolicy + private var publicKeyAlgorithmPolicy: PublicKeyAlgorithmPolicy = + origin.publicKeyAlgorithmPolicy + private var keyProtectionSettings: KeyRingProtectionSettings = origin.keyProtectionSettings + private var notationRegistry: NotationRegistry = origin.notationRegistry + private var keyGenerationAlgorithmSuite: AlgorithmSuite = origin.keyGenerationAlgorithmSuite + + fun withCertificationSignatureHashAlgorithmPolicy( + certificationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy + ) = apply { + this.certificationSignatureHashAlgorithmPolicy = + certificationSignatureHashAlgorithmPolicy + } + + fun withRevocationSignatureHashAlgorithmPolicy( + revocationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy + ) = apply { + this.revocationSignatureHashAlgorithmPolicy = revocationSignatureHashAlgorithmPolicy + } + + fun withDataSignatureHashAlgorithmPolicy( + dataSignatureHashAlgorithmPolicy: HashAlgorithmPolicy + ) = apply { this.dataSignatureHashAlgorithmPolicy = dataSignatureHashAlgorithmPolicy } + + fun withSymmetricKeyEncryptionAlgorithmPolicy( + symmetricKeyEncryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy + ) = apply { + this.symmetricKeyEncryptionAlgorithmPolicy = symmetricKeyEncryptionAlgorithmPolicy + } + + fun withSymmetricKeyDecryptionAlgorithmPolicy( + symmetricKeyDecryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy + ) = apply { + this.symmetricKeyDecryptionAlgorithmPolicy = symmetricKeyDecryptionAlgorithmPolicy + } + + fun withCompressionAlgorithmPolicy(compressionAlgorithmPolicy: CompressionAlgorithmPolicy) = + apply { + this.compressionAlgorithmPolicy = compressionAlgorithmPolicy + } + + fun withPublicKeyAlgorithmPolicy(publicKeyAlgorithmPolicy: PublicKeyAlgorithmPolicy) = + apply { + this.publicKeyAlgorithmPolicy = publicKeyAlgorithmPolicy + } + + fun withKeyProtectionSettings(keyProtectionSettings: KeyRingProtectionSettings) = apply { + this.keyProtectionSettings = keyProtectionSettings + } + + fun withNotationRegistry(notationRegistry: NotationRegistry) = apply { + this.notationRegistry = notationRegistry + } + + fun withKeyGenerationAlgorithmSuite(keyGenerationAlgorithmSuite: AlgorithmSuite) = apply { + this.keyGenerationAlgorithmSuite = keyGenerationAlgorithmSuite + } + + fun build() = + Policy( + certificationSignatureHashAlgorithmPolicy, + revocationSignatureHashAlgorithmPolicy, + dataSignatureHashAlgorithmPolicy, + symmetricKeyEncryptionAlgorithmPolicy, + symmetricKeyDecryptionAlgorithmPolicy, + compressionAlgorithmPolicy, + publicKeyAlgorithmPolicy, + keyProtectionSettings, + notationRegistry, + keyGenerationAlgorithmSuite) + .apply { + enableKeyParameterValidation = origin.enableKeyParameterValidation + signerUserIdValidationLevel = origin.signerUserIdValidationLevel + } + } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/EncryptDecryptTest.java b/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/EncryptDecryptTest.java index 71e5085e..6352984a 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/EncryptDecryptTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/EncryptDecryptTest.java @@ -59,10 +59,7 @@ public class EncryptDecryptTest { @BeforeEach public void setDefaultPolicy() { - PGPainless.getPolicy().setSymmetricKeyEncryptionAlgorithmPolicy( - Policy.SymmetricKeyAlgorithmPolicy.symmetricKeyEncryptionPolicy2022()); - PGPainless.getPolicy().setSymmetricKeyDecryptionAlgorithmPolicy( - Policy.SymmetricKeyAlgorithmPolicy.symmetricKeyDecryptionPolicy2022()); + PGPainless.getInstance().setAlgorithmPolicy(new Policy()); } @TestTemplate diff --git a/pgpainless-core/src/test/java/org/pgpainless/example/ManagePolicy.java b/pgpainless-core/src/test/java/org/pgpainless/example/ManagePolicy.java index 3b29e35d..c0cbc505 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/example/ManagePolicy.java +++ b/pgpainless-core/src/test/java/org/pgpainless/example/ManagePolicy.java @@ -25,13 +25,13 @@ import org.pgpainless.util.NotationRegistry; * can be rejected. * Note, that PGPainless distinguishes between hash algorithms used in revocation and non-revocation signatures, * and has different policies for those. - * + *

* Furthermore, PGPainless has policies for symmetric encryption algorithms (both for encrypting and decrypting), * for public key algorithms and key lengths, as well as compression algorithms. - * + *

* The following examples show how these policies can be modified. - * - * PGPainless' policy is being accessed by calling {@link PGPainless#getPolicy()}. + *

+ * PGPainless' policy is being accessed by calling {@link PGPainless#getAlgorithmPolicy()}. * Custom sub-policies can be set by calling the setter methods of {@link Policy}. */ public class ManagePolicy { @@ -43,50 +43,29 @@ public class ManagePolicy { @AfterEach public void resetPolicy() { // Policy for hash algorithms in non-revocation signatures - PGPainless.getPolicy().setCertificationSignatureHashAlgorithmPolicy( - Policy.HashAlgorithmPolicy.static2022SignatureHashAlgorithmPolicy()); - // Policy for hash algorithms in data signatures - PGPainless.getPolicy().setDataSignatureHashAlgorithmPolicy( - Policy.HashAlgorithmPolicy.static2022SignatureHashAlgorithmPolicy()); - // Policy for hash algorithms in revocation signatures - PGPainless.getPolicy().setRevocationSignatureHashAlgorithmPolicy( - Policy.HashAlgorithmPolicy.static2022RevocationSignatureHashAlgorithmPolicy()); - // Policy for public key algorithms and bit lengths - PGPainless.getPolicy().setPublicKeyAlgorithmPolicy( - Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy()); - // Policy for acceptable symmetric encryption algorithms when decrypting messages - PGPainless.getPolicy().setSymmetricKeyDecryptionAlgorithmPolicy( - Policy.SymmetricKeyAlgorithmPolicy.symmetricKeyDecryptionPolicy2022()); - // Policy for acceptable symmetric encryption algorithms when encrypting messages - PGPainless.getPolicy().setSymmetricKeyEncryptionAlgorithmPolicy( - Policy.SymmetricKeyAlgorithmPolicy.symmetricKeyEncryptionPolicy2022()); - // Policy for acceptable compression algorithms - PGPainless.getPolicy().setCompressionAlgorithmPolicy( - Policy.CompressionAlgorithmPolicy.anyCompressionAlgorithmPolicy()); - // Known notations - PGPainless.getPolicy().getNotationRegistry().clear(); + 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. - * + *

* PGPainless comes with a {@link Policy} class that defines which algorithms are trustworthy and acceptable. * It also allows the user to specify a custom policy tailored to their needs. - * + *

* Per default, PGPainless will reject non-revocation signatures that use SHA-1 as hash algorithm. * To inspect PGPainless' default signature hash algorithm policy, see * {@link Policy.HashAlgorithmPolicy#static2022SignatureHashAlgorithmPolicy()}. - * + *

* Since it may be a valid use-case to accept signatures made using SHA-1 as part of a less strict policy, * this example demonstrates how to set a custom signature hash algorithm policy. */ @Test public void setCustomSignatureHashPolicy() { - // Get PGPainless' policy singleton - Policy policy = PGPainless.getPolicy(); + // Get PGPainless' policy + Policy oldPolicy = PGPainless.getInstance().getAlgorithmPolicy(); - Policy.HashAlgorithmPolicy sigHashAlgoPolicy = policy.getDataSignatureHashAlgorithmPolicy(); + Policy.HashAlgorithmPolicy sigHashAlgoPolicy = oldPolicy.getDataSignatureHashAlgorithmPolicy(); assertTrue(sigHashAlgoPolicy.isAcceptable(HashAlgorithm.SHA512)); // Per default, non-revocation signatures using SHA-1 are rejected assertFalse(sigHashAlgoPolicy.isAcceptable(HashAlgorithm.SHA1)); @@ -98,12 +77,17 @@ 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 - policy.setDataSignatureHashAlgorithmPolicy(customPolicy); + PGPainless.getInstance().setAlgorithmPolicy( + oldPolicy.copy().withDataSignatureHashAlgorithmPolicy(customPolicy).build() + ); - sigHashAlgoPolicy = policy.getDataSignatureHashAlgorithmPolicy(); + sigHashAlgoPolicy = PGPainless.getInstance().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); } /** @@ -111,13 +95,13 @@ public class ManagePolicy { * Per default, PGPainless will reject signatures made by keys of unacceptable algorithm or length. * See {@link Policy.PublicKeyAlgorithmPolicy#bsi2021PublicKeyAlgorithmPolicy()} * to inspect PGPainless' defaults. - * + *

* This example demonstrates how to set a custom public key algorithm policy. */ @Test public void setCustomPublicKeyAlgorithmPolicy() { - Policy policy = PGPainless.getPolicy(); - Policy.PublicKeyAlgorithmPolicy pkAlgorithmPolicy = policy.getPublicKeyAlgorithmPolicy(); + Policy oldPolicy = PGPainless.getInstance().getAlgorithmPolicy(); + Policy.PublicKeyAlgorithmPolicy pkAlgorithmPolicy = oldPolicy.getPublicKeyAlgorithmPolicy(); assertTrue(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 4096)); assertTrue(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 2048)); assertFalse(pkAlgorithmPolicy.isAcceptable(PublicKeyAlgorithm.RSA_GENERAL, 1024)); @@ -131,27 +115,30 @@ public class ManagePolicy { put(PublicKeyAlgorithm.RSA_GENERAL, 3000); }} ); - policy.setPublicKeyAlgorithmPolicy(customPolicy); + PGPainless.getInstance().setAlgorithmPolicy(oldPolicy.copy().withPublicKeyAlgorithmPolicy(customPolicy).build()); - pkAlgorithmPolicy = policy.getPublicKeyAlgorithmPolicy(); + pkAlgorithmPolicy = PGPainless.getInstance().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); } /** * OpenPGP requires implementations to reject signatures which contain critical notation data subpackets * which are not known to the implementation. - * + *

* PGPainless allows the user to define which notations should be considered known notations. * The following example demonstrates how to mark the notation value 'unknown@pgpainless.org' as known, * such that signatures containing a critical notation with that name are no longer being invalidated because of it. */ @Test public void manageKnownNotations() { - Policy policy = PGPainless.getPolicy(); + Policy policy = PGPainless.getInstance().getAlgorithmPolicy(); NotationRegistry notationRegistry = policy.getNotationRegistry(); assertFalse(notationRegistry.isKnownNotation("unknown@pgpainless.org")); diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/generation/GeneratingWeakKeyThrowsTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/generation/GeneratingWeakKeyThrowsTest.java index 65dea167..49db0243 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/generation/GeneratingWeakKeyThrowsTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/generation/GeneratingWeakKeyThrowsTest.java @@ -22,9 +22,7 @@ public class GeneratingWeakKeyThrowsTest { @Test public void refuseToGenerateWeakPrimaryKeyTest() { // ensure we have default public key algorithm policy set - PGPainless.getPolicy().setPublicKeyAlgorithmPolicy( - Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy()); - + PGPainless.getInstance().setAlgorithmPolicy(new Policy()); assertThrows(IllegalArgumentException.class, () -> PGPainless.buildKeyRing() .setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._1024), @@ -34,8 +32,7 @@ public class GeneratingWeakKeyThrowsTest { @Test public void refuseToAddWeakSubkeyDuringGenerationTest() { // ensure we have default public key algorithm policy set - PGPainless.getPolicy().setPublicKeyAlgorithmPolicy( - Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy()); + PGPainless.getInstance().setAlgorithmPolicy(new Policy()); KeyRingBuilder kb = PGPainless.buildKeyRing() .setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._4096), @@ -52,8 +49,10 @@ public class GeneratingWeakKeyThrowsTest { Map bitStrengths = new HashMap<>(); bitStrengths.put(PublicKeyAlgorithm.RSA_GENERAL, 512); - PGPainless.getPolicy().setPublicKeyAlgorithmPolicy( - new Policy.PublicKeyAlgorithmPolicy(bitStrengths)); + Policy oldPolicy = PGPainless.getPolicy(); + PGPainless.getInstance().setAlgorithmPolicy(oldPolicy.copy() + .withPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(bitStrengths)) + .build()); PGPainless.buildKeyRing() .setPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._4096), @@ -64,7 +63,6 @@ public class GeneratingWeakKeyThrowsTest { .build(); // reset public key algorithm policy - PGPainless.getPolicy().setPublicKeyAlgorithmPolicy( - Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy()); + PGPainless.getInstance().setAlgorithmPolicy(oldPolicy); } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RefuseToAddWeakSubkeyTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RefuseToAddWeakSubkeyTest.java index e640302e..925b4426 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/RefuseToAddWeakSubkeyTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/RefuseToAddWeakSubkeyTest.java @@ -29,7 +29,11 @@ public class RefuseToAddWeakSubkeyTest { @Test public void testEditorRefusesToAddWeakSubkey() { // ensure default policy is set - PGPainless.getPolicy().setPublicKeyAlgorithmPolicy(Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy()); + Policy oldPolicy = PGPainless.getPolicy(); + Policy adjusted = oldPolicy.copy().withPublicKeyAlgorithmPolicy( + Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy() + ).build(); + PGPainless.getInstance().setAlgorithmPolicy(adjusted); PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() .modernKeyRing("Alice") @@ -39,6 +43,7 @@ public class RefuseToAddWeakSubkeyTest { assertThrows(IllegalArgumentException.class, () -> editor.addSubKey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys())); + PGPainless.getInstance().setAlgorithmPolicy(oldPolicy); } @Test @@ -47,6 +52,8 @@ public class RefuseToAddWeakSubkeyTest { .modernKeyRing("Alice") .getPGPSecretKeyRing(); + Policy oldPolicy = PGPainless.getPolicy(); + // set weak policy Map minimalBitStrengths = new EnumMap<>(PublicKeyAlgorithm.class); // §5.4.1 @@ -68,7 +75,9 @@ public class RefuseToAddWeakSubkeyTest { minimalBitStrengths.put(PublicKeyAlgorithm.DIFFIE_HELLMAN, 2000); // §7.2.2 minimalBitStrengths.put(PublicKeyAlgorithm.ECDH, 250); - PGPainless.getPolicy().setPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(minimalBitStrengths)); + PGPainless.getInstance().setAlgorithmPolicy(oldPolicy.copy() + .withPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(minimalBitStrengths)) + .build()); SecretKeyRingEditorInterface editor = PGPainless.modifyKeyRing(secretKeys); KeySpec spec = KeySpec.getBuilder(KeyType.RSA(RsaLength._1024), KeyFlag.ENCRYPT_COMMS) @@ -81,6 +90,6 @@ public class RefuseToAddWeakSubkeyTest { assertEquals(2, PGPainless.inspectKeyRing(secretKeys).getEncryptionSubkeys(EncryptionPurpose.ANY).size()); // reset default policy - PGPainless.getPolicy().setPublicKeyAlgorithmPolicy(Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy()); + PGPainless.getInstance().setAlgorithmPolicy(oldPolicy); } } diff --git a/pgpainless-core/src/test/java/org/pgpainless/policy/PolicySetterTest.java b/pgpainless-core/src/test/java/org/pgpainless/policy/PolicySetterTest.java index 6e90847d..bd044b3b 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/policy/PolicySetterTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/policy/PolicySetterTest.java @@ -18,43 +18,43 @@ public class PolicySetterTest { @Test public void testSetCertificationSignatureHashAlgorithmPolicy_NullFails() { Policy policy = Policy.getInstance(); - assertThrows(NullPointerException.class, () -> policy.setCertificationSignatureHashAlgorithmPolicy(null)); + assertThrows(NullPointerException.class, () -> policy.copy().withCertificationSignatureHashAlgorithmPolicy(null)); } @Test public void testSetDataSignatureHashAlgorithmPolicy_NullFails() { Policy policy = Policy.getInstance(); - assertThrows(NullPointerException.class, () -> policy.setDataSignatureHashAlgorithmPolicy(null)); + assertThrows(NullPointerException.class, () -> policy.copy().withDataSignatureHashAlgorithmPolicy(null)); } @Test public void testSetRevocationSignatureHashAlgorithmPolicy_NullFails() { Policy policy = Policy.getInstance(); - assertThrows(NullPointerException.class, () -> policy.setRevocationSignatureHashAlgorithmPolicy(null)); + assertThrows(NullPointerException.class, () -> policy.copy().withRevocationSignatureHashAlgorithmPolicy(null)); } @Test public void testSetSymmetricKeyEncryptionAlgorithmPolicy_NullFails() { Policy policy = Policy.getInstance(); - assertThrows(NullPointerException.class, () -> policy.setSymmetricKeyEncryptionAlgorithmPolicy(null)); + assertThrows(NullPointerException.class, () -> policy.copy().withSymmetricKeyEncryptionAlgorithmPolicy(null)); } @Test public void testSetSymmetricKeyDecryptionAlgorithmPolicy_NullFails() { Policy policy = Policy.getInstance(); - assertThrows(NullPointerException.class, () -> policy.setSymmetricKeyDecryptionAlgorithmPolicy(null)); + assertThrows(NullPointerException.class, () -> policy.copy().withSymmetricKeyDecryptionAlgorithmPolicy(null)); } @Test public void testSetCompressionAlgorithmPolicy_NullFails() { Policy policy = Policy.getInstance(); - assertThrows(NullPointerException.class, () -> policy.setCompressionAlgorithmPolicy(null)); + assertThrows(NullPointerException.class, () -> policy.copy().withCompressionAlgorithmPolicy(null)); } @Test public void testSetPublicKeyAlgorithmPolicy_NullFails() { Policy policy = Policy.getInstance(); - assertThrows(NullPointerException.class, () -> policy.setPublicKeyAlgorithmPolicy(null)); + assertThrows(NullPointerException.class, () -> policy.copy().withPublicKeyAlgorithmPolicy(null)); } @Test @@ -62,7 +62,7 @@ public class PolicySetterTest { Policy policy = new Policy(); Map acceptableAlgorithms = new HashMap<>(); acceptableAlgorithms.put(PublicKeyAlgorithm.RSA_GENERAL, 2000); - policy.setPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(acceptableAlgorithms)); + policy = policy.copy().withPublicKeyAlgorithmPolicy(new Policy.PublicKeyAlgorithmPolicy(acceptableAlgorithms)).build(); // Policy does not contain ECDSA assertFalse(policy.getPublicKeyAlgorithmPolicy().isAcceptable(PublicKeyAlgorithm.ECDSA, 256)); diff --git a/pgpainless-core/src/test/java/org/pgpainless/policy/PolicyTest.java b/pgpainless-core/src/test/java/org/pgpainless/policy/PolicyTest.java index 9ff4df85..27288218 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/policy/PolicyTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/policy/PolicyTest.java @@ -28,23 +28,12 @@ public class PolicyTest { @BeforeAll public static void setup() { - policy = new Policy(); - policy.setCompressionAlgorithmPolicy(new Policy.CompressionAlgorithmPolicy(CompressionAlgorithm.UNCOMPRESSED, - Arrays.asList(CompressionAlgorithm.ZIP, CompressionAlgorithm.ZLIB, CompressionAlgorithm.UNCOMPRESSED))); - - policy.setSymmetricKeyEncryptionAlgorithmPolicy(new Policy.SymmetricKeyAlgorithmPolicy(SymmetricKeyAlgorithm.AES_256, - Arrays.asList(SymmetricKeyAlgorithm.AES_256, SymmetricKeyAlgorithm.AES_192, SymmetricKeyAlgorithm.AES_128))); - - policy.setSymmetricKeyDecryptionAlgorithmPolicy(new Policy.SymmetricKeyAlgorithmPolicy(SymmetricKeyAlgorithm.AES_256, - Arrays.asList(SymmetricKeyAlgorithm.AES_256, SymmetricKeyAlgorithm.AES_192, SymmetricKeyAlgorithm.AES_128, SymmetricKeyAlgorithm.BLOWFISH))); - Map sigHashAlgoMap = new HashMap<>(); sigHashAlgoMap.put(HashAlgorithm.SHA512, null); sigHashAlgoMap.put(HashAlgorithm.SHA384, null); sigHashAlgoMap.put(HashAlgorithm.SHA256, null); sigHashAlgoMap.put(HashAlgorithm.SHA224, null); sigHashAlgoMap.put(HashAlgorithm.SHA1, DateUtil.parseUTCDate("2013-02-01 00:00:00 UTC")); - policy.setCertificationSignatureHashAlgorithmPolicy(new Policy.HashAlgorithmPolicy(HashAlgorithm.SHA512, sigHashAlgoMap)); Map revHashAlgoMap = new HashMap<>(); revHashAlgoMap.put(HashAlgorithm.SHA512, null); @@ -53,10 +42,26 @@ public class PolicyTest { revHashAlgoMap.put(HashAlgorithm.SHA224, null); revHashAlgoMap.put(HashAlgorithm.SHA1, DateUtil.parseUTCDate("2013-02-01 00:00:00 UTC")); revHashAlgoMap.put(HashAlgorithm.RIPEMD160, DateUtil.parseUTCDate("2013-02-01 00:00:00 UTC")); - policy.setRevocationSignatureHashAlgorithmPolicy(new Policy.HashAlgorithmPolicy(HashAlgorithm.SHA512, - revHashAlgoMap)); - policy.setPublicKeyAlgorithmPolicy(Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy()); + policy = new Policy().copy() + + .withCompressionAlgorithmPolicy(new Policy.CompressionAlgorithmPolicy(CompressionAlgorithm.UNCOMPRESSED, + Arrays.asList(CompressionAlgorithm.ZIP, CompressionAlgorithm.ZLIB, CompressionAlgorithm.UNCOMPRESSED))) + + .withSymmetricKeyEncryptionAlgorithmPolicy(new Policy.SymmetricKeyAlgorithmPolicy(SymmetricKeyAlgorithm.AES_256, + Arrays.asList(SymmetricKeyAlgorithm.AES_256, SymmetricKeyAlgorithm.AES_192, SymmetricKeyAlgorithm.AES_128))) + + .withSymmetricKeyDecryptionAlgorithmPolicy(new Policy.SymmetricKeyAlgorithmPolicy(SymmetricKeyAlgorithm.AES_256, + Arrays.asList(SymmetricKeyAlgorithm.AES_256, SymmetricKeyAlgorithm.AES_192, SymmetricKeyAlgorithm.AES_128, SymmetricKeyAlgorithm.BLOWFISH))) + + .withCertificationSignatureHashAlgorithmPolicy(new Policy.HashAlgorithmPolicy(HashAlgorithm.SHA512, sigHashAlgoMap)) + + .withRevocationSignatureHashAlgorithmPolicy(new Policy.HashAlgorithmPolicy(HashAlgorithm.SHA512, + revHashAlgoMap)) + + .withPublicKeyAlgorithmPolicy(Policy.PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy()) + + .build(); } @Test diff --git a/pgpainless-sop/src/test/java/org/pgpainless/sop/VerifyLegacySignatureTest.java b/pgpainless-sop/src/test/java/org/pgpainless/sop/VerifyLegacySignatureTest.java index 23fd9840..721c338d 100644 --- a/pgpainless-sop/src/test/java/org/pgpainless/sop/VerifyLegacySignatureTest.java +++ b/pgpainless-sop/src/test/java/org/pgpainless/sop/VerifyLegacySignatureTest.java @@ -134,8 +134,12 @@ public class VerifyLegacySignatureTest { assertFalse(result.getResult().isEmpty()); // Adjust data signature hash policy to accept new SHA-1 sigs - PGPainless.getPolicy().setDataSignatureHashAlgorithmPolicy( - Policy.HashAlgorithmPolicy.static2022RevocationSignatureHashAlgorithmPolicy()); + Policy policy = PGPainless.getPolicy(); + Policy adjusted = policy.copy() + .withDataSignatureHashAlgorithmPolicy( + Policy.HashAlgorithmPolicy.static2022RevocationSignatureHashAlgorithmPolicy() + ).build(); + PGPainless.getInstance().setAlgorithmPolicy(adjusted); // Sig generated in 2024 using SHA1 String newSig = "-----BEGIN PGP MESSAGE-----\n" + @@ -160,5 +164,8 @@ public class VerifyLegacySignatureTest { .toByteArrayAndResult(); assertFalse(result.getResult().isEmpty()); + + // Reset old policy + PGPainless.getInstance().setAlgorithmPolicy(policy); } }