Add PGPSecretKey.unlock() methods

This commit is contained in:
Paul Schaub 2023-09-12 14:35:29 +02:00
parent 6f9e692474
commit 19063454cb
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
6 changed files with 60 additions and 15 deletions

View File

@ -5,7 +5,50 @@
package org.bouncycastle.extensions
import org.bouncycastle.bcpg.S2K
import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPPrivateKey
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor
import org.pgpainless.exception.KeyIntegrityException
import org.pgpainless.exception.WrongPassphraseException
import org.pgpainless.key.protection.SecretKeyRingProtector
import org.pgpainless.key.protection.UnlockSecretKey
import org.pgpainless.util.Passphrase
/**
* Unlock the secret key to get its [PGPPrivateKey].
*
* @param passphrase passphrase to unlock the secret key with.
* @throws PGPException if the key cannot be unlocked
* @throws KeyIntegrityException if the public key part was tampered with
* @throws WrongPassphraseException
*/
@Throws(PGPException::class, KeyIntegrityException::class)
fun PGPSecretKey.unlock(passphrase: Passphrase): PGPPrivateKey =
UnlockSecretKey.unlockSecretKey(this, passphrase)
/**
* Unlock the secret key to get its [PGPPrivateKey].
*
* @param protector protector to unlock the secret key.
* @throws PGPException if the key cannot be unlocked
* @throws KeyIntegrityException if the public key part was tampered with
*/
@Throws(PGPException::class, KeyIntegrityException::class)
@JvmOverloads
fun PGPSecretKey.unlock(protector: SecretKeyRingProtector = SecretKeyRingProtector.unprotectedKeys()): PGPPrivateKey =
UnlockSecretKey.unlockSecretKey(this, protector)
/**
* Unlock the secret key to get its [PGPPrivateKey].
*
* @param decryptor decryptor to unlock the secret key.
* @throws PGPException if the key cannot be unlocked
* @throws KeyIntegrityException if the public key part was tampered with
*/
@Throws(PGPException::class, KeyIntegrityException::class)
fun PGPSecretKey.unlock(decryptor: PBESecretKeyDecryptor?): PGPPrivateKey =
UnlockSecretKey.unlockSecretKey(this, decryptor)
/**
* Returns indication that the secret key is encrypted.

View File

@ -7,6 +7,7 @@ package org.pgpainless.decryption_verification
import openpgp.openPgpKeyId
import org.bouncycastle.bcpg.BCPGInputStream
import org.bouncycastle.bcpg.UnsupportedPacketVersionException
import org.bouncycastle.extensions.unlock
import org.bouncycastle.openpgp.*
import org.bouncycastle.openpgp.operator.PBEDataDecryptorFactory
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory
@ -21,7 +22,6 @@ import org.pgpainless.decryption_verification.syntax_check.StackSymbol
import org.pgpainless.exception.*
import org.pgpainless.implementation.ImplementationFactory
import org.pgpainless.key.SubkeyIdentifier
import org.pgpainless.key.protection.UnlockSecretKey
import org.pgpainless.key.util.KeyRingUtils
import org.pgpainless.policy.Policy
import org.pgpainless.signature.SignatureUtils
@ -302,7 +302,7 @@ class OpenPgpMessageInputStream(
continue
}
val privateKey = UnlockSecretKey.unlockSecretKey(secretKey, protector)
val privateKey = secretKey.unlock(protector)
if (decryptWithPrivateKey(esks, privateKey, decryptionKeyId, pkesk)) {
return true
}
@ -325,7 +325,7 @@ class OpenPgpMessageInputStream(
continue
}
val privateKey = UnlockSecretKey.unlockSecretKey(secretKey, protector)
val privateKey = secretKey.unlock(protector)
if (decryptWithPrivateKey(esks, privateKey, decryptionKeyId, pkesk)) {
return true
}
@ -351,7 +351,7 @@ class OpenPgpMessageInputStream(
LOGGER.debug("Attempt decryption with key $decryptionKeyId while interactively requesting its passphrase.")
val protector = options.getSecretKeyProtector(decryptionKeys) ?: continue
val privateKey = UnlockSecretKey.unlockSecretKey(secretKey, protector)
val privateKey = secretKey.unlock(protector)
if (decryptWithPrivateKey(esks, privateKey, decryptionKeyId, pkesk)) {
return true
}

View File

@ -4,6 +4,7 @@
package org.pgpainless.encryption_signing
import org.bouncycastle.extensions.unlock
import org.bouncycastle.openpgp.*
import org.pgpainless.PGPainless.Companion.getPolicy
import org.pgpainless.PGPainless.Companion.inspectKeyRing
@ -17,7 +18,6 @@ import org.pgpainless.implementation.ImplementationFactory
import org.pgpainless.key.OpenPgpFingerprint.Companion.of
import org.pgpainless.key.SubkeyIdentifier
import org.pgpainless.key.protection.SecretKeyRingProtector
import org.pgpainless.key.protection.UnlockSecretKey.Companion.unlockSecretKey
import org.pgpainless.policy.Policy
import org.pgpainless.signature.subpackets.BaseSignatureSubpackets.Callback
import org.pgpainless.signature.subpackets.SignatureSubpackets
@ -157,7 +157,7 @@ class SigningOptions {
for (signingPubKey in signingPubKeys) {
val signingSecKey: PGPSecretKey = signingKey.getSecretKey(signingPubKey.keyID)
?: throw MissingSecretKeyException(of(signingKey), signingPubKey.keyID)
val signingSubkey: PGPPrivateKey = unlockSecretKey(signingSecKey, signingKeyProtector)
val signingSubkey: PGPPrivateKey = signingSecKey.unlock(signingKeyProtector)
val hashAlgorithms =
if (userId != null) keyRingInfo.getPreferredHashAlgorithms(userId)
else keyRingInfo.getPreferredHashAlgorithms(signingPubKey.keyID)
@ -199,7 +199,7 @@ class SigningOptions {
val signingSecKey = signingKey.getSecretKey(signingPubKey.keyID)
?: throw MissingSecretKeyException(of(signingKey), signingPubKey.keyID)
val signingSubkey = unlockSecretKey(signingSecKey, signingKeyProtector)
val signingSubkey = signingSecKey.unlock(signingKeyProtector)
val hashAlgorithms = keyRingInfo.getPreferredHashAlgorithms(signingPubKey.keyID)
val hashAlgorithm: HashAlgorithm = negotiateHashAlgorithm(hashAlgorithms, getPolicy())
addSigningMethod(signingKey, signingSubkey, hashAlgorithm, signatureType, false, subpacketsCallback)
@ -292,7 +292,7 @@ class SigningOptions {
for (signingPubKey in signingPubKeys) {
val signingSecKey: PGPSecretKey = signingKey.getSecretKey(signingPubKey.keyID)
?: throw MissingSecretKeyException(of(signingKey), signingPubKey.keyID)
val signingSubkey: PGPPrivateKey = unlockSecretKey(signingSecKey, signingKeyProtector)
val signingSubkey: PGPPrivateKey = signingSecKey.unlock(signingKeyProtector)
val hashAlgorithms =
if (userId != null) keyRingInfo.getPreferredHashAlgorithms(userId)
else keyRingInfo.getPreferredHashAlgorithms(signingPubKey.keyID)
@ -332,7 +332,7 @@ class SigningOptions {
if (signingPubKey.keyID == keyId) {
val signingSecKey: PGPSecretKey = signingKey.getSecretKey(signingPubKey.keyID)
?: throw MissingSecretKeyException(of(signingKey), signingPubKey.keyID)
val signingSubkey: PGPPrivateKey = unlockSecretKey(signingSecKey, signingKeyProtector)
val signingSubkey: PGPPrivateKey = signingSecKey.unlock(signingKeyProtector)
val hashAlgorithms = keyRingInfo.getPreferredHashAlgorithms(signingPubKey.keyID)
val hashAlgorithm: HashAlgorithm = negotiateHashAlgorithm(hashAlgorithms, getPolicy())
addSigningMethod(signingKey, signingSubkey, hashAlgorithm, signatureType, true, subpacketsCallback)

View File

@ -4,6 +4,7 @@
package org.pgpainless.key.generation
import org.bouncycastle.extensions.unlock
import org.bouncycastle.openpgp.*
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor
import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor
@ -14,7 +15,6 @@ import org.pgpainless.PGPainless
import org.pgpainless.algorithm.KeyFlag
import org.pgpainless.algorithm.SignatureType
import org.pgpainless.implementation.ImplementationFactory
import org.pgpainless.key.protection.UnlockSecretKey
import org.pgpainless.policy.Policy
import org.pgpainless.provider.ProviderFactory
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets
@ -129,7 +129,7 @@ class KeyRingBuilder : KeyRingBuilderInterface<KeyRingBuilder> {
// Attempt to add additional user-ids to the primary public key
var primaryPubKey = secretKeys.next().publicKey
val privateKey = UnlockSecretKey.unlockSecretKey(secretKeyRing.secretKey, secretKeyDecryptor)
val privateKey = secretKeyRing.secretKey.unlock(secretKeyDecryptor)
val userIdIterator = userIds.entries.iterator()
if (userIdIterator.hasNext()) {
userIdIterator.next() // Skip primary userId

View File

@ -5,13 +5,13 @@
package org.pgpainless.key.protection.fixes
import org.bouncycastle.bcpg.SecretKeyPacket
import org.bouncycastle.extensions.unlock
import org.bouncycastle.openpgp.PGPSecretKey
import org.bouncycastle.openpgp.PGPSecretKeyRing
import org.pgpainless.algorithm.HashAlgorithm
import org.pgpainless.exception.WrongPassphraseException
import org.pgpainless.implementation.ImplementationFactory
import org.pgpainless.key.protection.SecretKeyRingProtector
import org.pgpainless.key.protection.UnlockSecretKey.Companion.unlockSecretKey
/**
* Repair class to fix keys which use S2K usage of value [SecretKeyPacket.USAGE_CHECKSUM].
@ -62,7 +62,7 @@ class S2KUsageFix {
throw WrongPassphraseException("Missing passphrase for key with ID " + java.lang.Long.toHexString(keyId))
}
val privateKey = unlockSecretKey(key, protector)
val privateKey = key.unlock(protector)
// This constructor makes use of USAGE_SHA1 by default
val fixedKey = PGPSecretKey(
privateKey,

View File

@ -8,12 +8,12 @@ import openpgp.openPgpKeyId
import org.bouncycastle.bcpg.S2K
import org.bouncycastle.bcpg.SecretKeyPacket
import org.bouncycastle.extensions.certificate
import org.bouncycastle.extensions.unlock
import org.bouncycastle.openpgp.*
import org.bouncycastle.util.Strings
import org.pgpainless.exception.MissingPassphraseException
import org.pgpainless.implementation.ImplementationFactory
import org.pgpainless.key.protection.SecretKeyRingProtector
import org.pgpainless.key.protection.UnlockSecretKey
import org.pgpainless.key.protection.fixes.S2KUsageFix
import org.slf4j.Logger
import org.slf4j.LoggerFactory
@ -164,8 +164,10 @@ class KeyRingUtils {
* @throws PGPException if something goes wrong (e.g. wrong passphrase)
*/
@JvmStatic
@Deprecated("Deprecated in favor of secretKey.unlock(protector)",
ReplaceWith("secretKey.unlock(protector)"))
fun unlockSecretKey(secretKey: PGPSecretKey, protector: SecretKeyRingProtector): PGPPrivateKey {
return UnlockSecretKey.unlockSecretKey(secretKey, protector)
return secretKey.unlock(protector)
}
/**