mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-04-16 03:28:37 +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
pgpainless-core
build.gradle
version.gradlesrc
main/kotlin/org/pgpainless/decryption_verification
test/java/org/pgpainless/decryption_verification
|
@ -22,6 +22,7 @@ dependencies {
|
|||
// Bouncy Castle
|
||||
api "org.bouncycastle:bcprov-jdk18on:$bouncyCastleVersion"
|
||||
api "org.bouncycastle:bcpg-jdk18on:$bouncyPgVersion"
|
||||
api "org.bouncycastle:bcutil-jdk18on:$bouncyCastleVersion"
|
||||
// api(files("../libs/bcpg-jdk18on-1.70.jar"))
|
||||
|
||||
// @Nullable, @Nonnull annotations
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
|
||||
package org.pgpainless.decryption_verification
|
||||
|
||||
import org.bouncycastle.bcpg.AEADEncDataPacket
|
||||
import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket
|
||||
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.util.encoders.Base64
|
||||
import org.pgpainless.key.SubkeyIdentifier
|
||||
|
@ -21,16 +25,34 @@ import org.pgpainless.key.SubkeyIdentifier
|
|||
class CachingBcPublicKeyDataDecryptorFactory(
|
||||
privateKey: PGPPrivateKey,
|
||||
override val subkeyIdentifier: SubkeyIdentifier
|
||||
) : BcPublicKeyDataDecryptorFactory(privateKey), CustomPublicKeyDataDecryptorFactory {
|
||||
) : CustomPublicKeyDataDecryptorFactory() {
|
||||
|
||||
private val decryptorFactory: BcPublicKeyDataDecryptorFactory =
|
||||
BcPublicKeyDataDecryptorFactory(privateKey)
|
||||
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(
|
||||
keyAlgorithm: Int,
|
||||
secKeyData: Array<out ByteArray>
|
||||
secKeyData: Array<out ByteArray>,
|
||||
pkeskVersion: Int
|
||||
): ByteArray =
|
||||
lookupSessionKeyData(secKeyData)
|
||||
?: costlyRecoverSessionData(keyAlgorithm, secKeyData).also {
|
||||
?: costlyRecoverSessionData(keyAlgorithm, secKeyData, pkeskVersion).also {
|
||||
cacheSessionKeyData(secKeyData, it)
|
||||
}
|
||||
|
||||
|
@ -39,8 +61,9 @@ class CachingBcPublicKeyDataDecryptorFactory(
|
|||
|
||||
private fun costlyRecoverSessionData(
|
||||
keyAlgorithm: Int,
|
||||
secKeyData: Array<out ByteArray>
|
||||
): ByteArray = super.recoverSessionData(keyAlgorithm, secKeyData)
|
||||
secKeyData: Array<out ByteArray>,
|
||||
pkeskVersion: Int
|
||||
): ByteArray = decryptorFactory.recoverSessionData(keyAlgorithm, secKeyData, pkeskVersion)
|
||||
|
||||
private fun cacheSessionKeyData(secKeyData: Array<out ByteArray>, sessionKey: ByteArray) {
|
||||
cachedSessions[toKey(secKeyData)] = sessionKey.clone()
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
package org.pgpainless.decryption_verification
|
||||
|
||||
import org.bouncycastle.openpgp.operator.AbstractPublicKeyDataDecryptorFactory
|
||||
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory
|
||||
import org.pgpainless.key.SubkeyIdentifier
|
||||
|
||||
|
@ -14,7 +15,7 @@ import org.pgpainless.key.SubkeyIdentifier
|
|||
*
|
||||
* @see [ConsumerOptions.addCustomDecryptorFactory]
|
||||
*/
|
||||
interface CustomPublicKeyDataDecryptorFactory : PublicKeyDataDecryptorFactory {
|
||||
abstract class CustomPublicKeyDataDecryptorFactory : AbstractPublicKeyDataDecryptorFactory() {
|
||||
|
||||
/**
|
||||
* Identifier for the subkey for which this particular [CustomPublicKeyDataDecryptorFactory] is
|
||||
|
@ -22,5 +23,5 @@ interface CustomPublicKeyDataDecryptorFactory : PublicKeyDataDecryptorFactory {
|
|||
*
|
||||
* @return subkey identifier
|
||||
*/
|
||||
val subkeyIdentifier: SubkeyIdentifier
|
||||
abstract val subkeyIdentifier: SubkeyIdentifier
|
||||
}
|
||||
|
|
|
@ -29,11 +29,17 @@ class HardwareSecurity {
|
|||
* @param keyId id of the key
|
||||
* @param keyAlgorithm algorithm
|
||||
* @param sessionKeyData encrypted session key
|
||||
* @param pkeskVersion version of the Public-Key-Encrypted-Session-Key packet (3 or 6)
|
||||
* @return decrypted session key
|
||||
* @throws HardwareSecurityException exception
|
||||
*/
|
||||
@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(
|
||||
override val subkeyIdentifier: SubkeyIdentifier,
|
||||
private val callback: DecryptionCallback,
|
||||
) : CustomPublicKeyDataDecryptorFactory {
|
||||
) : CustomPublicKeyDataDecryptorFactory() {
|
||||
|
||||
// luckily we can instantiate the BcPublicKeyDataDecryptorFactory with null as argument.
|
||||
private val factory: PublicKeyDataDecryptorFactory = BcPublicKeyDataDecryptorFactory(null)
|
||||
|
@ -73,10 +79,12 @@ class HardwareSecurity {
|
|||
|
||||
override fun recoverSessionData(
|
||||
keyAlgorithm: Int,
|
||||
secKeyData: Array<out ByteArray>
|
||||
secKeyData: Array<out ByteArray>,
|
||||
pkeskVersion: Int
|
||||
): ByteArray {
|
||||
return try {
|
||||
callback.decryptSessionKey(subkeyIdentifier.subkeyId, keyAlgorithm, secKeyData[0])
|
||||
callback.decryptSessionKey(
|
||||
subkeyIdentifier.subkeyId, keyAlgorithm, secKeyData[0], pkeskVersion)
|
||||
} catch (e: HardwareSecurityException) {
|
||||
throw PGPException("Hardware-backed decryption failed.", e)
|
||||
}
|
||||
|
|
|
@ -55,14 +55,14 @@ public class CustomPublicKeyDataDecryptorFactoryTest {
|
|||
|
||||
HardwareSecurity.DecryptionCallback hardwareDecryptionCallback = new HardwareSecurity.DecryptionCallback() {
|
||||
@Override
|
||||
public byte[] decryptSessionKey(long keyId, int keyAlgorithm, byte[] sessionKeyData)
|
||||
public byte[] decryptSessionKey(long keyId, int keyAlgorithm, byte[] sessionKeyData, int pkeskVersion)
|
||||
throws HardwareSecurity.HardwareSecurityException {
|
||||
// Emulate hardware decryption.
|
||||
try {
|
||||
PGPSecretKey decryptionKey = secretKey.getSecretKey(encryptionKey.getKeyID());
|
||||
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(decryptionKey, Passphrase.emptyPassphrase());
|
||||
PublicKeyDataDecryptorFactory internal = new BcPublicKeyDataDecryptorFactory(privateKey);
|
||||
return internal.recoverSessionData(keyAlgorithm, new byte[][] {sessionKeyData});
|
||||
return internal.recoverSessionData(keyAlgorithm, new byte[][] {sessionKeyData}, pkeskVersion);
|
||||
} catch (PGPException e) {
|
||||
throw new HardwareSecurity.HardwareSecurityException();
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ allprojects {
|
|||
isSnapshot = true
|
||||
pgpainlessMinAndroidSdk = 10
|
||||
javaSourceCompatibility = 1.8
|
||||
bouncyCastleVersion = '1.78.1'
|
||||
bouncyCastleVersion = '1.80'
|
||||
bouncyPgVersion = bouncyCastleVersion
|
||||
junitVersion = '5.8.2'
|
||||
logbackVersion = '1.5.13'
|
||||
|
|
Loading…
Add table
Reference in a new issue