From de67461fb2fe590759e005f84cd254c2d3516750 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Mon, 17 Oct 2022 02:47:11 +0200 Subject: [PATCH] Fix NPEs and expose decryption keys --- .../MessageMetadata.java | 20 +++++++++++++ .../OpenPgpMessageInputStream.java | 30 ++++++++++++------- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/MessageMetadata.java b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/MessageMetadata.java index 2cd2a6f2..1be47112 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/MessageMetadata.java +++ b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/MessageMetadata.java @@ -7,6 +7,7 @@ package org.pgpainless.decryption_verification; import org.pgpainless.algorithm.CompressionAlgorithm; import org.pgpainless.algorithm.StreamEncoding; import org.pgpainless.algorithm.SymmetricKeyAlgorithm; +import org.pgpainless.key.SubkeyIdentifier; import org.pgpainless.util.SessionKey; import javax.annotation.Nonnull; @@ -182,6 +183,24 @@ public class MessageMetadata { return (LiteralData) nested; } + public SubkeyIdentifier getDecryptionKey() { + Iterator iterator = new LayerIterator(message) { + @Override + public boolean matches(Nested layer) { + return layer instanceof EncryptedData; + } + + @Override + public SubkeyIdentifier getProperty(Layer last) { + return ((EncryptedData) last).decryptionKey; + } + }; + if (iterator.hasNext()) { + return iterator.next(); + } + return null; + } + public abstract static class Layer { protected final List verifiedDetachedSignatures = new ArrayList<>(); protected final List rejectedDetachedSignatures = new ArrayList<>(); @@ -309,6 +328,7 @@ public class MessageMetadata { public static class EncryptedData extends Layer implements Nested { protected final SymmetricKeyAlgorithm algorithm; + protected SubkeyIdentifier decryptionKey; protected SessionKey sessionKey; protected List recipients; diff --git a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/OpenPgpMessageInputStream.java b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/OpenPgpMessageInputStream.java index 37ccff37..944ce6e4 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/OpenPgpMessageInputStream.java +++ b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/OpenPgpMessageInputStream.java @@ -334,6 +334,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream { MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData( SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory))); + encryptedData.decryptionKey = new SubkeyIdentifier(decryptionKeys, decryptionKey.getKeyID()); encryptedData.sessionKey = sessionKey; IntegrityProtectedInputStream integrityProtected = new IntegrityProtectedInputStream(decrypted, pkesk, options); @@ -361,6 +362,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream { MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData( SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory))); + encryptedData.decryptionKey = new SubkeyIdentifier(decryptionKeyCandidate.getA(), privateKey.getKeyID()); encryptedData.sessionKey = sessionKey; IntegrityProtectedInputStream integrityProtected = new IntegrityProtectedInputStream(decrypted, pkesk, options); @@ -560,8 +562,6 @@ public class OpenPgpMessageInputStream extends DecryptionStream { final List correspondingSignatures; boolean isLiteral = true; - final List verified = new ArrayList<>(); - private Signatures(ConsumerOptions options) { this.options = options; this.detachedSignatures = new ArrayList<>(); @@ -580,24 +580,33 @@ public class OpenPgpMessageInputStream extends DecryptionStream { void addDetachedSignature(PGPSignature signature) { long keyId = SignatureUtils.determineIssuerKeyId(signature); PGPPublicKeyRing certificate = findCertificate(keyId); - initialize(signature, certificate, keyId); - this.detachedSignatures.add(new DetachedOrPrependedSignature(signature, certificate, keyId)); + + if (certificate != null) { + initialize(signature, certificate, keyId); + this.detachedSignatures.add(new DetachedOrPrependedSignature(signature, certificate, keyId)); + } } void addPrependedSignature(PGPSignature signature) { long keyId = SignatureUtils.determineIssuerKeyId(signature); PGPPublicKeyRing certificate = findCertificate(keyId); - initialize(signature, certificate, keyId); - this.prependedSignatures.add(new DetachedOrPrependedSignature(signature, certificate, keyId)); + + if (certificate != null) { + initialize(signature, certificate, keyId); + this.prependedSignatures.add(new DetachedOrPrependedSignature(signature, certificate, keyId)); + } } void addOnePassSignature(PGPOnePassSignature signature) { PGPPublicKeyRing certificate = findCertificate(signature.getKeyID()); - OnePassSignature ops = new OnePassSignature(signature, certificate, signature.getKeyID()); - ops.init(certificate); - onePassSignatures.add(ops); - literalOPS.add(ops); + if (certificate != null) { + OnePassSignature ops = new OnePassSignature(signature, certificate, signature.getKeyID()); + ops.init(certificate); + onePassSignatures.add(ops); + + literalOPS.add(ops); + } if (signature.isContaining()) { enterNesting(); } @@ -898,6 +907,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream { resultBuilder.setFileName(m.getFilename()); resultBuilder.setFileEncoding(m.getFormat()); resultBuilder.setSessionKey(m.getSessionKey()); + resultBuilder.setDecryptionKey(m.getDecryptionKey()); for (SignatureVerification accepted : m.getVerifiedDetachedSignatures()) { resultBuilder.addVerifiedDetachedSignature(accepted);