diff --git a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/ConsumerOptions.java b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/ConsumerOptions.java index b6117a60..d57eff48 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/ConsumerOptions.java +++ b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/ConsumerOptions.java @@ -48,6 +48,7 @@ public class ConsumerOptions { // Session key for decryption without passphrase/key private SessionKey sessionKey = null; + private HardwareSecurity.DecryptionCallback hardwareDecryptionCallback = null; private final Map decryptionKeys = new HashMap<>(); private final Set decryptionPassphrases = new HashSet<>(); @@ -238,6 +239,11 @@ public class ConsumerOptions { return this; } + public ConsumerOptions setHardwareDecryptionCallback(HardwareSecurity.DecryptionCallback callback) { + this.hardwareDecryptionCallback = callback; + return this; + } + public @Nonnull Set getDecryptionKeys() { return Collections.unmodifiableSet(decryptionKeys.keySet()); } diff --git a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/HardwareSecurity.java b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/HardwareSecurity.java new file mode 100644 index 00000000..bea14aef --- /dev/null +++ b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/HardwareSecurity.java @@ -0,0 +1,27 @@ +package org.pgpainless.decryption_verification; + +import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData; +import org.pgpainless.util.SessionKey; + +public class HardwareSecurity { + + public interface DecryptionCallback { + + /** + * 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 {@link HardwareSecurityException} is thrown. + * + * @param pkesk public-key-encrypted session key + * @return decrypted session key + * @throws HardwareSecurityException exception + */ + SessionKey decryptSessionKey(PGPPublicKeyEncryptedData pkesk) throws HardwareSecurityException; + + } + + public static class HardwareSecurityException extends Exception { + + } +} diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/HardwareSecurityCallbackTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/HardwareSecurityCallbackTest.java new file mode 100644 index 00000000..d731277e --- /dev/null +++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/HardwareSecurityCallbackTest.java @@ -0,0 +1,39 @@ +package org.pgpainless.decryption_verification; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData; +import org.junit.jupiter.api.Test; +import org.pgpainless.PGPainless; +import org.pgpainless.util.SessionKey; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +public class HardwareSecurityCallbackTest { + + @Test + public void test() throws PGPException, IOException { + PGPainless.decryptAndOrVerify() + .onInputStream(new ByteArrayInputStream(new byte[0])) + .withOptions(ConsumerOptions.get() + .setHardwareDecryptionCallback(new HardwareSecurity.DecryptionCallback() { + @Override + public SessionKey decryptSessionKey(PGPPublicKeyEncryptedData pkesk) throws HardwareSecurity.HardwareSecurityException { + /* + pkesk.getSessionKey(new PublicKeyDataDecryptorFactory() { + @Override + public byte[] recoverSessionData(int keyAlgorithm, byte[][] secKeyData) throws PGPException { + return new byte[0]; + } + + @Override + public PGPDataDecryptor createDataDecryptor(boolean withIntegrityPacket, int encAlgorithm, byte[] key) throws PGPException { + return null; + } + }); + */ + return null; + } + })); + } +}