mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-09-09 10:19:39 +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:
parent
9a1a01fe05
commit
883eb80a63
6 changed files with 47 additions and 14 deletions
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue