1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-12-09 22:01:10 +01:00

Add support for decryption with hidden recipients

This commit is contained in:
Paul Schaub 2021-01-09 16:16:17 +01:00
parent 9333fa2b65
commit 63bf5a8e69
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
2 changed files with 97 additions and 11 deletions

View file

@ -33,6 +33,7 @@ import org.bouncycastle.openpgp.PGPCompressedData;
import org.bouncycastle.openpgp.PGPEncryptedData;
import org.bouncycastle.openpgp.PGPEncryptedDataList;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPKeyValidationException;
import org.bouncycastle.openpgp.PGPLiteralData;
import org.bouncycastle.openpgp.PGPObjectFactory;
import org.bouncycastle.openpgp.PGPOnePassSignature;
@ -43,6 +44,7 @@ import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPUtil;
@ -208,18 +210,38 @@ public final class DecryptionStreamFactory {
} else if (encryptedData instanceof PGPPublicKeyEncryptedData) {
PGPPublicKeyEncryptedData publicKeyEncryptedData = (PGPPublicKeyEncryptedData) encryptedData;
long keyId = publicKeyEncryptedData.getKeyID();
resultBuilder.addRecipientKeyId(keyId);
LOGGER.log(LEVEL, "PGPEncryptedData is encrypted for key " + Long.toHexString(keyId));
if (decryptionKeys != null) {
PGPSecretKey secretKey = decryptionKeys.getSecretKey(keyId);
if (secretKey != null) {
LOGGER.log(LEVEL, "Found respective secret key " + Long.toHexString(keyId));
// Watch out! This assignment is possibly done multiple times.
encryptedSessionKey = publicKeyEncryptedData;
decryptionKey = secretKey.extractPrivateKey(decryptionKeyDecryptor.getDecryptor(keyId));
resultBuilder.setDecryptionFingerprint(new OpenPgpV4Fingerprint(secretKey));
// Known key id
if (keyId != 0) {
LOGGER.log(LEVEL, "PGPEncryptedData is encrypted for key " + Long.toHexString(keyId));
resultBuilder.addRecipientKeyId(keyId);
PGPSecretKey secretKey = decryptionKeys.getSecretKey(keyId);
if (secretKey != null) {
LOGGER.log(LEVEL, "Found respective secret key " + Long.toHexString(keyId));
// Watch out! This assignment is possibly done multiple times.
encryptedSessionKey = publicKeyEncryptedData;
decryptionKey = secretKey.extractPrivateKey(decryptionKeyDecryptor.getDecryptor(keyId));
resultBuilder.setDecryptionFingerprint(new OpenPgpV4Fingerprint(secretKey));
}
} else {
// Hidden recipient
LOGGER.log(LEVEL, "Hidden recipient detected. Try to decrypt with all available secret keys.");
outerloop: for (PGPSecretKeyRing ring : decryptionKeys) {
for (PGPSecretKey key : ring) {
PGPPrivateKey privateKey = key.extractPrivateKey(decryptionKeyDecryptor.getDecryptor(key.getKeyID()));
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance().getPublicKeyDataDecryptorFactory(privateKey);
try {
publicKeyEncryptedData.getSymmetricAlgorithm(decryptorFactory); // will only succeed if we have the right secret key
LOGGER.log(LEVEL, "Found correct key " + Long.toHexString(key.getKeyID()) + " for hidden recipient decryption.");
decryptionKey = privateKey;
resultBuilder.setDecryptionFingerprint(new OpenPgpV4Fingerprint(key));
encryptedSessionKey = publicKeyEncryptedData;
break outerloop;
} catch (ClassCastException | PGPKeyValidationException e) {
LOGGER.log(LEVEL, "Skipping wrong key " + Long.toHexString(key.getKeyID()) + " for hidden recipient decryption.", e);
}
}
}
}
}
}