1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-11-05 20:15:59 +01:00

Identify custom decryptor factories by subkey id

This commit is contained in:
Paul Schaub 2022-10-20 16:07:31 +02:00
parent 02c68460a9
commit a60917549d
5 changed files with 22 additions and 12 deletions

View file

@ -25,6 +25,7 @@ import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
import org.pgpainless.decryption_verification.cleartext_signatures.InMemoryMultiPassStrategy;
import org.pgpainless.decryption_verification.cleartext_signatures.MultiPassStrategy;
import org.pgpainless.key.SubkeyIdentifier;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.signature.SignatureUtils;
import org.pgpainless.util.Passphrase;
@ -49,7 +50,7 @@ public class ConsumerOptions {
// Session key for decryption without passphrase/key
private SessionKey sessionKey = null;
private final Map<Long, PublicKeyDataDecryptorFactory> customPublicKeyDataDecryptorFactories = new HashMap<>();
private final Map<SubkeyIdentifier, PublicKeyDataDecryptorFactory> customPublicKeyDataDecryptorFactories = new HashMap<>();
private final Map<PGPSecretKeyRing, SecretKeyRingProtector> decryptionKeys = new HashMap<>();
private final Set<Passphrase> decryptionPassphrases = new HashSet<>();
@ -249,11 +250,11 @@ public class ConsumerOptions {
* @return options
*/
public ConsumerOptions addCustomDecryptorFactory(@Nonnull CustomPublicKeyDataDecryptorFactory factory) {
this.customPublicKeyDataDecryptorFactories.put(factory.getKeyId(), factory);
this.customPublicKeyDataDecryptorFactories.put(factory.getSubkeyIdentifier(), factory);
return this;
}
Map<Long, PublicKeyDataDecryptorFactory> getCustomDecryptorFactories() {
Map<SubkeyIdentifier, PublicKeyDataDecryptorFactory> getCustomDecryptorFactories() {
return new HashMap<>(customPublicKeyDataDecryptorFactories);
}

View file

@ -5,9 +5,10 @@
package org.pgpainless.decryption_verification;
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
import org.pgpainless.key.SubkeyIdentifier;
public interface CustomPublicKeyDataDecryptorFactory extends PublicKeyDataDecryptorFactory {
long getKeyId();
SubkeyIdentifier getSubkeyIdentifier();
}

View file

@ -409,7 +409,7 @@ public final class DecryptionStreamFactory {
}
// Try custom PublicKeyDataDecryptorFactories (e.g. hardware-backed).
Map<Long, PublicKeyDataDecryptorFactory> customFactories = options.getCustomDecryptorFactories();
Map<SubkeyIdentifier, PublicKeyDataDecryptorFactory> customFactories = options.getCustomDecryptorFactories();
for (PGPPublicKeyEncryptedData publicKeyEncryptedData : publicKeyProtected) {
Long keyId = publicKeyEncryptedData.getKeyID();
if (!customFactories.containsKey(keyId)) {

View file

@ -11,6 +11,7 @@ import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.operator.PGPDataDecryptor;
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory;
import org.pgpainless.key.SubkeyIdentifier;
import java.util.HashSet;
import java.util.Set;
@ -74,16 +75,16 @@ public class HardwareSecurity {
// luckily we can instantiate the BcPublicKeyDataDecryptorFactory with null as argument.
private final PublicKeyDataDecryptorFactory factory =
new BcPublicKeyDataDecryptorFactory(null);
private long keyId;
private SubkeyIdentifier subkey;
/**
* Create a new {@link HardwareDataDecryptorFactory}.
*
* @param callback decryption callback
*/
public HardwareDataDecryptorFactory(long keyId, DecryptionCallback callback) {
public HardwareDataDecryptorFactory(SubkeyIdentifier subkeyIdentifier, DecryptionCallback callback) {
this.callback = callback;
this.keyId = keyId;
this.subkey = subkeyIdentifier;
}
@Override
@ -91,7 +92,7 @@ public class HardwareSecurity {
throws PGPException {
try {
// delegate decryption to the callback
return callback.decryptSessionKey(keyId, keyAlgorithm, secKeyData[0]);
return callback.decryptSessionKey(subkey.getSubkeyId(), keyAlgorithm, secKeyData[0]);
} catch (HardwareSecurityException e) {
throw new PGPException("Hardware-backed decryption failed.", e);
}
@ -104,8 +105,14 @@ public class HardwareSecurity {
}
@Override
public long getKeyId() {
return keyId;
public PGPDataDecryptor createDataDecryptor(int aeadAlgorithm, byte[] iv, int chunkSize, int encAlgorithm, byte[] key)
throws PGPException {
return factory.createDataDecryptor(aeadAlgorithm, iv, chunkSize, encAlgorithm, key);
}
@Override
public SubkeyIdentifier getSubkeyIdentifier() {
return subkey;
}
}

View file

@ -19,6 +19,7 @@ import org.pgpainless.algorithm.EncryptionPurpose;
import org.pgpainless.encryption_signing.EncryptionOptions;
import org.pgpainless.encryption_signing.EncryptionStream;
import org.pgpainless.encryption_signing.ProducerOptions;
import org.pgpainless.key.SubkeyIdentifier;
import org.pgpainless.key.info.KeyRingInfo;
import org.pgpainless.key.protection.UnlockSecretKey;
import org.pgpainless.util.Passphrase;
@ -74,7 +75,7 @@ public class CustomPublicKeyDataDecryptorFactoryTest {
.withOptions(ConsumerOptions.get()
.addCustomDecryptorFactory(
new HardwareSecurity.HardwareDataDecryptorFactory(
encryptionKey.getKeyID(),
new SubkeyIdentifier(cert, encryptionKey.getKeyID()),
hardwareDecryptionCallback)));
ByteArrayOutputStream decryptedOut = new ByteArrayOutputStream();