1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-11-26 22:32:07 +01:00

Add OpenPgpMetadata.isCleartextSigned and use it in sop to determine if message was cleartext signed

This commit is contained in:
Paul Schaub 2022-06-19 17:31:48 +02:00
parent 5375cd454f
commit 75455f1a3c
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
8 changed files with 88 additions and 54 deletions

View file

@ -155,6 +155,7 @@ public final class DecryptionStreamFactory {
if (openPgpIn.isAsciiArmored()) { if (openPgpIn.isAsciiArmored()) {
ArmoredInputStream armoredInputStream = ArmoredInputStreamFactory.get(openPgpIn); ArmoredInputStream armoredInputStream = ArmoredInputStreamFactory.get(openPgpIn);
if (armoredInputStream.isClearText()) { if (armoredInputStream.isClearText()) {
resultBuilder.setCleartextSigned();
return parseCleartextSignedMessage(armoredInputStream); return parseCleartextSignedMessage(armoredInputStream);
} else { } else {
outerDecodingStream = armoredInputStream; outerDecodingStream = armoredInputStream;

View file

@ -40,6 +40,7 @@ public class OpenPgpMetadata {
private final String fileName; private final String fileName;
private final Date modificationDate; private final Date modificationDate;
private final StreamEncoding fileEncoding; private final StreamEncoding fileEncoding;
private final boolean cleartextSigned;
public OpenPgpMetadata(Set<Long> recipientKeyIds, public OpenPgpMetadata(Set<Long> recipientKeyIds,
SubkeyIdentifier decryptionKey, SubkeyIdentifier decryptionKey,
@ -51,7 +52,8 @@ public class OpenPgpMetadata {
List<SignatureVerification.Failure> invalidDetachedSignatures, List<SignatureVerification.Failure> invalidDetachedSignatures,
String fileName, String fileName,
Date modificationDate, Date modificationDate,
StreamEncoding fileEncoding) { StreamEncoding fileEncoding,
boolean cleartextSigned) {
this.recipientKeyIds = Collections.unmodifiableSet(recipientKeyIds); this.recipientKeyIds = Collections.unmodifiableSet(recipientKeyIds);
this.decryptionKey = decryptionKey; this.decryptionKey = decryptionKey;
@ -64,6 +66,7 @@ public class OpenPgpMetadata {
this.fileName = fileName; this.fileName = fileName;
this.modificationDate = modificationDate; this.modificationDate = modificationDate;
this.fileEncoding = fileEncoding; this.fileEncoding = fileEncoding;
this.cleartextSigned = cleartextSigned;
} }
/** /**
@ -269,6 +272,15 @@ public class OpenPgpMetadata {
return fileEncoding; return fileEncoding;
} }
/**
* Return true if the message was signed using the cleartext signature framework.
*
* @return true if cleartext signed.
*/
public boolean isCleartextSigned() {
return cleartextSigned;
}
public static Builder getBuilder() { public static Builder getBuilder() {
return new Builder(); return new Builder();
} }
@ -282,6 +294,7 @@ public class OpenPgpMetadata {
private String fileName; private String fileName;
private StreamEncoding fileEncoding; private StreamEncoding fileEncoding;
private Date modificationDate; private Date modificationDate;
private boolean cleartextSigned = false;
private final List<SignatureVerification> verifiedInbandSignatures = new ArrayList<>(); private final List<SignatureVerification> verifiedInbandSignatures = new ArrayList<>();
private final List<SignatureVerification> verifiedDetachedSignatures = new ArrayList<>(); private final List<SignatureVerification> verifiedDetachedSignatures = new ArrayList<>();
@ -324,29 +337,38 @@ public class OpenPgpMetadata {
return this; return this;
} }
public Builder addVerifiedInbandSignature(SignatureVerification signatureVerification) {
this.verifiedInbandSignatures.add(signatureVerification);
return this;
}
public Builder addVerifiedDetachedSignature(SignatureVerification signatureVerification) {
this.verifiedDetachedSignatures.add(signatureVerification);
return this;
}
public Builder addInvalidInbandSignature(SignatureVerification signatureVerification, SignatureValidationException e) {
this.invalidInbandSignatures.add(new SignatureVerification.Failure(signatureVerification, e));
return this;
}
public Builder addInvalidDetachedSignature(SignatureVerification signatureVerification, SignatureValidationException e) {
this.invalidDetachedSignatures.add(new SignatureVerification.Failure(signatureVerification, e));
return this;
}
public Builder setCleartextSigned() {
this.cleartextSigned = true;
return this;
}
public OpenPgpMetadata build() { public OpenPgpMetadata build() {
return new OpenPgpMetadata( return new OpenPgpMetadata(
recipientFingerprints, decryptionKey, recipientFingerprints, decryptionKey,
sessionKey, compressionAlgorithm, sessionKey, compressionAlgorithm,
verifiedInbandSignatures, invalidInbandSignatures, verifiedInbandSignatures, invalidInbandSignatures,
verifiedDetachedSignatures, invalidDetachedSignatures, verifiedDetachedSignatures, invalidDetachedSignatures,
fileName, modificationDate, fileEncoding); fileName, modificationDate, fileEncoding, cleartextSigned);
}
public void addVerifiedInbandSignature(SignatureVerification signatureVerification) {
this.verifiedInbandSignatures.add(signatureVerification);
}
public void addVerifiedDetachedSignature(SignatureVerification signatureVerification) {
this.verifiedDetachedSignatures.add(signatureVerification);
}
public void addInvalidInbandSignature(SignatureVerification signatureVerification, SignatureValidationException e) {
this.invalidInbandSignatures.add(new SignatureVerification.Failure(signatureVerification, e));
}
public void addInvalidDetachedSignature(SignatureVerification signatureVerification, SignatureValidationException e) {
this.invalidDetachedSignatures.add(new SignatureVerification.Failure(signatureVerification, e));
} }
} }
} }

View file

@ -94,6 +94,7 @@ public class CleartextSignatureVerificationTest {
OpenPgpMetadata result = decryptionStream.getResult(); OpenPgpMetadata result = decryptionStream.getResult();
assertTrue(result.isVerified()); assertTrue(result.isVerified());
assertTrue(result.isCleartextSigned());
PGPSignature signature = result.getVerifiedSignatures().values().iterator().next(); PGPSignature signature = result.getVerifiedSignatures().values().iterator().next();

View file

@ -6,6 +6,7 @@ package org.pgpainless.decryption_verification;
import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -68,6 +69,7 @@ public class DecryptAndVerifyMessageTest {
assertTrue(metadata.isEncrypted()); assertTrue(metadata.isEncrypted());
assertTrue(metadata.isSigned()); assertTrue(metadata.isSigned());
assertFalse(metadata.isCleartextSigned());
assertTrue(metadata.isVerified()); assertTrue(metadata.isVerified());
assertEquals(CompressionAlgorithm.ZLIB, metadata.getCompressionAlgorithm()); assertEquals(CompressionAlgorithm.ZLIB, metadata.getCompressionAlgorithm());
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getSymmetricKeyAlgorithm()); assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getSymmetricKeyAlgorithm());

View file

@ -41,6 +41,7 @@ public class SignedMessageVerificationWithoutCertIsStillSigned {
OpenPgpMetadata metadata = verificationStream.getResult(); OpenPgpMetadata metadata = verificationStream.getResult();
assertFalse(metadata.isCleartextSigned());
assertTrue(metadata.isSigned(), "Message is signed, even though we miss the verification cert."); assertTrue(metadata.isSigned(), "Message is signed, even though we miss the verification cert.");
assertFalse(metadata.isVerified(), "Message is not verified because we lack the verification cert."); assertFalse(metadata.isVerified(), "Message is not verified because we lack the verification cert.");
} }

View file

@ -16,16 +16,15 @@ import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.util.io.Streams; import org.bouncycastle.util.io.Streams;
import org.pgpainless.PGPainless; import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm; import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.decryption_verification.ConsumerOptions; import org.pgpainless.decryption_verification.ConsumerOptions;
import org.pgpainless.decryption_verification.DecryptionStream; import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.decryption_verification.OpenPgpMetadata; import org.pgpainless.decryption_verification.OpenPgpMetadata;
import org.pgpainless.decryption_verification.SignatureVerification;
import org.pgpainless.exception.MissingDecryptionMethodException; import org.pgpainless.exception.MissingDecryptionMethodException;
import org.pgpainless.exception.WrongPassphraseException; import org.pgpainless.exception.WrongPassphraseException;
import org.pgpainless.key.SubkeyIdentifier;
import org.pgpainless.util.Passphrase; import org.pgpainless.util.Passphrase;
import sop.DecryptionResult; import sop.DecryptionResult;
import sop.ReadyWithResult; import sop.ReadyWithResult;
@ -151,12 +150,8 @@ public class DecryptImpl implements Decrypt {
OpenPgpMetadata metadata = decryptionStream.getResult(); OpenPgpMetadata metadata = decryptionStream.getResult();
List<Verification> verificationList = new ArrayList<>(); List<Verification> verificationList = new ArrayList<>();
for (SubkeyIdentifier verifiedSigningKey : metadata.getVerifiedSignatures().keySet()) { for (SignatureVerification signatureVerification : metadata.getVerifiedInbandSignatures()) {
PGPSignature signature = metadata.getVerifiedSignatures().get(verifiedSigningKey); verificationList.add(map(signatureVerification));
verificationList.add(new Verification(
signature.getCreationTime(),
verifiedSigningKey.getSubkeyFingerprint().toString(),
verifiedSigningKey.getPrimaryKeyFingerprint().toString()));
} }
if (!consumerOptions.getCertificates().isEmpty()) { if (!consumerOptions.getCertificates().isEmpty()) {
@ -178,4 +173,10 @@ public class DecryptImpl implements Decrypt {
} }
}; };
} }
private Verification map(SignatureVerification sigVerification) {
return new Verification(sigVerification.getSignature().getCreationTime(),
sigVerification.getSigningKey().getSubkeyFingerprint().toString(),
sigVerification.getSigningKey().getPrimaryKeyFingerprint().toString());
}
} }

View file

@ -12,13 +12,12 @@ import java.util.List;
import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.util.io.Streams; import org.bouncycastle.util.io.Streams;
import org.pgpainless.PGPainless; import org.pgpainless.PGPainless;
import org.pgpainless.decryption_verification.ConsumerOptions; import org.pgpainless.decryption_verification.ConsumerOptions;
import org.pgpainless.decryption_verification.DecryptionStream; import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.decryption_verification.OpenPgpMetadata; import org.pgpainless.decryption_verification.OpenPgpMetadata;
import org.pgpainless.key.SubkeyIdentifier; import org.pgpainless.decryption_verification.SignatureVerification;
import sop.Verification; import sop.Verification;
import sop.exception.SOPGPException; import sop.exception.SOPGPException;
import sop.operation.DetachedVerify; import sop.operation.DetachedVerify;
@ -75,12 +74,8 @@ public class DetachedVerifyImpl implements DetachedVerify {
OpenPgpMetadata metadata = decryptionStream.getResult(); OpenPgpMetadata metadata = decryptionStream.getResult();
List<Verification> verificationList = new ArrayList<>(); List<Verification> verificationList = new ArrayList<>();
for (SubkeyIdentifier verifiedSigningKey : metadata.getVerifiedSignatures().keySet()) { for (SignatureVerification signatureVerification : metadata.getVerifiedDetachedSignatures()) {
PGPSignature signature = metadata.getVerifiedSignatures().get(verifiedSigningKey); verificationList.add(map(signatureVerification));
verificationList.add(new Verification(
signature.getCreationTime(),
verifiedSigningKey.getSubkeyFingerprint().toString(),
verifiedSigningKey.getPrimaryKeyFingerprint().toString()));
} }
if (!options.getCertificates().isEmpty()) { if (!options.getCertificates().isEmpty()) {
@ -94,4 +89,10 @@ public class DetachedVerifyImpl implements DetachedVerify {
throw new SOPGPException.BadData(e); throw new SOPGPException.BadData(e);
} }
} }
private Verification map(SignatureVerification sigVerification) {
return new Verification(sigVerification.getSignature().getCreationTime(),
sigVerification.getSigningKey().getSubkeyFingerprint().toString(),
sigVerification.getSigningKey().getPrimaryKeyFingerprint().toString());
}
} }

