mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-25 12:27:58 +01:00
Identify custom decryptor factories by subkey id
This commit is contained in:
parent
2fdfdfa63e
commit
344ad1c982
5 changed files with 22 additions and 12 deletions
|
@ -25,6 +25,7 @@ import org.bouncycastle.openpgp.PGPSignature;
|
||||||
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
|
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
|
||||||
import org.pgpainless.decryption_verification.cleartext_signatures.InMemoryMultiPassStrategy;
|
import org.pgpainless.decryption_verification.cleartext_signatures.InMemoryMultiPassStrategy;
|
||||||
import org.pgpainless.decryption_verification.cleartext_signatures.MultiPassStrategy;
|
import org.pgpainless.decryption_verification.cleartext_signatures.MultiPassStrategy;
|
||||||
|
import org.pgpainless.key.SubkeyIdentifier;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.signature.SignatureUtils;
|
import org.pgpainless.signature.SignatureUtils;
|
||||||
import org.pgpainless.util.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
|
@ -49,7 +50,7 @@ public class ConsumerOptions {
|
||||||
|
|
||||||
// Session key for decryption without passphrase/key
|
// Session key for decryption without passphrase/key
|
||||||
private SessionKey sessionKey = null;
|
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 Map<PGPSecretKeyRing, SecretKeyRingProtector> decryptionKeys = new HashMap<>();
|
||||||
private final Set<Passphrase> decryptionPassphrases = new HashSet<>();
|
private final Set<Passphrase> decryptionPassphrases = new HashSet<>();
|
||||||
|
@ -249,11 +250,11 @@ public class ConsumerOptions {
|
||||||
* @return options
|
* @return options
|
||||||
*/
|
*/
|
||||||
public ConsumerOptions addCustomDecryptorFactory(@Nonnull CustomPublicKeyDataDecryptorFactory factory) {
|
public ConsumerOptions addCustomDecryptorFactory(@Nonnull CustomPublicKeyDataDecryptorFactory factory) {
|
||||||
this.customPublicKeyDataDecryptorFactories.put(factory.getKeyId(), factory);
|
this.customPublicKeyDataDecryptorFactories.put(factory.getSubkeyIdentifier(), factory);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Long, PublicKeyDataDecryptorFactory> getCustomDecryptorFactories() {
|
Map<SubkeyIdentifier, PublicKeyDataDecryptorFactory> getCustomDecryptorFactories() {
|
||||||
return new HashMap<>(customPublicKeyDataDecryptorFactories);
|
return new HashMap<>(customPublicKeyDataDecryptorFactories);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
package org.pgpainless.decryption_verification;
|
package org.pgpainless.decryption_verification;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
|
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
|
||||||
|
import org.pgpainless.key.SubkeyIdentifier;
|
||||||
|
|
||||||
public interface CustomPublicKeyDataDecryptorFactory extends PublicKeyDataDecryptorFactory {
|
public interface CustomPublicKeyDataDecryptorFactory extends PublicKeyDataDecryptorFactory {
|
||||||
|
|
||||||
long getKeyId();
|
SubkeyIdentifier getSubkeyIdentifier();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -409,7 +409,7 @@ public final class DecryptionStreamFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try custom PublicKeyDataDecryptorFactories (e.g. hardware-backed).
|
// Try custom PublicKeyDataDecryptorFactories (e.g. hardware-backed).
|
||||||
Map<Long, PublicKeyDataDecryptorFactory> customFactories = options.getCustomDecryptorFactories();
|
Map<SubkeyIdentifier, PublicKeyDataDecryptorFactory> customFactories = options.getCustomDecryptorFactories();
|
||||||
for (PGPPublicKeyEncryptedData publicKeyEncryptedData : publicKeyProtected) {
|
for (PGPPublicKeyEncryptedData publicKeyEncryptedData : publicKeyProtected) {
|
||||||
Long keyId = publicKeyEncryptedData.getKeyID();
|
Long keyId = publicKeyEncryptedData.getKeyID();
|
||||||
if (!customFactories.containsKey(keyId)) {
|
if (!customFactories.containsKey(keyId)) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.bouncycastle.openpgp.operator.PGPDataDecryptor;
|
import org.bouncycastle.openpgp.operator.PGPDataDecryptor;
|
||||||
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
|
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
|
||||||
import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory;
|
import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory;
|
||||||
|
import org.pgpainless.key.SubkeyIdentifier;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -74,16 +75,16 @@ public class HardwareSecurity {
|
||||||
// luckily we can instantiate the BcPublicKeyDataDecryptorFactory with null as argument.
|
// luckily we can instantiate the BcPublicKeyDataDecryptorFactory with null as argument.
|
||||||
private final PublicKeyDataDecryptorFactory factory =
|
private final PublicKeyDataDecryptorFactory factory =
|
||||||
new BcPublicKeyDataDecryptorFactory(null);
|
new BcPublicKeyDataDecryptorFactory(null);
|
||||||
private long keyId;
|
private SubkeyIdentifier subkey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link HardwareDataDecryptorFactory}.
|
* Create a new {@link HardwareDataDecryptorFactory}.
|
||||||
*
|
*
|
||||||
* @param callback decryption callback
|
* @param callback decryption callback
|
||||||
*/
|
*/
|
||||||
public HardwareDataDecryptorFactory(long keyId, DecryptionCallback callback) {
|
public HardwareDataDecryptorFactory(SubkeyIdentifier subkeyIdentifier, DecryptionCallback callback) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.keyId = keyId;
|
this.subkey = subkeyIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -91,7 +92,7 @@ public class HardwareSecurity {
|
||||||
throws PGPException {
|
throws PGPException {
|
||||||
try {
|
try {
|
||||||
// delegate decryption to the callback
|
// delegate decryption to the callback
|
||||||
return callback.decryptSessionKey(keyId, keyAlgorithm, secKeyData[0]);
|
return callback.decryptSessionKey(subkey.getSubkeyId(), keyAlgorithm, secKeyData[0]);
|
||||||
} catch (HardwareSecurityException e) {
|
} catch (HardwareSecurityException e) {
|
||||||
throw new PGPException("Hardware-backed decryption failed.", e);
|
throw new PGPException("Hardware-backed decryption failed.", e);
|
||||||
}
|
}
|
||||||
|
@ -104,8 +105,14 @@ public class HardwareSecurity {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getKeyId() {
|
public PGPDataDecryptor createDataDecryptor(int aeadAlgorithm, byte[] iv, int chunkSize, int encAlgorithm, byte[] key)
|
||||||
return keyId;
|
throws PGPException {
|
||||||
|
return factory.createDataDecryptor(aeadAlgorithm, iv, chunkSize, encAlgorithm, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubkeyIdentifier getSubkeyIdentifier() {
|
||||||
|
return subkey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.pgpainless.algorithm.EncryptionPurpose;
|
||||||
import org.pgpainless.encryption_signing.EncryptionOptions;
|
import org.pgpainless.encryption_signing.EncryptionOptions;
|
||||||
import org.pgpainless.encryption_signing.EncryptionStream;
|
import org.pgpainless.encryption_signing.EncryptionStream;
|
||||||
import org.pgpainless.encryption_signing.ProducerOptions;
|
import org.pgpainless.encryption_signing.ProducerOptions;
|
||||||
|
import org.pgpainless.key.SubkeyIdentifier;
|
||||||
import org.pgpainless.key.info.KeyRingInfo;
|
import org.pgpainless.key.info.KeyRingInfo;
|
||||||
import org.pgpainless.key.protection.UnlockSecretKey;
|
import org.pgpainless.key.protection.UnlockSecretKey;
|
||||||
import org.pgpainless.util.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
|
@ -74,7 +75,7 @@ public class CustomPublicKeyDataDecryptorFactoryTest {
|
||||||
.withOptions(ConsumerOptions.get()
|
.withOptions(ConsumerOptions.get()
|
||||||
.addCustomDecryptorFactory(
|
.addCustomDecryptorFactory(
|
||||||
new HardwareSecurity.HardwareDataDecryptorFactory(
|
new HardwareSecurity.HardwareDataDecryptorFactory(
|
||||||
encryptionKey.getKeyID(),
|
new SubkeyIdentifier(cert, encryptionKey.getKeyID()),
|
||||||
hardwareDecryptionCallback)));
|
hardwareDecryptionCallback)));
|
||||||
|
|
||||||
ByteArrayOutputStream decryptedOut = new ByteArrayOutputStream();
|
ByteArrayOutputStream decryptedOut = new ByteArrayOutputStream();
|
||||||
|
|
Loading…
Reference in a new issue