diff --git a/pgpainless-cli/src/test/java/org/pgpainless/cli/commands/RoundTripEncryptDecryptCmdTest.java b/pgpainless-cli/src/test/java/org/pgpainless/cli/commands/RoundTripEncryptDecryptCmdTest.java
index 9d3b3b9d..e4fd9e0c 100644
--- a/pgpainless-cli/src/test/java/org/pgpainless/cli/commands/RoundTripEncryptDecryptCmdTest.java
+++ b/pgpainless-cli/src/test/java/org/pgpainless/cli/commands/RoundTripEncryptDecryptCmdTest.java
@@ -14,7 +14,6 @@ import java.io.IOException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.KeyFlag;
@@ -135,7 +134,7 @@ public class RoundTripEncryptDecryptCmdTest extends CLITest {
}
@Test
- @Disabled("Disabled, since we now read certificates from secret keys")
+ // @Disabled("Disabled, since we now read certificates from secret keys")
public void testEncryptingForKeyFails() throws IOException {
File notACert = writeFile("key.asc", KEY);
diff --git a/pgpainless-core/src/main/java/org/gnupg/GnuPGDummyKeyUtil.java b/pgpainless-core/src/main/java/org/gnupg/GnuPGDummyKeyUtil.java
index 754ef3fa..48390c59 100644
--- a/pgpainless-core/src/main/java/org/gnupg/GnuPGDummyKeyUtil.java
+++ b/pgpainless-core/src/main/java/org/gnupg/GnuPGDummyKeyUtil.java
@@ -61,8 +61,7 @@ public final class GnuPGDummyKeyUtil {
return hardwareBackedKeys;
}
- public static Builder modify(@Nonnull OpenPGPKey key)
- {
+ public static Builder modify(@Nonnull OpenPGPKey key) {
return modify(key.getPGPSecretKeyRing());
}
diff --git a/pgpainless-core/src/main/java/org/pgpainless/exception/WrongPassphraseException.java b/pgpainless-core/src/main/java/org/pgpainless/exception/WrongPassphraseException.java
index 409db3e2..d039ca6a 100644
--- a/pgpainless-core/src/main/java/org/pgpainless/exception/WrongPassphraseException.java
+++ b/pgpainless-core/src/main/java/org/pgpainless/exception/WrongPassphraseException.java
@@ -4,6 +4,7 @@
package org.pgpainless.exception;
+import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.openpgp.PGPException;
public class WrongPassphraseException extends PGPException {
@@ -13,7 +14,11 @@ public class WrongPassphraseException extends PGPException {
}
public WrongPassphraseException(long keyId, PGPException cause) {
- this("Wrong passphrase provided for key " + Long.toHexString(keyId), cause);
+ this(new KeyIdentifier(keyId), cause);
+ }
+
+ public WrongPassphraseException(KeyIdentifier keyIdentifier, PGPException cause) {
+ this("Wrong passphrase provided for key " + keyIdentifier, cause);
}
public WrongPassphraseException(String message, PGPException cause) {
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/PGPKeyRingExtensions.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/PGPKeyRingExtensions.kt
index 7126db66..5727ee7c 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/PGPKeyRingExtensions.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/PGPKeyRingExtensions.kt
@@ -9,6 +9,8 @@ import org.bouncycastle.openpgp.PGPKeyRing
import org.bouncycastle.openpgp.PGPOnePassSignature
import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPSignature
+import org.bouncycastle.openpgp.api.OpenPGPCertificate
+import org.bouncycastle.openpgp.api.OpenPGPImplementation
import org.pgpainless.PGPainless
import org.pgpainless.key.OpenPgpFingerprint
import org.pgpainless.key.SubkeyIdentifier
@@ -72,3 +74,10 @@ val PGPKeyRing.openPgpFingerprint: OpenPgpFingerprint
/** Return this OpenPGP key as an ASCII armored String. */
fun PGPKeyRing.toAsciiArmor(): String = PGPainless.asciiArmor(this)
+
+@Deprecated("Use toOpenPGPCertificate(implementation) instead.")
+fun PGPKeyRing.toOpenPGPCertificate(): OpenPGPCertificate =
+ toOpenPGPCertificate(PGPainless.getInstance().implementation)
+
+fun PGPKeyRing.toOpenPGPCertificate(implementation: OpenPGPImplementation): OpenPGPCertificate =
+ OpenPGPCertificate(this, implementation)
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/PGPSecretKeyRingExtensions.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/PGPSecretKeyRingExtensions.kt
index 53e7e0c5..90c67236 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/PGPSecretKeyRingExtensions.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/bouncycastle/extensions/PGPSecretKeyRingExtensions.kt
@@ -6,6 +6,9 @@ package org.pgpainless.bouncycastle.extensions
import openpgp.openPgpKeyId
import org.bouncycastle.openpgp.*
+import org.bouncycastle.openpgp.api.OpenPGPImplementation
+import org.bouncycastle.openpgp.api.OpenPGPKey
+import org.pgpainless.PGPainless
import org.pgpainless.key.OpenPgpFingerprint
/** OpenPGP certificate containing the public keys of this OpenPGP key. */
@@ -74,3 +77,10 @@ fun PGPSecretKeyRing.getSecretKeyFor(onePassSignature: PGPOnePassSignature): PGP
fun PGPSecretKeyRing.getSecretKeyFor(pkesk: PGPPublicKeyEncryptedData): PGPSecretKey? =
this.getSecretKey(pkesk.keyIdentifier)
+
+@Deprecated("Use toOpenPGPKey(implementation) instead.")
+fun PGPSecretKeyRing.toOpenPGPKey(): OpenPGPKey =
+ toOpenPGPKey(PGPainless.getInstance().implementation)
+
+fun PGPSecretKeyRing.toOpenPGPKey(implementation: OpenPGPImplementation): OpenPGPKey =
+ OpenPGPKey(this, implementation)
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/ConsumerOptions.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/ConsumerOptions.kt
index de03b9d3..363bc7fa 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/ConsumerOptions.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/ConsumerOptions.kt
@@ -4,17 +4,16 @@
package org.pgpainless.decryption_verification
-import org.bouncycastle.bcpg.KeyIdentifier
import java.io.IOException
import java.io.InputStream
import java.util.*
+import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.*
import org.bouncycastle.openpgp.api.OpenPGPCertificate
import org.bouncycastle.openpgp.api.OpenPGPImplementation
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory
import org.pgpainless.PGPainless
-import org.pgpainless.bouncycastle.extensions.getPublicKeyFor
import org.pgpainless.decryption_verification.cleartext_signatures.InMemoryMultiPassStrategy
import org.pgpainless.decryption_verification.cleartext_signatures.MultiPassStrategy
import org.pgpainless.key.SubkeyIdentifier
@@ -24,9 +23,7 @@ import org.pgpainless.util.Passphrase
import org.pgpainless.util.SessionKey
/** Options for decryption and signature verification. */
-class ConsumerOptions(
- private val implementation: OpenPGPImplementation
-) {
+class ConsumerOptions {
private var ignoreMDCErrors = false
var isDisableAsciiArmorCRC = false
@@ -183,7 +180,8 @@ class ConsumerOptions(
@JvmOverloads
fun addDecryptionKey(
key: PGPSecretKeyRing,
- protector: SecretKeyRingProtector = SecretKeyRingProtector.unprotectedKeys()
+ protector: SecretKeyRingProtector = SecretKeyRingProtector.unprotectedKeys(),
+ implementation: OpenPGPImplementation = PGPainless.getInstance().implementation
) = addDecryptionKey(OpenPGPKey(key, implementation), protector)
/**
@@ -402,8 +400,10 @@ class ConsumerOptions(
*
* @param certificate certificate
*/
- fun addCertificate(certificate: PGPPublicKeyRing,
- implementation: OpenPGPImplementation = PGPainless.getInstance().implementation
+ @JvmOverloads
+ fun addCertificate(
+ certificate: PGPPublicKeyRing,
+ implementation: OpenPGPImplementation = PGPainless.getInstance().implementation
) {
explicitCertificates.add(OpenPGPCertificate(certificate, implementation))
}
@@ -442,10 +442,6 @@ class ConsumerOptions(
}
companion object {
- @JvmStatic
- @JvmOverloads
- fun get(
- implementation: OpenPGPImplementation = PGPainless.getInstance().implementation
- ) = ConsumerOptions(implementation)
+ @JvmStatic fun get() = ConsumerOptions()
}
}
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/MessageMetadata.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/MessageMetadata.kt
index 44321bb2..79a0ca98 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/MessageMetadata.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/MessageMetadata.kt
@@ -4,9 +4,9 @@
package org.pgpainless.decryption_verification
-import org.bouncycastle.bcpg.KeyIdentifier
import java.util.*
import javax.annotation.Nonnull
+import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.PGPKeyRing
import org.bouncycastle.openpgp.PGPLiteralData
import org.bouncycastle.openpgp.api.OpenPGPCertificate
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/MissingPublicKeyCallback.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/MissingPublicKeyCallback.kt
index eb81847f..9da5eb06 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/MissingPublicKeyCallback.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/MissingPublicKeyCallback.kt
@@ -4,7 +4,8 @@
package org.pgpainless.decryption_verification
-import org.bouncycastle.openpgp.PGPPublicKeyRing
+import org.bouncycastle.bcpg.KeyIdentifier
+import org.bouncycastle.openpgp.api.OpenPGPCertificate
fun interface MissingPublicKeyCallback {
@@ -14,14 +15,14 @@ fun interface MissingPublicKeyCallback {
* here. PGPainless will then continue verification with the next signature.
*
* Note: The key-id might belong to a subkey, so be aware that when looking up the
- * [PGPPublicKeyRing], you may not only search for the key-id on the key rings primary key!
+ * [OpenPGPCertificate], you may not only search for the key-id on the key rings primary key!
*
* It would be super cool to provide the OpenPgp fingerprint here, but unfortunately
* one-pass-signatures only contain the key id.
*
- * @param keyId ID of the missing signing (sub)key
+ * @param keyIdentifier ID of the missing signing (sub)key
* @return keyring containing the key or null
* @see RFC
*/
- fun onMissingPublicKeyEncountered(keyId: Long): PGPPublicKeyRing?
+ fun onMissingPublicKeyEncountered(keyIdentifier: KeyIdentifier): OpenPGPCertificate?
}
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/OpenPgpMessageInputStream.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/OpenPgpMessageInputStream.kt
index b4957a75..d193003f 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/OpenPgpMessageInputStream.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/OpenPgpMessageInputStream.kt
@@ -21,12 +21,8 @@ import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPKeyPair
import org.bouncycastle.openpgp.PGPOnePassSignature
import org.bouncycastle.openpgp.PGPPBEEncryptedData
-import org.bouncycastle.openpgp.PGPPrivateKey
import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData
-import org.bouncycastle.openpgp.PGPPublicKeyRing
-import org.bouncycastle.openpgp.PGPSecretKey
-import org.bouncycastle.openpgp.PGPSecretKeyRing
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.api.OpenPGPCertificate
import org.bouncycastle.openpgp.api.OpenPGPKey
@@ -40,11 +36,9 @@ import org.pgpainless.algorithm.CompressionAlgorithm
import org.pgpainless.algorithm.OpenPgpPacket
import org.pgpainless.algorithm.StreamEncoding
import org.pgpainless.algorithm.SymmetricKeyAlgorithm
-import org.pgpainless.bouncycastle.extensions.getPublicKeyFor
import org.pgpainless.bouncycastle.extensions.getSecretKeyFor
import org.pgpainless.bouncycastle.extensions.getSigningKeyFor
import org.pgpainless.bouncycastle.extensions.issuerKeyId
-import org.pgpainless.bouncycastle.extensions.unlock
import org.pgpainless.decryption_verification.MessageMetadata.CompressedData
import org.pgpainless.decryption_verification.MessageMetadata.EncryptedData
import org.pgpainless.decryption_verification.MessageMetadata.Layer
@@ -61,18 +55,16 @@ import org.pgpainless.exception.MissingDecryptionMethodException
import org.pgpainless.exception.MissingPassphraseException
import org.pgpainless.exception.SignatureValidationException
import org.pgpainless.exception.UnacceptableAlgorithmException
+import org.pgpainless.exception.WrongPassphraseException
import org.pgpainless.implementation.ImplementationFactory
import org.pgpainless.key.SubkeyIdentifier
-import org.pgpainless.key.util.KeyRingUtils
import org.pgpainless.policy.Policy
import org.pgpainless.signature.consumer.CertificateValidator
import org.pgpainless.signature.consumer.OnePassSignatureCheck
-import org.pgpainless.signature.consumer.SignatureCheck
import org.pgpainless.signature.consumer.SignatureValidator
import org.pgpainless.util.ArmoredInputStreamFactory
import org.pgpainless.util.SessionKey
import org.slf4j.LoggerFactory
-import kotlin.math.sign
class OpenPgpMessageInputStream(
type: Type,
@@ -430,10 +422,11 @@ class OpenPgpMessageInputStream(
val privateKey = secretKey.unlock(protector)
if (decryptWithPrivateKey(
- esks,
- privateKey,
- SubkeyIdentifier(secretKey.openPGPKey.pgpSecretKeyRing, secretKey.keyIdentifier),
- pkesk)) {
+ esks,
+ privateKey,
+ SubkeyIdentifier(
+ secretKey.openPGPKey.pgpSecretKeyRing, secretKey.keyIdentifier),
+ pkesk)) {
return true
}
}
@@ -441,27 +434,24 @@ class OpenPgpMessageInputStream(
// try anonymous secret keys
for (pkesk in esks.anonPkesks) {
- for (decryptionKeys in findPotentialDecryptionKeys(pkesk)) {
- if (hasUnsupportedS2KSpecifier(decryptionKeys)) {
+ for (decryptionKey in findPotentialDecryptionKeys(pkesk)) {
+ if (hasUnsupportedS2KSpecifier(decryptionKey)) {
continue
}
- LOGGER.debug("Attempt decryption of anonymous PKESK with key $decryptionKeys.")
- val protector = options.getSecretKeyProtector(decryptionKeys.openPGPKey) ?: continue
+ LOGGER.debug("Attempt decryption of anonymous PKESK with key $decryptionKey.")
+ val protector = options.getSecretKeyProtector(decryptionKey.openPGPKey) ?: continue
- if (!protector.hasPassphraseFor(decryptionKeys.keyIdentifier)) {
+ if (!protector.hasPassphraseFor(decryptionKey.keyIdentifier)) {
LOGGER.debug(
- "Missing passphrase for key ${decryptionKeys.keyIdentifier}. Postponing decryption until all other keys were tried.")
- postponedDueToMissingPassphrase.add(decryptionKeys to pkesk)
+ "Missing passphrase for key ${decryptionKey.keyIdentifier}. Postponing decryption until all other keys were tried.")
+ postponedDueToMissingPassphrase.add(decryptionKey to pkesk)
continue
}
- val privateKey = decryptionKeys.unlock(protector)
+ val privateKey = decryptionKey.unlock(protector)
if (decryptWithPrivateKey(
- esks,
- privateKey,
- SubkeyIdentifier(decryptionKeys.openPGPKey.pgpSecretKeyRing, privateKey.keyIdentifier),
- pkesk)) {
+ esks, privateKey, SubkeyIdentifier(decryptionKey), pkesk)) {
return true
}
}
@@ -471,7 +461,7 @@ class OpenPgpMessageInputStream(
MissingKeyPassphraseStrategy.THROW_EXCEPTION) {
// Non-interactive mode: Throw an exception with all locked decryption keys
postponedDueToMissingPassphrase
- .map { SubkeyIdentifier(getDecryptionKey(it.first.keyID)!!, it.first.keyID) }
+ .map { SubkeyIdentifier(it.first) }
.also { if (it.isNotEmpty()) throw MissingPassphraseException(it.toSet()) }
} else if (options.getMissingKeyPassphraseStrategy() ==
MissingKeyPassphraseStrategy.INTERACTIVE) {
@@ -486,7 +476,12 @@ class OpenPgpMessageInputStream(
LOGGER.debug(
"Attempt decryption with key $decryptionKeyId while interactively requesting its passphrase.")
val protector = options.getSecretKeyProtector(decryptionKeys) ?: continue
- val privateKey = secretKey.unlock(protector)
+ val privateKey =
+ try {
+ secretKey.unlock(protector)
+ } catch (e: PGPException) {
+ throw WrongPassphraseException(secretKey.keyIdentifier, e)
+ }
if (decryptWithPrivateKey(esks, privateKey, decryptionKeyId, pkesk)) {
return true
}
@@ -507,13 +502,12 @@ class OpenPgpMessageInputStream(
pkesk: PGPPublicKeyEncryptedData
): Boolean {
val decryptorFactory =
- ImplementationFactory.getInstance().getPublicKeyDataDecryptorFactory(privateKey.privateKey)
+ ImplementationFactory.getInstance()
+ .getPublicKeyDataDecryptorFactory(privateKey.privateKey)
return decryptPKESKAndStream(esks, decryptionKeyId, decryptorFactory, pkesk)
}
- private fun hasUnsupportedS2KSpecifier(
- secretKey: OpenPGPSecretKey
- ): Boolean {
+ private fun hasUnsupportedS2KSpecifier(secretKey: OpenPGPSecretKey): Boolean {
val s2k = secretKey.pgpSecretKey.s2K
if (s2k != null) {
if (s2k.type in 100..110) {
@@ -686,7 +680,8 @@ class OpenPgpMessageInputStream(
private fun getDecryptionKey(keyId: Long): OpenPGPKey? =
options.getDecryptionKeys().firstOrNull {
- it.pgpSecretKeyRing.any { k -> k.keyID == keyId }
+ it.pgpSecretKeyRing
+ .any { k -> k.keyID == keyId }
.and(
PGPainless.inspectKeyRing(it).decryptionSubkeys.any { k ->
k.keyIdentifier.keyId == keyId
@@ -855,7 +850,9 @@ class OpenPgpMessageInputStream(
val verification =
SignatureVerification(
signature,
- SubkeyIdentifier(check.verificationKeys.pgpPublicKeyRing, check.onePassSignature.keyIdentifier))
+ SubkeyIdentifier(
+ check.verificationKeys.pgpPublicKeyRing,
+ check.onePassSignature.keyIdentifier))
try {
SignatureValidator.signatureWasCreatedInBounds(
@@ -902,13 +899,13 @@ class OpenPgpMessageInputStream(
if (options.getMissingCertificateCallback() != null) {
return options
.getMissingCertificateCallback()!!
- .onMissingPublicKeyEncountered(signature.keyID)
+ .onMissingPublicKeyEncountered(signature.keyIdentifiers.first())
}
return null // TODO: Missing cert for sig
}
private fun findCertificate(signature: PGPOnePassSignature): OpenPGPCertificate? {
- val cert = options.getCertificateSource().getCertificate(signature.keyID)
+ val cert = options.getCertificateSource().getCertificate(signature.keyIdentifier)
if (cert != null) {
return cert
}
@@ -916,7 +913,7 @@ class OpenPgpMessageInputStream(
if (options.getMissingCertificateCallback() != null) {
return options
.getMissingCertificateCallback()!!
- .onMissingPublicKeyEncountered(signature.keyID)
+ .onMissingPublicKeyEncountered(signature.keyIdentifier)
}
return null // TODO: Missing cert for sig
}
@@ -968,15 +965,13 @@ class OpenPgpMessageInputStream(
fun finish(layer: Layer, policy: Policy) {
for (detached in detachedSignatures) {
val verification =
- SignatureVerification(detached.signature, detached.signingKeyIdentifier)
+ SignatureVerification(detached.signature, SubkeyIdentifier(detached.issuer))
try {
SignatureValidator.signatureWasCreatedInBounds(
options.getVerifyNotBefore(), options.getVerifyNotAfter())
.verify(detached.signature)
CertificateValidator.validateCertificateAndVerifyInitializedSignature(
- detached.signature,
- KeyRingUtils.publicKeys(detached.signingKeyRing),
- policy)
+ detached.signature, detached.issuerCertificate.pgpPublicKeyRing, policy)
LOGGER.debug("Acceptable signature by key ${verification.signingKey}")
layer.addVerifiedDetachedSignature(verification)
} catch (e: SignatureValidationException) {
@@ -988,15 +983,13 @@ class OpenPgpMessageInputStream(
for (prepended in prependedSignatures) {
val verification =
- SignatureVerification(prepended.signature, prepended.keyIdentifier)
+ SignatureVerification(prepended.signature, SubkeyIdentifier(prepended.issuer))
try {
SignatureValidator.signatureWasCreatedInBounds(
options.getVerifyNotBefore(), options.getVerifyNotAfter())
.verify(prepended.signature)
CertificateValidator.validateCertificateAndVerifyInitializedSignature(
- prepended.signature,
- KeyRingUtils.publicKeys(prepended.signingKeyRing),
- policy)
+ prepended.signature, prepended.issuerCertificate.pgpPublicKeyRing, policy)
LOGGER.debug("Acceptable signature by key ${verification.signingKey}")
layer.addVerifiedPrependedSignature(verification)
} catch (e: SignatureValidationException) {
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/OpenPgpFingerprint.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/OpenPgpFingerprint.kt
index 9a2f1f7b..679df490 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/OpenPgpFingerprint.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/OpenPgpFingerprint.kt
@@ -5,6 +5,7 @@
package org.pgpainless.key
import java.nio.charset.Charset
+import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.PGPKeyRing
import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPSecretKey
@@ -55,6 +56,8 @@ abstract class OpenPgpFingerprint : CharSequence, Comparable
constructor(keys: PGPKeyRing) : this(keys.publicKey)
+ abstract val keyIdentifier: KeyIdentifier
+
/**
* Check, whether the fingerprint consists of 40 valid hexadecimal characters.
*
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/OpenPgpV4Fingerprint.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/OpenPgpV4Fingerprint.kt
index e02f0ae7..4d05c4f9 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/OpenPgpV4Fingerprint.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/OpenPgpV4Fingerprint.kt
@@ -8,6 +8,7 @@ import java.net.URI
import java.nio.Buffer
import java.nio.ByteBuffer
import java.nio.charset.Charset
+import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.PGPKeyRing
import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPSecretKey
@@ -39,6 +40,8 @@ class OpenPgpV4Fingerprint : OpenPgpFingerprint {
return buf.getLong()
}
+ override val keyIdentifier: KeyIdentifier = KeyIdentifier(bytes)
+
override fun isValid(fingerprint: String): Boolean {
return fingerprint.matches("^[0-9A-F]{40}$".toRegex())
}
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/OpenPgpV5Fingerprint.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/OpenPgpV5Fingerprint.kt
index 7bc36cc9..df62ddef 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/OpenPgpV5Fingerprint.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/OpenPgpV5Fingerprint.kt
@@ -4,6 +4,7 @@
package org.pgpainless.key
+import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.PGPKeyRing
import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPSecretKey
@@ -24,4 +25,6 @@ class OpenPgpV5Fingerprint : _64DigitFingerprint {
override fun getVersion(): Int {
return 5
}
+
+ override val keyIdentifier: KeyIdentifier = KeyIdentifier(bytes)
}
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/SubkeyIdentifier.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/SubkeyIdentifier.kt
index 56307873..0ee58cc6 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/SubkeyIdentifier.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/SubkeyIdentifier.kt
@@ -7,6 +7,7 @@ package org.pgpainless.key
import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.PGPKeyRing
import org.bouncycastle.openpgp.PGPPublicKey
+import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey
/**
* Tuple class used to identify a subkey by fingerprints of the primary key of the subkeys key ring,
@@ -25,6 +26,12 @@ class SubkeyIdentifier(
constructor(keys: PGPKeyRing, keyId: Long) : this(keys, KeyIdentifier(keyId))
+ constructor(
+ key: OpenPGPComponentKey
+ ) : this(
+ OpenPgpFingerprint.of(key.certificate.pgpPublicKeyRing),
+ OpenPgpFingerprint.of(key.pgpPublicKey))
+
constructor(
keys: PGPKeyRing,
subkeyFingerprint: OpenPgpFingerprint
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/_64DigitFingerprint.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/_64DigitFingerprint.kt
index a34dd880..f5447d61 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/_64DigitFingerprint.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/_64DigitFingerprint.kt
@@ -7,6 +7,7 @@ package org.pgpainless.key
import java.nio.Buffer
import java.nio.ByteBuffer
import java.nio.charset.Charset
+import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.PGPKeyRing
import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPSecretKey
@@ -51,6 +52,8 @@ open class _64DigitFingerprint : OpenPgpFingerprint {
return -1 // might be v5 or v6
}
+ override val keyIdentifier: KeyIdentifier = KeyIdentifier(bytes)
+
override fun isValid(fingerprint: String): Boolean {
return fingerprint.matches(("^[0-9A-F]{64}$".toRegex()))
}
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.kt
index e5426f37..7202cff7 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditor.kt
@@ -9,6 +9,7 @@ import java.util.function.Predicate
import javax.annotation.Nonnull
import kotlin.NoSuchElementException
import openpgp.openPgpKeyId
+import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.bcpg.sig.KeyExpirationTime
import org.bouncycastle.openpgp.*
import org.pgpainless.PGPainless
@@ -248,7 +249,7 @@ class SecretKeyRingEditor(
val version = OpenPGPKeyVersion.from(secretKeyRing.getPublicKey().version)
val keyPair = KeyRingBuilder.generateKeyPair(keySpec, OpenPGPKeyVersion.v4, referenceTime)
val subkeyProtector =
- PasswordBasedSecretKeyRingProtector.forKeyId(keyPair.keyID, subkeyPassphrase)
+ PasswordBasedSecretKeyRingProtector.forKeyId(keyPair.keyIdentifier, subkeyPassphrase)
val keyFlags = KeyFlag.fromBitmask(keySpec.subpackets.keyFlags).toMutableList()
return addSubKey(
keyPair,
@@ -555,15 +556,15 @@ class SecretKeyRingEditor(
}
override fun changeSubKeyPassphraseFromOldPassphrase(
- keyId: Long,
+ keyIdentifier: KeyIdentifier,
oldPassphrase: Passphrase,
oldProtectionSettings: KeyRingProtectionSettings
): SecretKeyRingEditorInterface.WithKeyRingEncryptionSettings {
return WithKeyRingEncryptionSettingsImpl(
this,
- keyId,
+ keyIdentifier,
CachingSecretKeyRingProtector(
- mapOf(keyId to oldPassphrase), oldProtectionSettings, null))
+ mapOf(keyIdentifier to oldPassphrase), oldProtectionSettings, null))
}
override fun done(): PGPSecretKeyRing {
@@ -746,7 +747,7 @@ class SecretKeyRingEditor(
private class WithKeyRingEncryptionSettingsImpl(
private val editor: SecretKeyRingEditor,
- private val keyId: Long?,
+ private val keyId: KeyIdentifier?,
private val oldProtector: SecretKeyRingProtector
) : SecretKeyRingEditorInterface.WithKeyRingEncryptionSettings {
@@ -763,7 +764,7 @@ class SecretKeyRingEditor(
private class WithPassphraseImpl(
private val editor: SecretKeyRingEditor,
- private val keyId: Long?,
+ private val keyId: KeyIdentifier?,
private val oldProtector: SecretKeyRingProtector,
private val newProtectionSettings: KeyRingProtectionSettings
) : SecretKeyRingEditorInterface.WithPassphrase {
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditorInterface.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditorInterface.kt
index 140ff905..ad8e36ff 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditorInterface.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/modification/secretkeyring/SecretKeyRingEditorInterface.kt
@@ -8,6 +8,7 @@ import java.io.IOException
import java.security.InvalidAlgorithmParameterException
import java.security.NoSuchAlgorithmException
import java.util.*
+import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.*
import org.pgpainless.algorithm.KeyFlag
import org.pgpainless.key.OpenPgpFingerprint
@@ -592,19 +593,9 @@ interface SecretKeyRingEditorInterface {
KeyRingProtectionSettings.secureDefaultSettings()
): WithKeyRingEncryptionSettings
- /**
- * Change the passphrase of a single subkey in the key ring.
- *
- * Note: While it is a valid use-case to have different passphrases per subKey, this is one of
- * the reasons why OpenPGP sucks in practice.
- *
- * @param keyId id of the subkey
- * @param oldPassphrase old passphrase (empty if the key was unprotected)
- * @return next builder step
- */
+ @Deprecated("Pass KeyIdentifier instead.")
fun changeSubKeyPassphraseFromOldPassphrase(keyId: Long, oldPassphrase: Passphrase) =
- changeSubKeyPassphraseFromOldPassphrase(
- keyId, oldPassphrase, KeyRingProtectionSettings.secureDefaultSettings())
+ changeSubKeyPassphraseFromOldPassphrase(KeyIdentifier(keyId), oldPassphrase)
/**
* Change the passphrase of a single subkey in the key ring.
@@ -612,13 +603,30 @@ interface SecretKeyRingEditorInterface {
* Note: While it is a valid use-case to have different passphrases per subKey, this is one of
* the reasons why OpenPGP sucks in practice.
*
- * @param keyId id of the subkey
+ * @param keyIdentifier id of the subkey
+ * @param oldPassphrase old passphrase (empty if the key was unprotected)
+ * @return next builder step
+ */
+ fun changeSubKeyPassphraseFromOldPassphrase(
+ keyIdentifier: KeyIdentifier,
+ oldPassphrase: Passphrase
+ ) =
+ changeSubKeyPassphraseFromOldPassphrase(
+ keyIdentifier, oldPassphrase, KeyRingProtectionSettings.secureDefaultSettings())
+
+ /**
+ * Change the passphrase of a single subkey in the key ring.
+ *
+ * Note: While it is a valid use-case to have different passphrases per subKey, this is one of
+ * the reasons why OpenPGP sucks in practice.
+ *
+ * @param keyIdentifier id of the subkey
* @param oldPassphrase old passphrase (empty if the key was unprotected)
* @param oldProtectionSettings custom settings for the old passphrase
* @return next builder step
*/
fun changeSubKeyPassphraseFromOldPassphrase(
- keyId: Long,
+ keyIdentifier: KeyIdentifier,
oldPassphrase: Passphrase,
oldProtectionSettings: KeyRingProtectionSettings
): WithKeyRingEncryptionSettings
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/BaseSecretKeyRingProtector.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/BaseSecretKeyRingProtector.kt
index c5db2086..35a6ebee 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/BaseSecretKeyRingProtector.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/BaseSecretKeyRingProtector.kt
@@ -4,6 +4,8 @@
package org.pgpainless.key.protection
+import org.bouncycastle.bcpg.KeyIdentifier
+import org.bouncycastle.openpgp.api.OpenPGPKey
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor
import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor
import org.pgpainless.implementation.ImplementationFactory
@@ -22,16 +24,21 @@ open class BaseSecretKeyRingProtector(
passphraseProvider: SecretKeyPassphraseProvider
) : this(passphraseProvider, KeyRingProtectionSettings.secureDefaultSettings())
- override fun hasPassphraseFor(keyId: Long): Boolean = passphraseProvider.hasPassphrase(keyId)
+ override fun hasPassphraseFor(keyIdentifier: KeyIdentifier): Boolean {
+ return passphraseProvider.hasPassphrase(keyIdentifier)
+ }
override fun getDecryptor(keyId: Long): PBESecretKeyDecryptor? =
- passphraseProvider.getPassphraseFor(keyId)?.let {
+ getDecryptor(KeyIdentifier(keyId))
+
+ override fun getDecryptor(keyIdentifier: KeyIdentifier): PBESecretKeyDecryptor? =
+ passphraseProvider.getPassphraseFor(keyIdentifier)?.let {
if (it.isEmpty) null
else ImplementationFactory.getInstance().getPBESecretKeyDecryptor(it)
}
- override fun getEncryptor(keyId: Long): PBESecretKeyEncryptor? =
- passphraseProvider.getPassphraseFor(keyId)?.let {
+ override fun getEncryptor(keyIdentifier: KeyIdentifier): PBESecretKeyEncryptor? {
+ return passphraseProvider.getPassphraseFor(keyIdentifier)?.let {
if (it.isEmpty) null
else
ImplementationFactory.getInstance()
@@ -41,4 +48,9 @@ open class BaseSecretKeyRingProtector(
protectionSettings.s2kCount,
it)
}
+ }
+
+ override fun getKeyPassword(p0: OpenPGPKey.OpenPGPSecretKey): CharArray? {
+ return passphraseProvider.getPassphraseFor(p0.keyIdentifier)?.getChars()
+ }
}
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/CachingSecretKeyRingProtector.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/CachingSecretKeyRingProtector.kt
index 20704685..75ba146c 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/CachingSecretKeyRingProtector.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/CachingSecretKeyRingProtector.kt
@@ -4,9 +4,12 @@
package org.pgpainless.key.protection
-import openpgp.openPgpKeyId
+import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.PGPKeyRing
import org.bouncycastle.openpgp.PGPPublicKey
+import org.bouncycastle.openpgp.api.OpenPGPKey
+import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor
+import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor
import org.pgpainless.key.OpenPgpFingerprint
import org.pgpainless.key.protection.passphrase_provider.SecretKeyPassphraseProvider
import org.pgpainless.util.Passphrase
@@ -21,7 +24,7 @@ import org.pgpainless.util.Passphrase
*/
class CachingSecretKeyRingProtector : SecretKeyRingProtector, SecretKeyPassphraseProvider {
- private val cache: MutableMap
+ private val cache: MutableMap
private val protector: SecretKeyRingProtector
private val provider: SecretKeyPassphraseProvider?
@@ -30,12 +33,12 @@ class CachingSecretKeyRingProtector : SecretKeyRingProtector, SecretKeyPassphras
constructor(
missingPassphraseCallback: SecretKeyPassphraseProvider?
) : this(
- mapOf(),
+ mapOf(),
KeyRingProtectionSettings.secureDefaultSettings(),
missingPassphraseCallback)
constructor(
- passphrases: Map,
+ passphrases: Map,
protectionSettings: KeyRingProtectionSettings,
missingPassphraseCallback: SecretKeyPassphraseProvider?
) {
@@ -44,6 +47,10 @@ class CachingSecretKeyRingProtector : SecretKeyRingProtector, SecretKeyPassphras
this.provider = missingPassphraseCallback
}
+ @Deprecated("Pass KeyIdentifier instead.")
+ fun addPassphrase(keyId: Long, passphrase: Passphrase) =
+ addPassphrase(KeyIdentifier(keyId), passphrase)
+
/**
* Add a passphrase to the cache. If the cache already contains a passphrase for the given
* key-id, a [IllegalArgumentException] is thrown. The reason for this is to prevent accidental
@@ -53,24 +60,30 @@ class CachingSecretKeyRingProtector : SecretKeyRingProtector, SecretKeyPassphras
* If you can ensure that there will be no key-id clash, and you want to replace the passphrase,
* you can use [replacePassphrase] to replace the passphrase.
*
- * @param keyId id of the key
+ * @param keyIdentifier id of the key
* @param passphrase passphrase
*/
- fun addPassphrase(keyId: Long, passphrase: Passphrase) = apply {
- require(!cache.containsKey(keyId)) {
- "The cache already holds a passphrase for ID ${keyId.openPgpKeyId()}.\n" +
+ fun addPassphrase(keyIdentifier: KeyIdentifier, passphrase: Passphrase) = apply {
+ require(!cache.containsKey(keyIdentifier)) {
+ "The cache already holds a passphrase for ID ${keyIdentifier}.\n" +
"If you want to replace this passphrase, use replacePassphrase(Long, Passphrase) instead."
}
- cache[keyId] = passphrase
+ cache[keyIdentifier] = passphrase
}
+ @Deprecated("Pass KeyIdentifier instead.")
+ fun replacePassphrase(keyId: Long, passphrase: Passphrase) =
+ replacePassphrase(KeyIdentifier(keyId), passphrase)
+
/**
* Replace the passphrase for the given key-id in the cache.
*
* @param keyId keyId
* @param passphrase passphrase
*/
- fun replacePassphrase(keyId: Long, passphrase: Passphrase) = apply { cache[keyId] = passphrase }
+ fun replacePassphrase(keyId: KeyIdentifier, passphrase: Passphrase) = apply {
+ cache[keyId] = passphrase
+ }
/**
* Remember the given passphrase for all keys in the given key ring. If for the key-id of any
@@ -91,14 +104,14 @@ class CachingSecretKeyRingProtector : SecretKeyRingProtector, SecretKeyPassphras
fun addPassphrase(keyRing: PGPKeyRing, passphrase: Passphrase) = apply {
// check for existing passphrases before doing anything
keyRing.publicKeys.forEach {
- require(!cache.containsKey(it.keyID)) {
- "The cache already holds a passphrase for the key with ID ${it.keyID.openPgpKeyId()}.\n" +
+ require(!cache.containsKey(it.keyIdentifier)) {
+ "The cache already holds a passphrase for the key with ID ${it.keyIdentifier}.\n" +
"If you want to replace the passphrase, use replacePassphrase(PGPKeyRing, Passphrase) instead."
}
}
// only then instert
- keyRing.publicKeys.forEach { cache[it.keyID] = passphrase }
+ keyRing.publicKeys.forEach { cache[it.keyIdentifier] = passphrase }
}
/**
@@ -108,7 +121,7 @@ class CachingSecretKeyRingProtector : SecretKeyRingProtector, SecretKeyPassphras
* @param passphrase passphrase
*/
fun replacePassphrase(keyRing: PGPKeyRing, passphrase: Passphrase) = apply {
- keyRing.publicKeys.forEach { cache[it.keyID] = passphrase }
+ keyRing.publicKeys.forEach { cache[it.keyIdentifier] = passphrase }
}
/**
@@ -118,7 +131,7 @@ class CachingSecretKeyRingProtector : SecretKeyRingProtector, SecretKeyPassphras
* @param passphrase passphrase
*/
fun addPassphrase(key: PGPPublicKey, passphrase: Passphrase) =
- addPassphrase(key.keyID, passphrase)
+ addPassphrase(key.keyIdentifier, passphrase)
/**
* Remember the given passphrase for the key with the given fingerprint.
@@ -127,14 +140,17 @@ class CachingSecretKeyRingProtector : SecretKeyRingProtector, SecretKeyPassphras
* @param passphrase passphrase
*/
fun addPassphrase(fingerprint: OpenPgpFingerprint, passphrase: Passphrase) =
- addPassphrase(fingerprint.keyId, passphrase)
+ addPassphrase(fingerprint.keyIdentifier, passphrase)
+
+ @Deprecated("Pass KeyIdentifier instead.")
+ fun forgetPassphrase(keyId: Long) = forgetPassphrase(KeyIdentifier(keyId))
/**
* Remove a passphrase from the cache. The passphrase will be cleared and then removed.
*
* @param keyId id of the key
*/
- fun forgetPassphrase(keyId: Long) = apply { cache.remove(keyId)?.clear() }
+ fun forgetPassphrase(keyId: KeyIdentifier) = apply { cache.remove(keyId)?.clear() }
/**
* Forget the passphrase to all keys in the provided key ring.
@@ -150,18 +166,27 @@ class CachingSecretKeyRingProtector : SecretKeyRingProtector, SecretKeyPassphras
*
* @param key key
*/
- fun forgetPassphrase(key: PGPPublicKey) = apply { forgetPassphrase(key.keyID) }
+ fun forgetPassphrase(key: PGPPublicKey) = apply { forgetPassphrase(key.keyIdentifier) }
- override fun getPassphraseFor(keyId: Long?): Passphrase? {
- return if (hasPassphrase(keyId)) cache[keyId]
- else provider?.getPassphraseFor(keyId)?.also { cache[keyId] = it }
+ override fun getPassphraseFor(keyIdentifier: KeyIdentifier): Passphrase? {
+ return if (hasPassphrase(keyIdentifier)) cache[keyIdentifier]
+ else provider?.getPassphraseFor(keyIdentifier)?.also { cache[keyIdentifier] = it }
}
- override fun hasPassphrase(keyId: Long?) = cache[keyId]?.isValid ?: false
+ override fun hasPassphraseFor(keyIdentifier: KeyIdentifier): Boolean {
+ return hasPassphrase(keyIdentifier)
+ }
- override fun hasPassphraseFor(keyId: Long) = hasPassphrase(keyId)
+ override fun hasPassphrase(keyIdentifier: KeyIdentifier): Boolean {
+ return cache[keyIdentifier]?.isValid ?: false
+ }
- override fun getDecryptor(keyId: Long) = protector.getDecryptor(keyId)
+ override fun getDecryptor(keyIdentifier: KeyIdentifier): PBESecretKeyDecryptor? =
+ protector.getDecryptor(keyIdentifier)
- override fun getEncryptor(keyId: Long) = protector.getEncryptor(keyId)
+ override fun getEncryptor(keyIdentifier: KeyIdentifier): PBESecretKeyEncryptor? =
+ protector.getEncryptor(keyIdentifier)
+
+ override fun getKeyPassword(p0: OpenPGPKey.OpenPGPSecretKey): CharArray? =
+ getPassphraseFor(p0.keyIdentifier)?.getChars()
}
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/PasswordBasedSecretKeyRingProtector.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/PasswordBasedSecretKeyRingProtector.kt
index 9eb47e88..a4f9d2bb 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/PasswordBasedSecretKeyRingProtector.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/PasswordBasedSecretKeyRingProtector.kt
@@ -4,6 +4,7 @@
package org.pgpainless.key.protection
+import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.PGPKeyRing
import org.bouncycastle.openpgp.PGPSecretKey
import org.pgpainless.key.protection.passphrase_provider.SecretKeyPassphraseProvider
@@ -38,12 +39,12 @@ class PasswordBasedSecretKeyRingProtector : BaseSecretKeyRingProtector {
): PasswordBasedSecretKeyRingProtector {
return object : SecretKeyPassphraseProvider {
- override fun getPassphraseFor(keyId: Long?): Passphrase? {
- return if (hasPassphrase(keyId)) passphrase else null
+ override fun getPassphraseFor(keyIdentifier: KeyIdentifier): Passphrase? {
+ return if (hasPassphrase(keyIdentifier)) passphrase else null
}
- override fun hasPassphrase(keyId: Long?): Boolean {
- return keyId != null && keyRing.getPublicKey(keyId) != null
+ override fun hasPassphrase(keyIdentifier: KeyIdentifier): Boolean {
+ return keyRing.getPublicKey(keyIdentifier) != null
}
}
.let { PasswordBasedSecretKeyRingProtector(it) }
@@ -51,20 +52,20 @@ class PasswordBasedSecretKeyRingProtector : BaseSecretKeyRingProtector {
@JvmStatic
fun forKey(key: PGPSecretKey, passphrase: Passphrase): PasswordBasedSecretKeyRingProtector =
- forKeyId(key.publicKey.keyID, passphrase)
+ forKeyId(key.publicKey.keyIdentifier, passphrase)
@JvmStatic
fun forKeyId(
- singleKeyId: Long,
+ singleKeyIdentifier: KeyIdentifier,
passphrase: Passphrase
): PasswordBasedSecretKeyRingProtector {
return object : SecretKeyPassphraseProvider {
- override fun getPassphraseFor(keyId: Long?): Passphrase? {
- return if (hasPassphrase(keyId)) passphrase else null
+ override fun getPassphraseFor(keyIdentifier: KeyIdentifier): Passphrase? {
+ return if (hasPassphrase(keyIdentifier)) passphrase else null
}
- override fun hasPassphrase(keyId: Long?): Boolean {
- return keyId == singleKeyId
+ override fun hasPassphrase(keyIdentifier: KeyIdentifier): Boolean {
+ return keyIdentifier.matches(singleKeyIdentifier)
}
}
.let { PasswordBasedSecretKeyRingProtector(it) }
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/SecretKeyRingProtector.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/SecretKeyRingProtector.kt
index 373c964c..ccab4c27 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/SecretKeyRingProtector.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/SecretKeyRingProtector.kt
@@ -4,6 +4,7 @@
package org.pgpainless.key.protection
+import kotlin.Throws
import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPSecretKey
@@ -14,7 +15,6 @@ import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor
import org.pgpainless.key.protection.passphrase_provider.SecretKeyPassphraseProvider
import org.pgpainless.key.protection.passphrase_provider.SolitaryPassphraseProvider
import org.pgpainless.util.Passphrase
-import kotlin.Throws
/**
* Task of the [SecretKeyRingProtector] is to map encryptor/decryptor objects to key-ids.
@@ -43,10 +43,11 @@ interface SecretKeyRingProtector : KeyPassphraseProvider {
* @param keyId id of the key
* @return decryptor for the key
*/
- @Throws(PGPException::class) fun getDecryptor(keyId: Long): PBESecretKeyDecryptor? =
- getDecryptor(KeyIdentifier(keyId))
+ @Throws(PGPException::class)
+ fun getDecryptor(keyId: Long): PBESecretKeyDecryptor? = getDecryptor(KeyIdentifier(keyId))
- @Throws(PGPException::class) fun getDecryptor(keyIdentifier: KeyIdentifier): PBESecretKeyDecryptor?
+ @Throws(PGPException::class)
+ fun getDecryptor(keyIdentifier: KeyIdentifier): PBESecretKeyDecryptor?
/**
* Return an encryptor for the key of id `keyId`. This method returns null if the key is
@@ -55,10 +56,11 @@ interface SecretKeyRingProtector : KeyPassphraseProvider {
* @param keyId id of the key
* @return encryptor for the key
*/
- @Throws(PGPException::class) fun getEncryptor(keyId: Long): PBESecretKeyEncryptor? =
- getEncryptor(KeyIdentifier(keyId))
+ @Throws(PGPException::class)
+ fun getEncryptor(keyId: Long): PBESecretKeyEncryptor? = getEncryptor(KeyIdentifier(keyId))
- @Throws(PGPException::class) fun getEncryptor(keyIdentifier: KeyIdentifier): PBESecretKeyEncryptor?
+ @Throws(PGPException::class)
+ fun getEncryptor(keyIdentifier: KeyIdentifier): PBESecretKeyEncryptor?
companion object {
@@ -97,7 +99,7 @@ interface SecretKeyRingProtector : KeyPassphraseProvider {
passphrase: Passphrase,
keys: PGPSecretKeyRing
): SecretKeyRingProtector =
- fromPassphraseMap(keys.map { it.keyID }.associateWith { passphrase })
+ fromPassphraseMap(keys.map { it.keyIdentifier }.associateWith { passphrase })
/**
* Use the provided passphrase to unlock any key.
@@ -132,12 +134,15 @@ interface SecretKeyRingProtector : KeyPassphraseProvider {
* Otherwise, this protector will always return null.
*
* @param passphrase passphrase
- * @param keyId id of the key to lock/unlock
+ * @param keyIdentifier id of the key to lock/unlock
* @return protector
*/
@JvmStatic
- fun unlockSingleKeyWith(passphrase: Passphrase, keyId: Long): SecretKeyRingProtector =
- PasswordBasedSecretKeyRingProtector.forKeyId(keyId, passphrase)
+ fun unlockSingleKeyWith(
+ passphrase: Passphrase,
+ keyIdentifier: KeyIdentifier
+ ): SecretKeyRingProtector =
+ PasswordBasedSecretKeyRingProtector.forKeyId(keyIdentifier, passphrase)
/**
* Protector for unprotected keys. This protector returns null for all
@@ -159,7 +164,9 @@ interface SecretKeyRingProtector : KeyPassphraseProvider {
* @return protector
*/
@JvmStatic
- fun fromPassphraseMap(passphraseMap: Map): SecretKeyRingProtector =
+ fun fromPassphraseMap(
+ passphraseMap: Map
+ ): SecretKeyRingProtector =
CachingSecretKeyRingProtector(
passphraseMap, KeyRingProtectionSettings.secureDefaultSettings(), null)
}
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/MapBasedPassphraseProvider.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/MapBasedPassphraseProvider.kt
index 3457cff7..2ba0e448 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/MapBasedPassphraseProvider.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/MapBasedPassphraseProvider.kt
@@ -4,6 +4,7 @@
package org.pgpainless.key.protection.passphrase_provider
+import org.bouncycastle.bcpg.KeyIdentifier
import org.pgpainless.util.Passphrase
/**
@@ -14,9 +15,11 @@ import org.pgpainless.util.Passphrase
*
* TODO: Make this null-safe and throw an exception instead?
*/
-class MapBasedPassphraseProvider(val map: Map) : SecretKeyPassphraseProvider {
+class MapBasedPassphraseProvider(val map: Map) :
+ SecretKeyPassphraseProvider {
- override fun getPassphraseFor(keyId: Long?): Passphrase? = map[keyId]
+ override fun getPassphraseFor(keyIdentifier: KeyIdentifier): Passphrase? = map[keyIdentifier]
- override fun hasPassphrase(keyId: Long?): Boolean = map.containsKey(keyId)
+ override fun hasPassphrase(keyIdentifier: KeyIdentifier): Boolean =
+ map.containsKey(keyIdentifier)
}
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SecretKeyPassphraseProvider.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SecretKeyPassphraseProvider.kt
index a80b8bb0..268538f2 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SecretKeyPassphraseProvider.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SecretKeyPassphraseProvider.kt
@@ -4,6 +4,7 @@
package org.pgpainless.key.protection.passphrase_provider
+import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.PGPSecretKey
import org.pgpainless.util.Passphrase
@@ -19,7 +20,7 @@ interface SecretKeyPassphraseProvider {
* @return passphrase or null, if no passphrase record is found.
*/
fun getPassphraseFor(secretKey: PGPSecretKey): Passphrase? {
- return getPassphraseFor(secretKey.keyID)
+ return getPassphraseFor(secretKey.keyIdentifier)
}
/**
@@ -30,7 +31,11 @@ interface SecretKeyPassphraseProvider {
* @param keyId if of the secret key
* @return passphrase or null, if no passphrase record has been found.
*/
- fun getPassphraseFor(keyId: Long?): Passphrase?
+ fun getPassphraseFor(keyId: Long): Passphrase? = getPassphraseFor(KeyIdentifier(keyId))
- fun hasPassphrase(keyId: Long?): Boolean
+ fun getPassphraseFor(keyIdentifier: KeyIdentifier): Passphrase?
+
+ fun hasPassphrase(keyId: Long): Boolean = hasPassphrase(KeyIdentifier(keyId))
+
+ fun hasPassphrase(keyIdentifier: KeyIdentifier): Boolean
}
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SolitaryPassphraseProvider.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SolitaryPassphraseProvider.kt
index a9f6801d..b846df2d 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SolitaryPassphraseProvider.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/protection/passphrase_provider/SolitaryPassphraseProvider.kt
@@ -4,12 +4,13 @@
package org.pgpainless.key.protection.passphrase_provider
+import org.bouncycastle.bcpg.KeyIdentifier
import org.pgpainless.util.Passphrase
/** Implementation of the [SecretKeyPassphraseProvider] that holds a single [Passphrase]. */
class SolitaryPassphraseProvider(val passphrase: Passphrase?) : SecretKeyPassphraseProvider {
- override fun getPassphraseFor(keyId: Long?): Passphrase? = passphrase
+ override fun getPassphraseFor(keyIdentifier: KeyIdentifier): Passphrase? = passphrase
- override fun hasPassphrase(keyId: Long?): Boolean = true
+ override fun hasPassphrase(keyIdentifier: KeyIdentifier): Boolean = true
}
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/key/util/KeyRingUtils.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/key/util/KeyRingUtils.kt
index f83b5486..02624fd1 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/key/util/KeyRingUtils.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/key/util/KeyRingUtils.kt
@@ -7,6 +7,7 @@ package org.pgpainless.key.util
import java.io.ByteArrayOutputStream
import kotlin.jvm.Throws
import openpgp.openPgpKeyId
+import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.bcpg.S2K
import org.bouncycastle.bcpg.SecretKeyPacket
import org.bouncycastle.openpgp.*
@@ -468,7 +469,7 @@ class KeyRingUtils {
@JvmStatic
@Throws(MissingPassphraseException::class, PGPException::class)
fun changePassphrase(
- keyId: Long?,
+ keyId: KeyIdentifier?,
secretKeys: PGPSecretKeyRing,
oldProtector: SecretKeyRingProtector,
newProtector: SecretKeyRingProtector
@@ -484,7 +485,7 @@ class KeyRingUtils {
secretKeys.secretKeys
.asSequence()
.map {
- if (it.keyID == keyId) {
+ if (it.keyIdentifier.matches(keyId)) {
reencryptPrivateKey(it, oldProtector, newProtector)
} else {
it
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/CertificateValidator.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/CertificateValidator.kt
index 83b7e54e..61bdd282 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/CertificateValidator.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/CertificateValidator.kt
@@ -13,6 +13,7 @@ import org.bouncycastle.openpgp.PGPSignature
import org.pgpainless.PGPainless
import org.pgpainless.algorithm.KeyFlag
import org.pgpainless.algorithm.SignatureType
+import org.pgpainless.bouncycastle.extensions.getPublicKey
import org.pgpainless.bouncycastle.extensions.issuerKeyId
import org.pgpainless.exception.SignatureValidationException
import org.pgpainless.key.util.KeyRingUtils
@@ -303,10 +304,12 @@ class CertificateValidator {
policy: Policy
): Boolean {
return validateCertificate(
- onePassSignature.signature!!, onePassSignature.verificationKeys, policy) &&
+ onePassSignature.signature!!,
+ onePassSignature.verificationKeys.pgpPublicKeyRing,
+ policy) &&
SignatureVerifier.verifyOnePassSignature(
onePassSignature.signature!!,
- onePassSignature.verificationKeys.getPublicKey(
+ onePassSignature.verificationKeys.pgpKeyRing.getPublicKey(
onePassSignature.signature!!.issuerKeyId),
onePassSignature,
policy)
diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/OnePassSignatureCheck.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/OnePassSignatureCheck.kt
index 59d65cdb..7536776e 100644
--- a/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/OnePassSignatureCheck.kt
+++ b/pgpainless-core/src/main/kotlin/org/pgpainless/signature/consumer/OnePassSignatureCheck.kt
@@ -8,8 +8,6 @@ import org.bouncycastle.openpgp.PGPOnePassSignature
import org.bouncycastle.openpgp.PGPPublicKeyRing
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.api.OpenPGPCertificate
-import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPComponentKey
-import org.pgpainless.bouncycastle.extensions.getSigningKeyFor
import org.pgpainless.key.SubkeyIdentifier
/**
diff --git a/pgpainless-core/src/test/java/investigations/InvestigateMultiSEIPMessageHandlingTest.java b/pgpainless-core/src/test/java/investigations/InvestigateMultiSEIPMessageHandlingTest.java
index f37bf690..28488fac 100644
--- a/pgpainless-core/src/test/java/investigations/InvestigateMultiSEIPMessageHandlingTest.java
+++ b/pgpainless-core/src/test/java/investigations/InvestigateMultiSEIPMessageHandlingTest.java
@@ -21,6 +21,7 @@ import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignatureGenerator;
+import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.bouncycastle.openpgp.operator.PGPDataEncryptorBuilder;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.Test;
@@ -176,12 +177,13 @@ public class InvestigateMultiSEIPMessageHandlingTest {
@Test
public void testDecryptAndVerifyDetectsAppendedSEIPData() throws IOException, PGPException {
- PGPSecretKeyRing ring1 = PGPainless.readKeyRing().secretKeyRing(KEY1);
- PGPSecretKeyRing ring2 = PGPainless.readKeyRing().secretKeyRing(KEY2);
+ PGPainless api = PGPainless.getInstance();
+ OpenPGPKey ring1 = api.readKey().parseKey(KEY1);
+ OpenPGPKey ring2 = api.readKey().parseKey(KEY2);
- ConsumerOptions options = new ConsumerOptions()
- .addVerificationCert(PGPainless.extractCertificate(ring1))
- .addVerificationCert(PGPainless.extractCertificate(ring2))
+ ConsumerOptions options = ConsumerOptions.get()
+ .addVerificationCert(ring2)
+ .addVerificationCert(ring2)
.addDecryptionKey(ring1);
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
diff --git a/pgpainless-core/src/test/java/investigations/OnePassSignatureVerificationWithPartialLengthLiteralDataRegressionTest.java b/pgpainless-core/src/test/java/investigations/OnePassSignatureVerificationWithPartialLengthLiteralDataRegressionTest.java
index 7ec53edb..3afcce54 100644
--- a/pgpainless-core/src/test/java/investigations/OnePassSignatureVerificationWithPartialLengthLiteralDataRegressionTest.java
+++ b/pgpainless-core/src/test/java/investigations/OnePassSignatureVerificationWithPartialLengthLiteralDataRegressionTest.java
@@ -124,7 +124,7 @@ public class OnePassSignatureVerificationWithPartialLengthLiteralDataRegressionT
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(in)
- .withOptions(new ConsumerOptions()
+ .withOptions(ConsumerOptions.get()
.addVerificationCert(cert)
.addDecryptionKey(secretKeys));
diff --git a/pgpainless-core/src/test/java/org/bouncycastle/AsciiArmorCRCTests.java b/pgpainless-core/src/test/java/org/bouncycastle/AsciiArmorCRCTests.java
index eb9e7ef5..031c3e73 100644
--- a/pgpainless-core/src/test/java/org/bouncycastle/AsciiArmorCRCTests.java
+++ b/pgpainless-core/src/test/java/org/bouncycastle/AsciiArmorCRCTests.java
@@ -544,7 +544,7 @@ public class AsciiArmorCRCTests {
assertThrows(IOException.class, () -> {
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8)))
- .withOptions(new ConsumerOptions().addDecryptionKey(
+ .withOptions(ConsumerOptions.get().addDecryptionKey(
key, SecretKeyRingProtector.unlockAnyKeyWith(passphrase)
));
diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/DecryptAndVerifyMessageTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/DecryptAndVerifyMessageTest.java
index 82796cb9..22372f2e 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/DecryptAndVerifyMessageTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/DecryptAndVerifyMessageTest.java
@@ -52,7 +52,7 @@ public class DecryptAndVerifyMessageTest {
public void decryptMessageAndVerifySignatureTest() throws Exception {
String encryptedMessage = TestKeys.MSG_SIGN_CRYPT_JULIET_JULIET;
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.addDecryptionKey(juliet)
.addVerificationCert(KeyRingUtils.publicKeyRingFrom(juliet));
@@ -87,7 +87,7 @@ public class DecryptAndVerifyMessageTest {
public void decryptMessageAndReadBeyondEndTest() throws Exception {
final String encryptedMessage = TestKeys.MSG_SIGN_CRYPT_JULIET_JULIET;
- final ConsumerOptions options = new ConsumerOptions()
+ final ConsumerOptions options = ConsumerOptions.get()
.addDecryptionKey(juliet)
.addVerificationCert(KeyRingUtils.publicKeyRingFrom(juliet));
@@ -105,7 +105,7 @@ public class DecryptAndVerifyMessageTest {
public void decryptMessageAndVerifySignatureByteByByteTest() throws Exception {
String encryptedMessage = TestKeys.MSG_SIGN_CRYPT_JULIET_JULIET;
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.addDecryptionKey(juliet)
.addVerificationCert(KeyRingUtils.publicKeyRingFrom(juliet));
diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/DecryptHiddenRecipientMessageTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/DecryptHiddenRecipientMessageTest.java
index fc8cf347..a5f39d0f 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/DecryptHiddenRecipientMessageTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/DecryptHiddenRecipientMessageTest.java
@@ -128,7 +128,7 @@ public class DecryptHiddenRecipientMessageTest {
"=1knQ\n" +
"-----END PGP MESSAGE-----\n";
ByteArrayInputStream messageIn = new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8));
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.addDecryptionKey(secretKeys);
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/IgnoreUnknownSignatureVersionsTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/IgnoreUnknownSignatureVersionsTest.java
index 2b222c83..b5c1bed0 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/IgnoreUnknownSignatureVersionsTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/IgnoreUnknownSignatureVersionsTest.java
@@ -177,7 +177,7 @@ public class IgnoreUnknownSignatureVersionsTest {
private MessageMetadata verifySignature(PGPPublicKeyRing cert, String BASE_CASE) throws PGPException, IOException {
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify().onInputStream(new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8)))
- .withOptions(new ConsumerOptions()
+ .withOptions(ConsumerOptions.get()
.addVerificationCert(cert)
.addVerificationOfDetachedSignatures(new ByteArrayInputStream(BASE_CASE.getBytes(StandardCharsets.UTF_8))));
diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/MissingPassphraseForDecryptionTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/MissingPassphraseForDecryptionTest.java
index 979587ac..6ff534b0 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/MissingPassphraseForDecryptionTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/MissingPassphraseForDecryptionTest.java
@@ -16,11 +16,13 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
+import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.util.io.Streams;
+import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
@@ -62,13 +64,13 @@ public class MissingPassphraseForDecryptionTest {
// interactive callback
SecretKeyPassphraseProvider callback = new SecretKeyPassphraseProvider() {
@Override
- public Passphrase getPassphraseFor(Long keyId) {
+ public Passphrase getPassphraseFor(@NotNull KeyIdentifier keyIdentifier) {
// is called in interactive mode
return Passphrase.fromPassword(passphrase);
}
@Override
- public boolean hasPassphrase(Long keyId) {
+ public boolean hasPassphrase(@NotNull KeyIdentifier keyIdentifier) {
return true;
}
};
@@ -95,13 +97,13 @@ public class MissingPassphraseForDecryptionTest {
SecretKeyPassphraseProvider callback = new SecretKeyPassphraseProvider() {
@Override
- public Passphrase getPassphraseFor(Long keyId) {
+ public Passphrase getPassphraseFor(@NotNull KeyIdentifier keyIdentifier) {
fail("MUST NOT get called in non-interactive mode.");
return null;
}
@Override
- public boolean hasPassphrase(Long keyId) {
+ public boolean hasPassphrase(@NotNull KeyIdentifier keyIdentifier) {
return true;
}
};
diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/PostponeDecryptionUsingKeyWithMissingPassphraseTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/PostponeDecryptionUsingKeyWithMissingPassphraseTest.java
index 8489da9a..1a4137f7 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/PostponeDecryptionUsingKeyWithMissingPassphraseTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/PostponeDecryptionUsingKeyWithMissingPassphraseTest.java
@@ -12,6 +12,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.util.io.Streams;
@@ -23,6 +24,8 @@ import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.key.protection.passphrase_provider.SecretKeyPassphraseProvider;
import org.pgpainless.util.Passphrase;
+import javax.annotation.Nonnull;
+
public class PostponeDecryptionUsingKeyWithMissingPassphraseTest {
private static PGPSecretKeyRing k1;
@@ -120,13 +123,13 @@ public class PostponeDecryptionUsingKeyWithMissingPassphraseTest {
public void missingPassphraseFirst() throws PGPException, IOException {
SecretKeyRingProtector protector1 = new CachingSecretKeyRingProtector(new SecretKeyPassphraseProvider() {
@Override
- public Passphrase getPassphraseFor(Long keyId) {
+ public Passphrase getPassphraseFor(@Nonnull KeyIdentifier keyIdentifier) {
fail("Although the first PKESK is for k1, we should have skipped it and tried k2 first, which has passphrase available.");
return null;
}
@Override
- public boolean hasPassphrase(Long keyId) {
+ public boolean hasPassphrase(@Nonnull KeyIdentifier keyIdentifier) {
return false;
}
});
@@ -134,7 +137,7 @@ public class PostponeDecryptionUsingKeyWithMissingPassphraseTest {
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(ENCRYPTED_FOR_K1_K2.getBytes(StandardCharsets.UTF_8)))
- .withOptions(new ConsumerOptions()
+ .withOptions(ConsumerOptions.get()
.addDecryptionKey(k1, protector1)
.addDecryptionKey(k2, protector2));
@@ -150,20 +153,20 @@ public class PostponeDecryptionUsingKeyWithMissingPassphraseTest {
SecretKeyRingProtector protector1 = SecretKeyRingProtector.unlockEachKeyWith(p1, k1);
SecretKeyRingProtector protector2 = new CachingSecretKeyRingProtector(new SecretKeyPassphraseProvider() {
@Override
- public Passphrase getPassphraseFor(Long keyId) {
+ public Passphrase getPassphraseFor(@Nonnull KeyIdentifier keyIdentifier) {
fail("This callback should not get called, since the first PKESK is for k1, which has a passphrase available.");
return null;
}
@Override
- public boolean hasPassphrase(Long keyId) {
+ public boolean hasPassphrase(@Nonnull KeyIdentifier keyIdentifier) {
return false;
}
});
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(ENCRYPTED_FOR_K1_K2.getBytes(StandardCharsets.UTF_8)))
- .withOptions(new ConsumerOptions()
+ .withOptions(ConsumerOptions.get()
.addDecryptionKey(k1, protector1)
.addDecryptionKey(k2, protector2));
@@ -178,13 +181,13 @@ public class PostponeDecryptionUsingKeyWithMissingPassphraseTest {
public void messagePassphraseFirst() throws PGPException, IOException {
SecretKeyPassphraseProvider provider = new SecretKeyPassphraseProvider() {
@Override
- public Passphrase getPassphraseFor(Long keyId) {
+ public Passphrase getPassphraseFor(@Nonnull KeyIdentifier keyIdentifier) {
fail("Since we provide a decryption passphrase, we should not try to decrypt any key.");
return null;
}
@Override
- public boolean hasPassphrase(Long keyId) {
+ public boolean hasPassphrase(@Nonnull KeyIdentifier keyIdentifier) {
return false;
}
};
@@ -192,7 +195,7 @@ public class PostponeDecryptionUsingKeyWithMissingPassphraseTest {
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(ENCRYPTED_FOR_K2_PASS_K1.getBytes(StandardCharsets.UTF_8)))
- .withOptions(new ConsumerOptions()
+ .withOptions(ConsumerOptions.get()
.addMessagePassphrase(PASSPHRASE)
.addDecryptionKey(k1, protector)
.addDecryptionKey(k2, protector));
diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/PreventDecryptionUsingNonEncryptionKeyTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/PreventDecryptionUsingNonEncryptionKeyTest.java
index f06f0233..ea54f2a4 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/PreventDecryptionUsingNonEncryptionKeyTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/PreventDecryptionUsingNonEncryptionKeyTest.java
@@ -180,7 +180,7 @@ public class PreventDecryptionUsingNonEncryptionKeyTest {
ByteArrayInputStream msgIn = new ByteArrayInputStream(MSG.getBytes(StandardCharsets.UTF_8));
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(msgIn)
- .withOptions(new ConsumerOptions().addDecryptionKey(secretKeys));
+ .withOptions(ConsumerOptions.get().addDecryptionKey(secretKeys));
Streams.drain(decryptionStream);
decryptionStream.close();
@@ -196,7 +196,7 @@ public class PreventDecryptionUsingNonEncryptionKeyTest {
ByteArrayInputStream msgIn = new ByteArrayInputStream(MSG.getBytes(StandardCharsets.UTF_8));
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
.onInputStream(msgIn)
- .withOptions(new ConsumerOptions().addDecryptionKey(secretKeys));
+ .withOptions(ConsumerOptions.get().addDecryptionKey(secretKeys));
Streams.drain(decryptionStream);
decryptionStream.close();
@@ -215,6 +215,6 @@ public class PreventDecryptionUsingNonEncryptionKeyTest {
assertThrows(MissingDecryptionMethodException.class, () ->
PGPainless.decryptAndOrVerify()
.onInputStream(msgIn)
- .withOptions(new ConsumerOptions().addDecryptionKey(secretKeys)));
+ .withOptions(ConsumerOptions.get().addDecryptionKey(secretKeys)));
}
}
diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/SignedMessageVerificationWithoutCertIsStillSignedTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/SignedMessageVerificationWithoutCertIsStillSignedTest.java
index 9f85b241..dfacbaac 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/SignedMessageVerificationWithoutCertIsStillSignedTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/SignedMessageVerificationWithoutCertIsStillSignedTest.java
@@ -30,7 +30,7 @@ public class SignedMessageVerificationWithoutCertIsStillSignedTest {
@Test
public void verifyMissingVerificationCertOptionStillResultsInMessageIsSigned() throws IOException, PGPException {
- ConsumerOptions withoutVerificationCert = new ConsumerOptions();
+ ConsumerOptions withoutVerificationCert = ConsumerOptions.get();
DecryptionStream verificationStream = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8)))
.withOptions(withoutVerificationCert);
diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyDetachedSignatureTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyDetachedSignatureTest.java
index e1406f87..e344d55f 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyDetachedSignatureTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyDetachedSignatureTest.java
@@ -57,7 +57,7 @@ public class VerifyDetachedSignatureTest {
DecryptionStream verifier = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(signedContent.getBytes(StandardCharsets.UTF_8)))
.withOptions(
- new ConsumerOptions()
+ ConsumerOptions.get()
.addVerificationOfDetachedSignatures(new ByteArrayInputStream(signature.getBytes(StandardCharsets.UTF_8)))
.addVerificationCerts(PGPainless.readKeyRing().keyRingCollection(pubkey, true).getPgpPublicKeyRingCollection())
.setMultiPassStrategy(new InMemoryMultiPassStrategy())
@@ -132,7 +132,7 @@ public class VerifyDetachedSignatureTest {
DecryptionStream verifier = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(signedContent.getBytes(StandardCharsets.UTF_8)))
.withOptions(
- new ConsumerOptions()
+ ConsumerOptions.get()
.addVerificationOfDetachedSignatures(new ByteArrayInputStream(signature.getBytes(StandardCharsets.UTF_8)))
.addVerificationCerts(PGPainless.readKeyRing().keyRingCollection(pubkey, true).getPgpPublicKeyRingCollection())
.setMultiPassStrategy(new InMemoryMultiPassStrategy())
diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyNotBeforeNotAfterTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyNotBeforeNotAfterTest.java
index 069a5f2d..e0608723 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyNotBeforeNotAfterTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyNotBeforeNotAfterTest.java
@@ -62,7 +62,7 @@ public class VerifyNotBeforeNotAfterTest {
@Test
public void noConstraintsVerifyInlineSig() throws PGPException, IOException {
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.addVerificationCert(certificate);
DecryptionStream verifier = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(inlineSigned))
@@ -74,7 +74,7 @@ public class VerifyNotBeforeNotAfterTest {
@Test
public void noConstraintsVerifyDetachedSig() throws PGPException, IOException {
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.addVerificationCert(certificate)
.addVerificationOfDetachedSignatures(new ByteArrayInputStream(detachedSignature));
DecryptionStream verifier = PGPainless.decryptAndOrVerify()
@@ -87,7 +87,7 @@ public class VerifyNotBeforeNotAfterTest {
@Test
public void notBeforeT1DoesNotRejectInlineSigMadeAtT1() throws PGPException, IOException {
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.verifyNotBefore(T1)
.addVerificationCert(certificate);
DecryptionStream verifier = PGPainless.decryptAndOrVerify()
@@ -99,7 +99,7 @@ public class VerifyNotBeforeNotAfterTest {
@Test
public void notBeforeT1DoesNotRejectDetachedSigMadeAtT1() throws PGPException, IOException {
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.verifyNotBefore(T1)
.addVerificationCert(certificate)
.addVerificationOfDetachedSignatures(new ByteArrayInputStream(detachedSignature));
@@ -112,7 +112,7 @@ public class VerifyNotBeforeNotAfterTest {
@Test
public void verifyNotBeforeT2DoesRejectInlineSignatureMadeAtT1() throws PGPException, IOException {
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.verifyNotBefore(T2)
.addVerificationCert(certificate);
DecryptionStream verifier = PGPainless.decryptAndOrVerify()
@@ -124,7 +124,7 @@ public class VerifyNotBeforeNotAfterTest {
@Test
public void verifyNotBeforeT2DoesRejectDetachedSigMadeAtT1() throws PGPException, IOException {
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.verifyNotBefore(T2)
.addVerificationCert(certificate)
.addVerificationOfDetachedSignatures(new ByteArrayInputStream(detachedSignature));
@@ -137,7 +137,7 @@ public class VerifyNotBeforeNotAfterTest {
@Test
public void verifyNotAfterT1DoesNotRejectInlineSigMadeAtT1() throws PGPException, IOException {
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.verifyNotAfter(T1)
.addVerificationCert(certificate);
DecryptionStream verifier = PGPainless.decryptAndOrVerify()
@@ -149,7 +149,7 @@ public class VerifyNotBeforeNotAfterTest {
@Test
public void verifyNotAfterT1DoesRejectDetachedSigMadeAtT1() throws PGPException, IOException {
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.verifyNotAfter(T1)
.addVerificationCert(certificate)
.addVerificationOfDetachedSignatures(new ByteArrayInputStream(detachedSignature));
@@ -162,7 +162,7 @@ public class VerifyNotBeforeNotAfterTest {
@Test
public void verifyNotAfterT0DoesRejectInlineSigMadeAtT1() throws PGPException, IOException {
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.verifyNotAfter(T0)
.addVerificationCert(certificate);
DecryptionStream verifier = PGPainless.decryptAndOrVerify()
@@ -174,7 +174,7 @@ public class VerifyNotBeforeNotAfterTest {
@Test
public void verifyNotAfterT0DoesRejectDetachedSigMadeAtT1() throws PGPException, IOException {
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.verifyNotAfter(T0)
.addVerificationCert(certificate)
.addVerificationOfDetachedSignatures(new ByteArrayInputStream(detachedSignature));
diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyVersion3SignaturePacketTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyVersion3SignaturePacketTest.java
index 6b9d9cab..6de4dc72 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyVersion3SignaturePacketTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyVersion3SignaturePacketTest.java
@@ -35,7 +35,7 @@ class VerifyVersion3SignaturePacketTest {
void verifyDetachedVersion3Signature() throws PGPException, IOException {
PGPSignature version3Signature = generateV3Signature();
- ConsumerOptions options = new ConsumerOptions()
+ ConsumerOptions options = ConsumerOptions.get()
.addVerificationCert(TestKeys.getEmilPublicKeyRing())
.addVerificationOfDetachedSignatures(new ByteArrayInputStream(version3Signature.getEncoded()));
diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyWithMissingPublicKeyCallbackTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyWithMissingPublicKeyCallbackTest.java
index 4845ddab..3bc2c5f0 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyWithMissingPublicKeyCallbackTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/VerifyWithMissingPublicKeyCallbackTest.java
@@ -13,21 +13,23 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
-import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
+import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.DocumentSignatureType;
+import org.pgpainless.algorithm.OpenPGPKeyVersion;
import org.pgpainless.encryption_signing.EncryptionStream;
import org.pgpainless.encryption_signing.ProducerOptions;
import org.pgpainless.encryption_signing.SigningOptions;
import org.pgpainless.key.TestKeys;
-import org.pgpainless.key.info.KeyRingInfo;
import org.pgpainless.key.protection.SecretKeyRingProtector;
-import org.pgpainless.key.util.KeyRingUtils;
+
+import javax.annotation.Nonnull;
/**
* Test functionality of the {@link MissingPublicKeyCallback} which is called when during signature verification,
@@ -38,11 +40,12 @@ public class VerifyWithMissingPublicKeyCallbackTest {
@Test
public void testMissingPublicKeyCallback() throws PGPException, IOException {
- PGPSecretKeyRing signingSecKeys = PGPainless.generateKeyRing().modernKeyRing("alice")
- .getPGPSecretKeyRing();
+ PGPainless api = PGPainless.getInstance();
+
+ OpenPGPKey signingSecKeys = api.generateKey(OpenPGPKeyVersion.v4).modernKeyRing("alice");
OpenPGPCertificate.OpenPGPComponentKey signingKey =
- new KeyRingInfo(signingSecKeys).getSigningSubkeys().get(0);
- PGPPublicKeyRing signingPubKeys = KeyRingUtils.publicKeyRingFrom(signingSecKeys);
+ signingSecKeys.getSigningKeys().get(0);
+ OpenPGPCertificate signingPubKeys = signingSecKeys.toCertificate();
PGPPublicKeyRing unrelatedKeys = TestKeys.getJulietPublicKeyRing();
String msg = "Arguing that you don't care about the right to privacy because you have nothing to hide" +
@@ -51,7 +54,7 @@ public class VerifyWithMissingPublicKeyCallbackTest {
EncryptionStream signingStream = PGPainless.encryptAndOrSign().onOutputStream(signOut)
.withOptions(ProducerOptions.sign(new SigningOptions().addInlineSignature(
SecretKeyRingProtector.unprotectedKeys(),
- signingSecKeys, DocumentSignatureType.CANONICAL_TEXT_DOCUMENT
+ signingSecKeys.getPGPSecretKeyRing(), DocumentSignatureType.CANONICAL_TEXT_DOCUMENT
)));
Streams.pipeAll(new ByteArrayInputStream(msg.getBytes(StandardCharsets.UTF_8)), signingStream);
signingStream.close();
@@ -62,8 +65,8 @@ public class VerifyWithMissingPublicKeyCallbackTest {
.addVerificationCert(unrelatedKeys)
.setMissingCertificateCallback(new MissingPublicKeyCallback() {
@Override
- public PGPPublicKeyRing onMissingPublicKeyEncountered(long keyId) {
- assertEquals(signingKey.getKeyIdentifier().getKeyId(), keyId, "Signing key-ID mismatch.");
+ public OpenPGPCertificate onMissingPublicKeyEncountered(@Nonnull KeyIdentifier keyIdentifier) {
+ assertEquals(signingKey.getKeyIdentifier(), keyIdentifier, "Signing key-ID mismatch.");
return signingPubKeys;
}
}));
diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeSecretKeyRingPassphraseTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeSecretKeyRingPassphraseTest.java
index ff41aa81..bfafa0a1 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeSecretKeyRingPassphraseTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/key/modification/ChangeSecretKeyRingPassphraseTest.java
@@ -97,7 +97,7 @@ public class ChangeSecretKeyRingPassphraseTest {
extractPrivateKey(subKey, Passphrase.fromPassword("weakPassphrase"));
PGPSecretKeyRing secretKeys = PGPainless.modifyKeyRing(keyRing)
- .changeSubKeyPassphraseFromOldPassphrase(subKey.getPublicKey().getKeyID(),
+ .changeSubKeyPassphraseFromOldPassphrase(subKey.getPublicKey().getKeyIdentifier(),
Passphrase.fromPassword("weakPassphrase"))
.withSecureDefaultSettings()
.toNewPassphrase(Passphrase.fromPassword("subKeyPassphrase"))
@@ -130,7 +130,7 @@ public class ChangeSecretKeyRingPassphraseTest {
PGPSecretKey subKey = keys.next();
PGPSecretKeyRing secretKeys = PGPainless.modifyKeyRing(keyRing)
- .changeSubKeyPassphraseFromOldPassphrase(subKey.getKeyID(), Passphrase.fromPassword("weakPassphrase"))
+ .changeSubKeyPassphraseFromOldPassphrase(subKey.getKeyIdentifier(), Passphrase.fromPassword("weakPassphrase"))
.withSecureDefaultSettings()
.toNoPassphrase()
.done();
diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/protection/CachingSecretKeyRingProtectorTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/protection/CachingSecretKeyRingProtectorTest.java
index 081d8959..d77466bf 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/key/protection/CachingSecretKeyRingProtectorTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/key/protection/CachingSecretKeyRingProtectorTest.java
@@ -13,11 +13,13 @@ import java.io.IOException;
import java.util.Iterator;
import java.util.Random;
+import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPKeyRing;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
+import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
@@ -30,13 +32,13 @@ public class CachingSecretKeyRingProtectorTest {
// Dummy passphrase callback that returns the doubled key-id as passphrase
private final SecretKeyPassphraseProvider dummyCallback = new SecretKeyPassphraseProvider() {
@Override
- public Passphrase getPassphraseFor(Long keyId) {
- long doubled = keyId * 2;
+ public Passphrase getPassphraseFor(@NotNull KeyIdentifier keyIdentifier) {
+ long doubled = keyIdentifier.getKeyId() * 2;
return Passphrase.fromPassword(Long.toString(doubled));
}
@Override
- public boolean hasPassphrase(Long keyId) {
+ public boolean hasPassphrase(@NotNull KeyIdentifier keyIdentifier) {
return true;
}
};
@@ -49,15 +51,15 @@ public class CachingSecretKeyRingProtectorTest {
}
@Test
- public void noCallbackReturnsNullForUnknownKeyId() {
+ public void noCallbackReturnsNullForUnknownKeyId() throws PGPException {
assertNull(protector.getDecryptor(123L));
assertNull(protector.getEncryptor(123L));
}
@Test
- public void testAddPassphrase() {
+ public void testAddPassphrase() throws PGPException {
Passphrase passphrase = Passphrase.fromPassword("HelloWorld");
- protector.addPassphrase(123L, passphrase);
+ protector.addPassphrase(new KeyIdentifier(123L), passphrase);
assertEquals(passphrase, protector.getPassphraseFor(123L));
assertNotNull(protector.getEncryptor(123L));
assertNotNull(protector.getDecryptor(123L));
@@ -75,7 +77,7 @@ public class CachingSecretKeyRingProtectorTest {
}
@Test
- public void testAddPassphraseForKeyRing() {
+ public void testAddPassphraseForKeyRing() throws PGPException {
PGPSecretKeyRing keys = PGPainless.generateKeyRing()
.modernKeyRing("test@test.test", "Passphrase123")
.getPGPSecretKeyRing();
diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/protection/MapBasedPassphraseProviderTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/protection/MapBasedPassphraseProviderTest.java
index 3961a2be..9dd6ba33 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/key/protection/MapBasedPassphraseProviderTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/key/protection/MapBasedPassphraseProviderTest.java
@@ -11,6 +11,7 @@ import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.junit.jupiter.api.Test;
@@ -22,10 +23,10 @@ public class MapBasedPassphraseProviderTest {
@Test
public void testMapBasedProvider() throws IOException, PGPException {
- Map passphraseMap = new ConcurrentHashMap<>();
- passphraseMap.put(1L, Passphrase.fromPassword("tiger"));
- passphraseMap.put(123123123L, Passphrase.fromPassword("snake"));
- passphraseMap.put(69696969L, Passphrase.emptyPassphrase());
+ Map passphraseMap = new ConcurrentHashMap<>();
+ passphraseMap.put(new KeyIdentifier(1L), Passphrase.fromPassword("tiger"));
+ passphraseMap.put(new KeyIdentifier(123123123L), Passphrase.fromPassword("snake"));
+ passphraseMap.put(new KeyIdentifier(69696969L), Passphrase.emptyPassphrase());
MapBasedPassphraseProvider provider = new MapBasedPassphraseProvider(passphraseMap);
assertEquals(Passphrase.fromPassword("tiger"), provider.getPassphraseFor(1L));
@@ -35,7 +36,7 @@ public class MapBasedPassphraseProviderTest {
PGPSecretKeyRing secretKeys = TestKeys.getCryptieSecretKeyRing();
passphraseMap = new ConcurrentHashMap<>();
- passphraseMap.put(secretKeys.getSecretKey().getKeyID(), TestKeys.CRYPTIE_PASSPHRASE);
+ passphraseMap.put(secretKeys.getSecretKey().getKeyIdentifier(), TestKeys.CRYPTIE_PASSPHRASE);
provider = new MapBasedPassphraseProvider(passphraseMap);
assertEquals(TestKeys.CRYPTIE_PASSPHRASE, provider.getPassphraseFor(secretKeys.getSecretKey()));
diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/protection/PassphraseProtectedKeyTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/protection/PassphraseProtectedKeyTest.java
index 6139ec0a..495d569e 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/key/protection/PassphraseProtectedKeyTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/key/protection/PassphraseProtectedKeyTest.java
@@ -10,9 +10,11 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import java.util.Iterator;
import javax.annotation.Nullable;
+import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
+import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.key.TestKeys;
@@ -29,8 +31,8 @@ public class PassphraseProtectedKeyTest {
new SecretKeyPassphraseProvider() {
@Nullable
@Override
- public Passphrase getPassphraseFor(Long keyId) {
- if (keyId == TestKeys.CRYPTIE_KEY_ID) {
+ public Passphrase getPassphraseFor(@NotNull KeyIdentifier keyIdentifier) {
+ if (keyIdentifier.getKeyId() == TestKeys.CRYPTIE_KEY_ID) {
return new Passphrase(TestKeys.CRYPTIE_PASSWORD.toCharArray());
} else {
return null;
@@ -38,19 +40,19 @@ public class PassphraseProtectedKeyTest {
}
@Override
- public boolean hasPassphrase(Long keyId) {
- return keyId == TestKeys.CRYPTIE_KEY_ID;
+ public boolean hasPassphrase(@NotNull KeyIdentifier keyIdentifier) {
+ return keyIdentifier.getKeyId() == TestKeys.CRYPTIE_KEY_ID;
}
});
@Test
- public void testReturnsNonNullDecryptorEncryptorForPassword() {
+ public void testReturnsNonNullDecryptorEncryptorForPassword() throws PGPException {
assertNotNull(protector.getEncryptor(TestKeys.CRYPTIE_KEY_ID));
assertNotNull(protector.getDecryptor(TestKeys.CRYPTIE_KEY_ID));
}
@Test
- public void testReturnsNullDecryptorEncryptorForNoPassword() {
+ public void testReturnsNullDecryptorEncryptorForNoPassword() throws PGPException {
assertNull(protector.getEncryptor(TestKeys.JULIET_KEY_ID));
assertNull(protector.getDecryptor(TestKeys.JULIET_KEY_ID));
}
diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/protection/SecretKeyRingProtectorTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/protection/SecretKeyRingProtectorTest.java
index 92ae553d..73258713 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/key/protection/SecretKeyRingProtectorTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/key/protection/SecretKeyRingProtectorTest.java
@@ -15,10 +15,12 @@ import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
+import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
+import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -85,8 +87,8 @@ public class SecretKeyRingProtectorTest {
@Test
public void testFromPassphraseMap() {
- Map passphraseMap = new ConcurrentHashMap<>();
- passphraseMap.put(1L, Passphrase.emptyPassphrase());
+ Map passphraseMap = new ConcurrentHashMap<>();
+ passphraseMap.put(new KeyIdentifier(1L), Passphrase.emptyPassphrase());
CachingSecretKeyRingProtector protector =
(CachingSecretKeyRingProtector) SecretKeyRingProtector.fromPassphraseMap(passphraseMap);
@@ -102,17 +104,17 @@ public class SecretKeyRingProtectorTest {
@Test
public void testMissingPassphraseCallback() {
- Map passphraseMap = new ConcurrentHashMap<>();
- passphraseMap.put(1L, Passphrase.emptyPassphrase());
+ Map passphraseMap = new ConcurrentHashMap<>();
+ passphraseMap.put(new KeyIdentifier(1L), Passphrase.emptyPassphrase());
CachingSecretKeyRingProtector protector = new CachingSecretKeyRingProtector(passphraseMap,
KeyRingProtectionSettings.secureDefaultSettings(), new SecretKeyPassphraseProvider() {
@Override
- public Passphrase getPassphraseFor(Long keyId) {
+ public Passphrase getPassphraseFor(@NotNull KeyIdentifier keyIdentifier) {
return Passphrase.fromPassword("missingP455w0rd");
}
@Override
- public boolean hasPassphrase(Long keyId) {
+ public boolean hasPassphrase(@NotNull KeyIdentifier keyIdentifier) {
return true;
}
});
diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/protection/UnprotectedKeysProtectorTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/protection/UnprotectedKeysProtectorTest.java
index 07f65a59..4f590c8b 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/key/protection/UnprotectedKeysProtectorTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/key/protection/UnprotectedKeysProtectorTest.java
@@ -6,6 +6,7 @@ package org.pgpainless.key.protection;
import static org.junit.jupiter.api.Assertions.assertNull;
+import org.bouncycastle.openpgp.PGPException;
import org.junit.jupiter.api.Test;
public class UnprotectedKeysProtectorTest {
@@ -13,12 +14,12 @@ public class UnprotectedKeysProtectorTest {
private final UnprotectedKeysProtector protector = new UnprotectedKeysProtector();
@Test
- public void testKeyProtectorReturnsNullDecryptor() {
+ public void testKeyProtectorReturnsNullDecryptor() throws PGPException {
assertNull(protector.getDecryptor(0L));
}
@Test
- public void testKeyProtectorReturnsNullEncryptor() {
+ public void testKeyProtectorReturnsNullEncryptor() throws PGPException {
assertNull(protector.getEncryptor(0L));
}
}
diff --git a/pgpainless-core/src/test/java/org/pgpainless/symmetric_encryption/MultiPassphraseSymmetricEncryptionTest.java b/pgpainless-core/src/test/java/org/pgpainless/symmetric_encryption/MultiPassphraseSymmetricEncryptionTest.java
index d0d37117..029f59ac 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/symmetric_encryption/MultiPassphraseSymmetricEncryptionTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/symmetric_encryption/MultiPassphraseSymmetricEncryptionTest.java
@@ -48,7 +48,7 @@ public class MultiPassphraseSymmetricEncryptionTest {
for (Passphrase passphrase : new Passphrase[] {Passphrase.fromPassword("p2"), Passphrase.fromPassword("p1")}) {
DecryptionStream decryptor = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(ciphertext))
- .withOptions(new ConsumerOptions()
+ .withOptions(ConsumerOptions.get()
.addMessagePassphrase(passphrase));
ByteArrayOutputStream plaintextOut = new ByteArrayOutputStream();
diff --git a/pgpainless-core/src/test/java/org/pgpainless/symmetric_encryption/SymmetricEncryptionTest.java b/pgpainless-core/src/test/java/org/pgpainless/symmetric_encryption/SymmetricEncryptionTest.java
index dbf7ca24..3fa54bf6 100644
--- a/pgpainless-core/src/test/java/org/pgpainless/symmetric_encryption/SymmetricEncryptionTest.java
+++ b/pgpainless-core/src/test/java/org/pgpainless/symmetric_encryption/SymmetricEncryptionTest.java
@@ -65,7 +65,7 @@ public class SymmetricEncryptionTest {
// Test symmetric decryption
DecryptionStream decryptor = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(ciphertext))
- .withOptions(new ConsumerOptions()
+ .withOptions(ConsumerOptions.get()
.addMessagePassphrase(encryptionPassphrase));
ByteArrayOutputStream decrypted = new ByteArrayOutputStream();
@@ -82,7 +82,7 @@ public class SymmetricEncryptionTest {
new SolitaryPassphraseProvider(Passphrase.fromPassword(TestKeys.CRYPTIE_PASSWORD)));
decryptor = PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(ciphertext))
- .withOptions(new ConsumerOptions()
+ .withOptions(ConsumerOptions.get()
.addDecryptionKeys(decryptionKeys, protector));
decrypted = new ByteArrayOutputStream();
@@ -110,7 +110,7 @@ public class SymmetricEncryptionTest {
assertThrows(MissingDecryptionMethodException.class, () -> PGPainless.decryptAndOrVerify()
.onInputStream(new ByteArrayInputStream(ciphertextOut.toByteArray()))
- .withOptions(new ConsumerOptions()
+ .withOptions(ConsumerOptions.get()
.setMissingKeyPassphraseStrategy(MissingKeyPassphraseStrategy.THROW_EXCEPTION)
.addMessagePassphrase(Passphrase.fromPassword("meldir"))));
}
diff --git a/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/MatchMakingSecretKeyRingProtector.kt b/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/MatchMakingSecretKeyRingProtector.kt
index 13347721..74e79511 100644
--- a/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/MatchMakingSecretKeyRingProtector.kt
+++ b/pgpainless-sop/src/main/kotlin/org/pgpainless/sop/MatchMakingSecretKeyRingProtector.kt
@@ -4,9 +4,11 @@
package org.pgpainless.sop
+import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.PGPSecretKeyRing
+import org.bouncycastle.openpgp.api.OpenPGPKey
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor
import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor
import org.pgpainless.bouncycastle.extensions.isDecrypted
@@ -41,7 +43,7 @@ class MatchMakingSecretKeyRingProtector : SecretKeyRingProtector {
}
if (testPassphrase(passphrase, subkey)) {
- protector.addPassphrase(subkey.keyID, passphrase)
+ protector.addPassphrase(subkey.keyIdentifier, passphrase)
}
}
}
@@ -54,11 +56,11 @@ class MatchMakingSecretKeyRingProtector : SecretKeyRingProtector {
key.forEach { subkey ->
if (subkey.isDecrypted()) {
- protector.addPassphrase(subkey.keyID, Passphrase.emptyPassphrase())
+ protector.addPassphrase(subkey.keyIdentifier, Passphrase.emptyPassphrase())
} else {
passphrases.forEach { passphrase ->
if (testPassphrase(passphrase, subkey)) {
- protector.addPassphrase(subkey.keyID, passphrase)
+ protector.addPassphrase(subkey.keyIdentifier, passphrase)
}
}
}
@@ -74,11 +76,17 @@ class MatchMakingSecretKeyRingProtector : SecretKeyRingProtector {
false
}
- override fun hasPassphraseFor(keyId: Long): Boolean = protector.hasPassphrase(keyId)
+ override fun hasPassphraseFor(keyIdentifier: KeyIdentifier): Boolean =
+ protector.hasPassphrase(keyIdentifier)
- override fun getDecryptor(keyId: Long): PBESecretKeyDecryptor? = protector.getDecryptor(keyId)
+ override fun getDecryptor(keyIdentifier: KeyIdentifier): PBESecretKeyDecryptor? =
+ protector.getDecryptor(keyIdentifier)
- override fun getEncryptor(keyId: Long): PBESecretKeyEncryptor? = protector.getEncryptor(keyId)
+ override fun getEncryptor(keyIdentifier: KeyIdentifier): PBESecretKeyEncryptor? =
+ protector.getEncryptor(keyIdentifier)
+
+ override fun getKeyPassword(p0: OpenPGPKey.OpenPGPSecretKey): CharArray? =
+ protector.getKeyPassword(p0)
/** Clear all known passphrases from the protector. */
fun clear() {
diff --git a/pgpainless-sop/src/test/java/sop/testsuite/pgpainless/operation/PGPainlessChangeKeyPasswordTest.java b/pgpainless-sop/src/test/java/sop/testsuite/pgpainless/operation/PGPainlessChangeKeyPasswordTest.java
index cc6dd4dd..cb45551d 100644
--- a/pgpainless-sop/src/test/java/sop/testsuite/pgpainless/operation/PGPainlessChangeKeyPasswordTest.java
+++ b/pgpainless-sop/src/test/java/sop/testsuite/pgpainless/operation/PGPainlessChangeKeyPasswordTest.java
@@ -4,6 +4,7 @@
package sop.testsuite.pgpainless.operation;
+import org.bouncycastle.bcpg.KeyIdentifier;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
@@ -38,9 +39,9 @@ public class PGPainlessChangeKeyPasswordTest extends ChangeKeyPasswordTest {
.build()
.getPGPSecretKeyRing();
Iterator keys = secretKeys.getPublicKeys();
- long primaryKeyId = keys.next().getKeyID();
- long signingKeyId = keys.next().getKeyID();
- long encryptKeyId = keys.next().getKeyID();
+ KeyIdentifier primaryKeyId = keys.next().getKeyIdentifier();
+ KeyIdentifier signingKeyId = keys.next().getKeyIdentifier();
+ KeyIdentifier encryptKeyId = keys.next().getKeyIdentifier();
String p1 = "sw0rdf1sh";
String p2 = "0r4ng3";