View file

@ -4,20 +4,6 @@
package org.pgpainless.sop; package org.pgpainless.sop;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.util.io.Streams;
import org.pgpainless.PGPainless;
import org.pgpainless.decryption_verification.ConsumerOptions;
import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.decryption_verification.OpenPgpMetadata;
import org.pgpainless.key.SubkeyIdentifier;
import sop.ReadyWithResult;
import sop.Verification;
import sop.exception.SOPGPException;
import sop.operation.InlineVerify;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -25,6 +11,19 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.util.io.Streams;
import org.pgpainless.PGPainless;
import org.pgpainless.decryption_verification.ConsumerOptions;
import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.decryption_verification.OpenPgpMetadata;
import org.pgpainless.decryption_verification.SignatureVerification;
import sop.ReadyWithResult;
import sop.Verification;
import sop.exception.SOPGPException;
import sop.operation.InlineVerify;
public class InlineVerifyImpl implements InlineVerify { public class InlineVerifyImpl implements InlineVerify {
private final ConsumerOptions options = new ConsumerOptions(); private final ConsumerOptions options = new ConsumerOptions();
@ -70,12 +69,12 @@ public class InlineVerifyImpl implements InlineVerify {
OpenPgpMetadata metadata = decryptionStream.getResult(); OpenPgpMetadata metadata = decryptionStream.getResult();
List<Verification> verificationList = new ArrayList<>(); List<Verification> verificationList = new ArrayList<>();
for (SubkeyIdentifier verifiedSigningKey : metadata.getVerifiedSignatures().keySet()) { List<SignatureVerification> verifications = metadata.isCleartextSigned() ?
PGPSignature signature = metadata.getVerifiedSignatures().get(verifiedSigningKey); metadata.getVerifiedDetachedSignatures() :
verificationList.add(new Verification( metadata.getVerifiedInbandSignatures();
signature.getCreationTime(),
verifiedSigningKey.getSubkeyFingerprint().toString(), for (SignatureVerification signatureVerification : verifications) {
verifiedSigningKey.getPrimaryKeyFingerprint().toString())); verificationList.add(map(signatureVerification));
} }
if (!options.getCertificates().isEmpty()) { if (!options.getCertificates().isEmpty()) {
@ -91,4 +90,10 @@ public class InlineVerifyImpl implements InlineVerify {
} }
}; };
} }
private Verification map(SignatureVerification sigVerification) {
return new Verification(sigVerification.getSignature().getCreationTime(),
sigVerification.getSigningKey().getSubkeyFingerprint().toString(),
sigVerification.getSigningKey().getPrimaryKeyFingerprint().toString());
}
} }