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:
parent
5375cd454f
commit
75455f1a3c
8 changed files with 88 additions and 54 deletions
|
@ -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;
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue