1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-09-09 02:09:38 +02:00

Bump bcpg, bcprov to 1.80, add bcutil dependency

Adding bcutil as a dependency is apparently required now.
See https://github.com/bcgit/bc-java/issues/1977
This commit is contained in:
Paul Schaub 2025-03-11 22:04:03 +01:00
parent 9a1a01fe05
commit 883eb80a63
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
6 changed files with 47 additions and 14 deletions

View file

@ -22,6 +22,7 @@ dependencies {
// Bouncy Castle // Bouncy Castle
api "org.bouncycastle:bcprov-jdk18on:$bouncyCastleVersion" api "org.bouncycastle:bcprov-jdk18on:$bouncyCastleVersion"
api "org.bouncycastle:bcpg-jdk18on:$bouncyPgVersion" api "org.bouncycastle:bcpg-jdk18on:$bouncyPgVersion"
api "org.bouncycastle:bcutil-jdk18on:$bouncyCastleVersion"
// api(files("../libs/bcpg-jdk18on-1.70.jar")) // api(files("../libs/bcpg-jdk18on-1.70.jar"))
// @Nullable, @Nonnull annotations // @Nullable, @Nonnull annotations

View file

@ -4,7 +4,11 @@
package org.pgpainless.decryption_verification package org.pgpainless.decryption_verification
import org.bouncycastle.bcpg.AEADEncDataPacket
import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket
import org.bouncycastle.openpgp.PGPPrivateKey import org.bouncycastle.openpgp.PGPPrivateKey
import org.bouncycastle.openpgp.PGPSessionKey
import org.bouncycastle.openpgp.operator.PGPDataDecryptor
import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory
import org.bouncycastle.util.encoders.Base64 import org.bouncycastle.util.encoders.Base64
import org.pgpainless.key.SubkeyIdentifier import org.pgpainless.key.SubkeyIdentifier
@ -21,16 +25,34 @@ import org.pgpainless.key.SubkeyIdentifier
class CachingBcPublicKeyDataDecryptorFactory( class CachingBcPublicKeyDataDecryptorFactory(
privateKey: PGPPrivateKey, privateKey: PGPPrivateKey,
override val subkeyIdentifier: SubkeyIdentifier override val subkeyIdentifier: SubkeyIdentifier
) : BcPublicKeyDataDecryptorFactory(privateKey), CustomPublicKeyDataDecryptorFactory { ) : CustomPublicKeyDataDecryptorFactory() {
private val decryptorFactory: BcPublicKeyDataDecryptorFactory =
BcPublicKeyDataDecryptorFactory(privateKey)
private val cachedSessions: MutableMap<String, ByteArray> = mutableMapOf() private val cachedSessions: MutableMap<String, ByteArray> = mutableMapOf()
override fun createDataDecryptor(p0: Boolean, p1: Int, p2: ByteArray?): PGPDataDecryptor {
return decryptorFactory.createDataDecryptor(p0, p1, p2)
}
override fun createDataDecryptor(p0: AEADEncDataPacket?, p1: PGPSessionKey?): PGPDataDecryptor {
return decryptorFactory.createDataDecryptor(p0, p1)
}
override fun createDataDecryptor(
p0: SymmetricEncIntegrityPacket?,
p1: PGPSessionKey?
): PGPDataDecryptor {
return decryptorFactory.createDataDecryptor(p0, p1)
}
override fun recoverSessionData( override fun recoverSessionData(
keyAlgorithm: Int, keyAlgorithm: Int,
secKeyData: Array<out ByteArray> secKeyData: Array<out ByteArray>,
pkeskVersion: Int
): ByteArray = ): ByteArray =
lookupSessionKeyData(secKeyData) lookupSessionKeyData(secKeyData)
?: costlyRecoverSessionData(keyAlgorithm, secKeyData).also { ?: costlyRecoverSessionData(keyAlgorithm, secKeyData, pkeskVersion).also {
cacheSessionKeyData(secKeyData, it) cacheSessionKeyData(secKeyData, it)
} }
@ -39,8 +61,9 @@ class CachingBcPublicKeyDataDecryptorFactory(
private fun costlyRecoverSessionData( private fun costlyRecoverSessionData(
keyAlgorithm: Int, keyAlgorithm: Int,
secKeyData: Array<out ByteArray> secKeyData: Array<out ByteArray>,
): ByteArray = super.recoverSessionData(keyAlgorithm, secKeyData) pkeskVersion: Int
): ByteArray = decryptorFactory.recoverSessionData(keyAlgorithm, secKeyData, pkeskVersion)
private fun cacheSessionKeyData(secKeyData: Array<out ByteArray>, sessionKey: ByteArray) { private fun cacheSessionKeyData(secKeyData: Array<out ByteArray>, sessionKey: ByteArray) {
cachedSessions[toKey(secKeyData)] = sessionKey.clone() cachedSessions[toKey(secKeyData)] = sessionKey.clone()

View file

@ -4,6 +4,7 @@
package org.pgpainless.decryption_verification package org.pgpainless.decryption_verification
import org.bouncycastle.openpgp.operator.AbstractPublicKeyDataDecryptorFactory
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory
import org.pgpainless.key.SubkeyIdentifier import org.pgpainless.key.SubkeyIdentifier
@ -14,7 +15,7 @@ import org.pgpainless.key.SubkeyIdentifier
* *
* @see [ConsumerOptions.addCustomDecryptorFactory] * @see [ConsumerOptions.addCustomDecryptorFactory]
*/ */
interface CustomPublicKeyDataDecryptorFactory : PublicKeyDataDecryptorFactory { abstract class CustomPublicKeyDataDecryptorFactory : AbstractPublicKeyDataDecryptorFactory() {
/** /**
* Identifier for the subkey for which this particular [CustomPublicKeyDataDecryptorFactory] is * Identifier for the subkey for which this particular [CustomPublicKeyDataDecryptorFactory] is
@ -22,5 +23,5 @@ interface CustomPublicKeyDataDecryptorFactory : PublicKeyDataDecryptorFactory {
* *
* @return subkey identifier * @return subkey identifier
*/ */
val subkeyIdentifier: SubkeyIdentifier abstract val subkeyIdentifier: SubkeyIdentifier
} }

View file

@ -29,11 +29,17 @@ class HardwareSecurity {
* @param keyId id of the key * @param keyId id of the key
* @param keyAlgorithm algorithm * @param keyAlgorithm algorithm
* @param sessionKeyData encrypted session key * @param sessionKeyData encrypted session key
* @param pkeskVersion version of the Public-Key-Encrypted-Session-Key packet (3 or 6)
* @return decrypted session key * @return decrypted session key
* @throws HardwareSecurityException exception * @throws HardwareSecurityException exception
*/ */
@Throws(HardwareSecurityException::class) @Throws(HardwareSecurityException::class)
fun decryptSessionKey(keyId: Long, keyAlgorithm: Int, sessionKeyData: ByteArray): ByteArray fun decryptSessionKey(
keyId: Long,
keyAlgorithm: Int,
sessionKeyData: ByteArray,
pkeskVersion: Int
): ByteArray
} }
/** /**
@ -44,7 +50,7 @@ class HardwareSecurity {
class HardwareDataDecryptorFactory( class HardwareDataDecryptorFactory(
override val subkeyIdentifier: SubkeyIdentifier, override val subkeyIdentifier: SubkeyIdentifier,
private val callback: DecryptionCallback, private val callback: DecryptionCallback,
) : CustomPublicKeyDataDecryptorFactory { ) : CustomPublicKeyDataDecryptorFactory() {
// luckily we can instantiate the BcPublicKeyDataDecryptorFactory with null as argument. // luckily we can instantiate the BcPublicKeyDataDecryptorFactory with null as argument.
private val factory: PublicKeyDataDecryptorFactory = BcPublicKeyDataDecryptorFactory(null) private val factory: PublicKeyDataDecryptorFactory = BcPublicKeyDataDecryptorFactory(null)
@ -73,10 +79,12 @@ class HardwareSecurity {
override fun recoverSessionData( override fun recoverSessionData(
keyAlgorithm: Int, keyAlgorithm: Int,
secKeyData: Array<out ByteArray> secKeyData: Array<out ByteArray>,
pkeskVersion: Int
): ByteArray { ): ByteArray {
return try { return try {
callback.decryptSessionKey(subkeyIdentifier.subkeyId, keyAlgorithm, secKeyData[0]) callback.decryptSessionKey(
subkeyIdentifier.subkeyId, keyAlgorithm, secKeyData[0], pkeskVersion)
} catch (e: HardwareSecurityException) { } catch (e: HardwareSecurityException) {
throw PGPException("Hardware-backed decryption failed.", e) throw PGPException("Hardware-backed decryption failed.", e)
} }

View file

@ -55,14 +55,14 @@ public class CustomPublicKeyDataDecryptorFactoryTest {
HardwareSecurity.DecryptionCallback hardwareDecryptionCallback = new HardwareSecurity.DecryptionCallback() { HardwareSecurity.DecryptionCallback hardwareDecryptionCallback = new HardwareSecurity.DecryptionCallback() {
@Override @Override
public byte[] decryptSessionKey(long keyId, int keyAlgorithm, byte[] sessionKeyData) public byte[] decryptSessionKey(long keyId, int keyAlgorithm, byte[] sessionKeyData, int pkeskVersion)
throws HardwareSecurity.HardwareSecurityException { throws HardwareSecurity.HardwareSecurityException {
// Emulate hardware decryption. // Emulate hardware decryption.
try { try {
PGPSecretKey decryptionKey = secretKey.getSecretKey(encryptionKey.getKeyID()); PGPSecretKey decryptionKey = secretKey.getSecretKey(encryptionKey.getKeyID());
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(decryptionKey, Passphrase.emptyPassphrase()); PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(decryptionKey, Passphrase.emptyPassphrase());
PublicKeyDataDecryptorFactory internal = new BcPublicKeyDataDecryptorFactory(privateKey); PublicKeyDataDecryptorFactory internal = new BcPublicKeyDataDecryptorFactory(privateKey);
return internal.recoverSessionData(keyAlgorithm, new byte[][] {sessionKeyData}); return internal.recoverSessionData(keyAlgorithm, new byte[][] {sessionKeyData}, pkeskVersion);
} catch (PGPException e) { } catch (PGPException e) {
throw new HardwareSecurity.HardwareSecurityException(); throw new HardwareSecurity.HardwareSecurityException();
} }

View file

@ -8,7 +8,7 @@ allprojects {
isSnapshot = true isSnapshot = true
pgpainlessMinAndroidSdk = 10 pgpainlessMinAndroidSdk = 10
javaSourceCompatibility = 1.8 javaSourceCompatibility = 1.8
bouncyCastleVersion = '1.78.1' bouncyCastleVersion = '1.80'
bouncyPgVersion = bouncyCastleVersion bouncyPgVersion = bouncyCastleVersion
junitVersion = '5.8.2' junitVersion = '5.8.2'
logbackVersion = '1.5.13' logbackVersion = '1.5.13'