From 8819ba0201c0fa307ab994098fea4e0072f083de Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Tue, 8 Apr 2025 13:21:11 +0200 Subject: [PATCH] HardwareSecurity: Replace usage of Long KeyId with KeyIdentifier --- .../HardwareSecurity.kt | 27 ++++++++++++++++++- ...stomPublicKeyDataDecryptorFactoryTest.java | 5 ++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/HardwareSecurity.kt b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/HardwareSecurity.kt index 50ef3e02..b6e2bd17 100644 --- a/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/HardwareSecurity.kt +++ b/pgpainless-core/src/main/kotlin/org/pgpainless/decryption_verification/HardwareSecurity.kt @@ -6,6 +6,7 @@ package org.pgpainless.decryption_verification import kotlin.jvm.Throws import org.bouncycastle.bcpg.AEADEncDataPacket +import org.bouncycastle.bcpg.KeyIdentifier import org.bouncycastle.bcpg.SymmetricEncIntegrityPacket import org.bouncycastle.openpgp.PGPException import org.bouncycastle.openpgp.PGPSessionKey @@ -33,12 +34,36 @@ class HardwareSecurity { * @return decrypted session key * @throws HardwareSecurityException exception */ + @Deprecated("Pass in a KeyIdentifier instead of a Long keyId.") @Throws(HardwareSecurityException::class) fun decryptSessionKey( keyId: Long, keyAlgorithm: Int, sessionKeyData: ByteArray, pkeskVersion: Int + ): ByteArray = + decryptSessionKey(KeyIdentifier(keyId), keyAlgorithm, sessionKeyData, pkeskVersion) + + /** + * Delegate decryption of a Public-Key-Encrypted-Session-Key (PKESK) to an external API for + * dealing with hardware security modules such as smartcards or TPMs. + * + * If decryption fails for some reason, a subclass of the [HardwareSecurityException] is + * thrown. + * + * @param keyIdentifier identifier of the encryption component 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( + keyIdentifier: KeyIdentifier, + keyAlgorithm: Int, + sessionKeyData: ByteArray, + pkeskVersion: Int ): ByteArray } @@ -84,7 +109,7 @@ class HardwareSecurity { ): ByteArray { return try { callback.decryptSessionKey( - subkeyIdentifier.subkeyId, keyAlgorithm, secKeyData[0], pkeskVersion) + subkeyIdentifier.keyIdentifier, keyAlgorithm, secKeyData[0], pkeskVersion) } catch (e: HardwareSecurityException) { throw PGPException("Hardware-backed decryption failed.", e) } diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/CustomPublicKeyDataDecryptorFactoryTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/CustomPublicKeyDataDecryptorFactoryTest.java index 947b6980..9ce1f5d6 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/CustomPublicKeyDataDecryptorFactoryTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/CustomPublicKeyDataDecryptorFactoryTest.java @@ -4,6 +4,7 @@ package org.pgpainless.decryption_verification; +import org.bouncycastle.bcpg.KeyIdentifier; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.api.OpenPGPCertificate; import org.bouncycastle.openpgp.api.OpenPGPKey; @@ -52,11 +53,11 @@ public class CustomPublicKeyDataDecryptorFactoryTest { HardwareSecurity.DecryptionCallback hardwareDecryptionCallback = new HardwareSecurity.DecryptionCallback() { @Override - public byte[] decryptSessionKey(long keyId, int keyAlgorithm, byte[] sessionKeyData, int pkeskVersion) + public byte[] decryptSessionKey(KeyIdentifier keyIdentifier, int keyAlgorithm, byte[] sessionKeyData, int pkeskVersion) throws HardwareSecurity.HardwareSecurityException { // Emulate hardware decryption. try { - OpenPGPKey.OpenPGPSecretKey decryptionKey = secretKey.getSecretKey(encryptionKey.getKeyIdentifier()); + OpenPGPKey.OpenPGPSecretKey decryptionKey = secretKey.getSecretKey(keyIdentifier); OpenPGPKey.OpenPGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(decryptionKey, Passphrase.emptyPassphrase()); PublicKeyDataDecryptorFactory internal = new BcPublicKeyDataDecryptorFactory(privateKey.getKeyPair().getPrivateKey()); return internal.recoverSessionData(keyAlgorithm, new byte[][] {sessionKeyData}, pkeskVersion);