diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/algorithm/negotiation/CompressionAlgorithmNegotiator.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/algorithm/negotiation/CompressionAlgorithmNegotiator.kt new file mode 100644 index 00000000..a028fc84 --- /dev/null +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/algorithm/negotiation/CompressionAlgorithmNegotiator.kt @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: 2025 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.algorithm.negotiation + +import org.pgpainless.algorithm.CompressionAlgorithm +import org.pgpainless.policy.Policy + +fun interface CompressionAlgorithmNegotiator { + fun negotiate( + policy: Policy, + override: CompressionAlgorithm?, + orderedPreferences: Set? + ): CompressionAlgorithm + + companion object { + @JvmStatic + fun staticNegotiation(): CompressionAlgorithmNegotiator = + CompressionAlgorithmNegotiator { policy, override, _ -> + override ?: policy.compressionAlgorithmPolicy.defaultCompressionAlgorithm + } + } +} diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionOptions.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionOptions.kt index 60e98626..ee2c5b18 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionOptions.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/EncryptionOptions.kt @@ -27,6 +27,9 @@ import org.pgpainless.key.info.KeyRingInfo import org.pgpainless.util.Passphrase class EncryptionOptions(private val purpose: EncryptionPurpose, private val api: PGPainless) { + + var encryptionMechanismNegotiator: EncryptionMechanismNegotiator = + EncryptionMechanismNegotiator.modificationDetectionOrBetter(byPopularity()) private val _encryptionMethods: MutableSet = mutableSetOf() private val keysAndAccessors: MutableMap = mutableMapOf() private val _keyRingInfo: MutableMap = mutableMapOf() @@ -442,13 +445,12 @@ class EncryptionOptions(private val purpose: EncryptionPurpose, private val api: keysAndAccessors.values.map { it.preferredSymmetricKeyAlgorithms }.toList() val mechanism = - EncryptionMechanismNegotiator.modificationDetectionOrBetter(byPopularity()) - .negotiate( - api.algorithmPolicy, - encryptionMechanismOverride, - features, - aeadAlgorithms, - symmetricKeyAlgorithms) + encryptionMechanismNegotiator.negotiate( + api.algorithmPolicy, + encryptionMechanismOverride, + features, + aeadAlgorithms, + symmetricKeyAlgorithms) return mechanism } diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/ProducerOptions.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/ProducerOptions.kt index e2c4596f..900d7fe6 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/ProducerOptions.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/ProducerOptions.kt @@ -8,13 +8,15 @@ import java.util.* import org.bouncycastle.openpgp.PGPLiteralData import org.pgpainless.algorithm.CompressionAlgorithm import org.pgpainless.algorithm.StreamEncoding +import org.pgpainless.algorithm.negotiation.CompressionAlgorithmNegotiator import org.pgpainless.policy.Policy class ProducerOptions( val encryptionOptions: EncryptionOptions?, val signingOptions: SigningOptions? ) { - + var compressionAlgorithmNegotiator: CompressionAlgorithmNegotiator = + CompressionAlgorithmNegotiator.staticNegotiation() private var _fileName: String = "" private var _modificationDate: Date = PGPLiteralData.NOW private var encodingField: StreamEncoding = StreamEncoding.BINARY @@ -237,8 +239,8 @@ class ProducerOptions( } internal fun negotiateCompressionAlgorithm(policy: Policy): CompressionAlgorithm { - return compressionAlgorithmOverride - ?: policy.compressionAlgorithmPolicy.defaultCompressionAlgorithm + return compressionAlgorithmNegotiator.negotiate( + policy, compressionAlgorithmOverride, setOf()) } companion object { diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/SigningOptions.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/SigningOptions.kt index 0df6c931..ce0774e8 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/SigningOptions.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/encryption_signing/SigningOptions.kt @@ -15,6 +15,7 @@ import org.pgpainless.PGPainless import org.pgpainless.algorithm.DocumentSignatureType import org.pgpainless.algorithm.HashAlgorithm import org.pgpainless.algorithm.PublicKeyAlgorithm.Companion.requireFromId +import org.pgpainless.algorithm.negotiation.HashAlgorithmNegotiator import org.pgpainless.algorithm.negotiation.HashAlgorithmNegotiator.Companion.negotiateSignatureHashAlgorithm import org.pgpainless.exception.KeyException import org.pgpainless.exception.KeyException.* @@ -27,7 +28,8 @@ import org.pgpainless.signature.subpackets.SignatureSubpackets import org.pgpainless.signature.subpackets.SignatureSubpacketsHelper class SigningOptions(private val api: PGPainless) { - + var hashAlgorithmNegotiator: HashAlgorithmNegotiator = + negotiateSignatureHashAlgorithm(api.algorithmPolicy) val signingMethods: Map = mutableMapOf() private var _hashAlgorithmOverride: HashAlgorithm? = null private var _evaluationDate: Date = Date() @@ -200,8 +202,7 @@ class SigningOptions(private val api: PGPainless) { val hashAlgorithms = if (userId != null) keyRingInfo.getPreferredHashAlgorithms(userId) else keyRingInfo.getPreferredHashAlgorithms(signingPubKey.keyIdentifier) - val hashAlgorithm: HashAlgorithm = - negotiateHashAlgorithm(hashAlgorithms, api.algorithmPolicy) + val hashAlgorithm: HashAlgorithm = negotiateHashAlgorithm(hashAlgorithms) addSigningMethod( signingPrivKey, hashAlgorithm, signatureType, false, subpacketsCallback) } @@ -268,8 +269,7 @@ class SigningOptions(private val api: PGPainless) { val signingPrivKey = unlockSecretKey(signingKey, signingKeyProtector) val hashAlgorithms = keyRingInfo.getPreferredHashAlgorithms(signingKey.keyIdentifier) - val hashAlgorithm: HashAlgorithm = - negotiateHashAlgorithm(hashAlgorithms, api.algorithmPolicy) + val hashAlgorithm: HashAlgorithm = negotiateHashAlgorithm(hashAlgorithms) addSigningMethod(signingPrivKey, hashAlgorithm, signatureType, false, subpacketsCallback) } @@ -467,8 +467,7 @@ class SigningOptions(private val api: PGPainless) { val hashAlgorithms = if (userId != null) keyRingInfo.getPreferredHashAlgorithms(userId) else keyRingInfo.getPreferredHashAlgorithms(signingKey.keyIdentifier) - val hashAlgorithm: HashAlgorithm = - negotiateHashAlgorithm(hashAlgorithms, api.algorithmPolicy) + val hashAlgorithm: HashAlgorithm = negotiateHashAlgorithm(hashAlgorithms) addSigningMethod(signingPrivKey, hashAlgorithm, signatureType, true, subpacketCallback) } @@ -559,12 +558,8 @@ class SigningOptions(private val api: PGPainless) { * @param policy policy * @return selected hash algorithm */ - private fun negotiateHashAlgorithm( - preferences: Set?, - policy: Policy - ): HashAlgorithm { - return _hashAlgorithmOverride - ?: negotiateSignatureHashAlgorithm(policy).negotiateHashAlgorithm(preferences) + private fun negotiateHashAlgorithm(preferences: Set?): HashAlgorithm { + return _hashAlgorithmOverride ?: hashAlgorithmNegotiator.negotiateHashAlgorithm(preferences) } @Throws(PGPException::class)