1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-11-16 09:22:05 +01:00

Cleaning up and collect signature verifications

This commit is contained in:
Paul Schaub 2022-10-16 18:15:31 +02:00
parent 43c369f1f9
commit a9f77ea100
3 changed files with 262 additions and 217 deletions

View file

@ -91,6 +91,62 @@ public class MessageMetadata {
}; };
} }
public @Nonnull List<SignatureVerification> getVerifiedSignatures() {
List<SignatureVerification> verifications = new ArrayList<>();
Iterator<List<SignatureVerification>> verificationsByLayer = getVerifiedSignaturesByLayer();
while (verificationsByLayer.hasNext()) {
verifications.addAll(verificationsByLayer.next());
}
return verifications;
}
public @Nonnull Iterator<List<SignatureVerification>> getVerifiedSignaturesByLayer() {
return new LayerIterator<List<SignatureVerification>>(message) {
@Override
boolean matches(Nested layer) {
return layer instanceof Layer;
}
@Override
boolean matches(Layer layer) {
return true;
}
@Override
List<SignatureVerification> getProperty(Layer last) {
return new ArrayList<>(last.getVerifiedSignatures());
}
};
}
public @Nonnull List<SignatureVerification.Failure> getRejectedSignatures() {
List<SignatureVerification.Failure> rejected = new ArrayList<>();
Iterator<List<SignatureVerification.Failure>> rejectedByLayer = getRejectedSignaturesByLayer();
while (rejectedByLayer.hasNext()) {
rejected.addAll(rejectedByLayer.next());
}
return rejected;
}
public @Nonnull Iterator<List<SignatureVerification.Failure>> getRejectedSignaturesByLayer() {
return new LayerIterator<List<SignatureVerification.Failure>>(message) {
@Override
boolean matches(Nested layer) {
return layer instanceof Layer;
}
@Override
boolean matches(Layer layer) {
return true;
}
@Override
List<SignatureVerification.Failure> getProperty(Layer last) {
return new ArrayList<>(last.getFailedSignatures());
}
};
}
public String getFilename() { public String getFilename() {
return findLiteralData().getFileName(); return findLiteralData().getFileName();
} }
@ -132,6 +188,14 @@ public class MessageMetadata {
public List<SignatureVerification.Failure> getFailedSignatures() { public List<SignatureVerification.Failure> getFailedSignatures() {
return new ArrayList<>(failedSignatures); return new ArrayList<>(failedSignatures);
} }
void addVerifiedSignature(SignatureVerification signatureVerification) {
verifiedSignatures.add(signatureVerification);
}
void addFailedSignature(SignatureVerification.Failure failure) {
failedSignatures.add(failure);
}
} }
public interface Nested { public interface Nested {
@ -223,9 +287,11 @@ public class MessageMetadata {
private abstract static class LayerIterator<O> implements Iterator<O> { private abstract static class LayerIterator<O> implements Iterator<O> {
private Nested current; private Nested current;
Layer last = null; Layer last = null;
Message parent;
LayerIterator(Message message) { LayerIterator(Message message) {
super(); super();
this.parent = message;
this.current = message.child; this.current = message.child;
if (matches(current)) { if (matches(current)) {
last = (Layer) current; last = (Layer) current;
@ -234,6 +300,9 @@ public class MessageMetadata {
@Override @Override
public boolean hasNext() { public boolean hasNext() {
if (parent != null && matches(parent)) {
return true;
}
if (last == null) { if (last == null) {
findNext(); findNext();
} }
@ -242,6 +311,11 @@ public class MessageMetadata {
@Override @Override
public O next() { public O next() {
if (parent != null && matches(parent)) {
O property = getProperty(parent);
parent = null;
return property;
}
if (last == null) { if (last == null) {
findNext(); findNext();
} }
@ -263,7 +337,16 @@ public class MessageMetadata {
} }
} }
abstract boolean matches(Nested layer); boolean matches(Nested layer) {
return false;
}
boolean matches(Layer layer) {
if (layer instanceof Nested) {
return matches((Nested) layer);
}
return false;
}
abstract O getProperty(Layer last); abstract O getProperty(Layer last);
} }

View file

@ -34,7 +34,6 @@ import org.bouncycastle.openpgp.operator.PBEDataDecryptorFactory;
import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider; import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider;
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory; import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
import org.bouncycastle.openpgp.operator.SessionKeyDataDecryptorFactory; import org.bouncycastle.openpgp.operator.SessionKeyDataDecryptorFactory;
import org.bouncycastle.util.encoders.Hex;
import org.pgpainless.PGPainless; import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.CompressionAlgorithm; import org.pgpainless.algorithm.CompressionAlgorithm;
import org.pgpainless.algorithm.EncryptionPurpose; import org.pgpainless.algorithm.EncryptionPurpose;
@ -81,16 +80,27 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
private final MessageMetadata.Layer metadata; private final MessageMetadata.Layer metadata;
private final Policy policy; private final Policy policy;
public OpenPgpMessageInputStream(InputStream inputStream, ConsumerOptions options) public OpenPgpMessageInputStream(@Nonnull InputStream inputStream,
@Nonnull ConsumerOptions options)
throws IOException, PGPException { throws IOException, PGPException {
this(inputStream, options, new MessageMetadata.Message()); this(inputStream, options, PGPainless.getPolicy());
} }
OpenPgpMessageInputStream(InputStream inputStream, ConsumerOptions options, MessageMetadata.Layer metadata) public OpenPgpMessageInputStream(@Nonnull InputStream inputStream,
@Nonnull ConsumerOptions options,
@Nonnull Policy policy)
throws PGPException, IOException {
this(inputStream, options, new MessageMetadata.Message(), policy);
}
protected OpenPgpMessageInputStream(@Nonnull InputStream inputStream,
@Nonnull ConsumerOptions options,
@Nonnull MessageMetadata.Layer metadata,
@Nonnull Policy policy)
throws PGPException, IOException { throws PGPException, IOException {
super(OpenPgpMetadata.getBuilder()); super(OpenPgpMetadata.getBuilder());
this.policy = PGPainless.getPolicy(); this.policy = policy;
this.options = options; this.options = options;
this.metadata = metadata; this.metadata = metadata;
this.signatures = new Signatures(options); this.signatures = new Signatures(options);
@ -100,6 +110,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
this.signatures.addDetachedSignatures(options.getDetachedSignatures()); this.signatures.addDetachedSignatures(options.getDetachedSignatures());
} }
// tee out packet bytes for signature verification
packetInputStream = new TeeBCPGInputStream(BCPGInputStream.wrap(inputStream), signatures); packetInputStream = new TeeBCPGInputStream(BCPGInputStream.wrap(inputStream), signatures);
// *omnomnom* // *omnomnom*
@ -125,37 +136,30 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
private void consumePackets() private void consumePackets()
throws IOException, PGPException { throws IOException, PGPException {
OpenPgpPacket nextPacket; OpenPgpPacket nextPacket;
loop: while ((nextPacket = packetInputStream.nextPacketTag()) != null) {
loop: // we break this when we go deeper.
while ((nextPacket = packetInputStream.nextPacketTag()) != null) {
signatures.nextPacket(nextPacket); signatures.nextPacket(nextPacket);
switch (nextPacket) { switch (nextPacket) {
// Literal Data - the literal data content is the new input stream // Literal Data - the literal data content is the new input stream
case LIT: case LIT:
automaton.next(InputAlphabet.LiteralData);
processLiteralData(); processLiteralData();
break loop; break loop;
// Compressed Data - the content contains another OpenPGP message // Compressed Data - the content contains another OpenPGP message
case COMP: case COMP:
automaton.next(InputAlphabet.CompressedData);
processCompressedData(); processCompressedData();
break loop; break loop;
// One Pass Signature // One Pass Signature
case OPS: case OPS:
automaton.next(InputAlphabet.OnePassSignature); processOnePassSignature();
PGPOnePassSignature onePassSignature = readOnePassSignature();
signatures.addOnePassSignature(onePassSignature);
break; break;
// Signature - either prepended to the message, or corresponding to a One Pass Signature // Signature - either prepended to the message, or corresponding to a One Pass Signature
case SIG: case SIG:
// true if Signature corresponds to OnePassSignature processSignature();
boolean isSigForOPS = automaton.peekStack() == StackAlphabet.ops;
automaton.next(InputAlphabet.Signature);
processSignature(isSigForOPS);
break; break;
// Encrypted Data (ESKs and SED/SEIPD are parsed the same by BC) // Encrypted Data (ESKs and SED/SEIPD are parsed the same by BC)
@ -163,7 +167,6 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
case SKESK: case SKESK:
case SED: case SED:
case SEIPD: case SEIPD:
automaton.next(InputAlphabet.EncryptedData);
if (processEncryptedData()) { if (processEncryptedData()) {
break loop; break loop;
} }
@ -200,36 +203,51 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
} }
} }
private void processSignature(boolean isSigForOPS) throws PGPException, IOException { private void processLiteralData() throws IOException {
PGPSignature signature = readSignature(); automaton.next(InputAlphabet.LiteralData);
if (isSigForOPS) { PGPLiteralData literalData = packetInputStream.readLiteralData();
signatures.leaveNesting(); // TODO: Only leave nesting if all OPSs are dealt with this.metadata.setChild(new MessageMetadata.LiteralData(
signatures.addCorrespondingOnePassSignature(signature); literalData.getFileName(),
} else { literalData.getModificationTime(),
signatures.addPrependedSignature(signature); StreamEncoding.requireFromCode(literalData.getFormat())));
} nestedInputStream = literalData.getDataStream();
} }
private void processCompressedData() throws IOException, PGPException { private void processCompressedData() throws IOException, PGPException {
automaton.next(InputAlphabet.CompressedData);
signatures.enterNesting(); signatures.enterNesting();
PGPCompressedData compressedData = packetInputStream.readCompressedData(); PGPCompressedData compressedData = packetInputStream.readCompressedData();
MessageMetadata.CompressedData compressionLayer = new MessageMetadata.CompressedData( MessageMetadata.CompressedData compressionLayer = new MessageMetadata.CompressedData(
CompressionAlgorithm.fromId(compressedData.getAlgorithm())); CompressionAlgorithm.fromId(compressedData.getAlgorithm()));
InputStream decompressed = compressedData.getDataStream(); InputStream decompressed = compressedData.getDataStream();
nestedInputStream = new OpenPgpMessageInputStream(buffer(decompressed), options, compressionLayer); nestedInputStream = new OpenPgpMessageInputStream(buffer(decompressed), options, compressionLayer, policy);
} }
private void processLiteralData() throws IOException { private void processOnePassSignature() throws PGPException, IOException {
PGPLiteralData literalData = packetInputStream.readLiteralData(); automaton.next(InputAlphabet.OnePassSignature);
this.metadata.setChild(new MessageMetadata.LiteralData(literalData.getFileName(), literalData.getModificationTime(), PGPOnePassSignature onePassSignature = packetInputStream.readOnePassSignature();
StreamEncoding.requireFromCode(literalData.getFormat()))); signatures.addOnePassSignature(onePassSignature);
nestedInputStream = literalData.getDataStream(); }
private void processSignature() throws PGPException, IOException {
// true if Signature corresponds to OnePassSignature
boolean isSigForOPS = automaton.peekStack() == StackAlphabet.ops;
automaton.next(InputAlphabet.Signature);
PGPSignature signature = packetInputStream.readSignature();
if (isSigForOPS) {
signatures.leaveNesting(); // TODO: Only leave nesting if all OPSs of the nesting layer are dealt with
signatures.addCorrespondingOnePassSignature(signature, metadata);
} else {
signatures.addPrependedSignature(signature);
}
} }
private boolean processEncryptedData() throws IOException, PGPException { private boolean processEncryptedData() throws IOException, PGPException {
automaton.next(InputAlphabet.EncryptedData);
PGPEncryptedDataList encDataList = packetInputStream.readEncryptedDataList(); PGPEncryptedDataList encDataList = packetInputStream.readEncryptedDataList();
// TODO: Replace with !encDataList.isIntegrityProtected() // TODO: Replace with !encDataList.isIntegrityProtected()
// once BC ships it
if (!encDataList.get(0).isIntegrityProtected()) { if (!encDataList.get(0).isIntegrityProtected()) {
throw new MessageNotIntegrityProtectedException(); throw new MessageNotIntegrityProtectedException();
} }
@ -239,24 +257,25 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
// Try session key // Try session key
if (options.getSessionKey() != null) { if (options.getSessionKey() != null) {
SessionKey sessionKey = options.getSessionKey(); SessionKey sessionKey = options.getSessionKey();
if (!policy.getSymmetricKeyDecryptionAlgorithmPolicy().isAcceptable(sessionKey.getAlgorithm())) {
throw new UnacceptableAlgorithmException("Symmetric algorithm " + sessionKey.getAlgorithm() + " is not acceptable."); throwIfUnacceptable(sessionKey.getAlgorithm());
}
SessionKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance() SessionKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
.getSessionKeyDataDecryptorFactory(sessionKey); .getSessionKeyDataDecryptorFactory(sessionKey);
// TODO: Replace with encDataList.addSessionKeyDecryptionMethod(sessionKey)
PGPEncryptedData esk = esks.all().get(0);
try {
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(sessionKey.getAlgorithm()); MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(sessionKey.getAlgorithm());
try {
// TODO: Use BCs new API once shipped
PGPEncryptedData esk = esks.all().get(0);
if (esk instanceof PGPPBEEncryptedData) { if (esk instanceof PGPPBEEncryptedData) {
PGPPBEEncryptedData skesk = (PGPPBEEncryptedData) esk; PGPPBEEncryptedData skesk = (PGPPBEEncryptedData) esk;
InputStream decrypted = skesk.getDataStream(decryptorFactory); InputStream decrypted = skesk.getDataStream(decryptorFactory);
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData); nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
return true; return true;
} else if (esk instanceof PGPPublicKeyEncryptedData) { } else if (esk instanceof PGPPublicKeyEncryptedData) {
PGPPublicKeyEncryptedData pkesk = (PGPPublicKeyEncryptedData) esk; PGPPublicKeyEncryptedData pkesk = (PGPPublicKeyEncryptedData) esk;
InputStream decrypted = pkesk.getDataStream(decryptorFactory); InputStream decrypted = pkesk.getDataStream(decryptorFactory);
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData); nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
return true; return true;
} else { } else {
throw new RuntimeException("Unknown ESK class type: " + esk.getClass().getName()); throw new RuntimeException("Unknown ESK class type: " + esk.getClass().getName());
@ -268,19 +287,25 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
// Try passwords // Try passwords
for (PGPPBEEncryptedData skesk : esks.skesks) { for (PGPPBEEncryptedData skesk : esks.skesks) {
SymmetricKeyAlgorithm kekAlgorithm = SymmetricKeyAlgorithm.requireFromId(skesk.getAlgorithm());
throwIfUnacceptable(kekAlgorithm);
for (Passphrase passphrase : options.getDecryptionPassphrases()) { for (Passphrase passphrase : options.getDecryptionPassphrases()) {
PBEDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance() PBEDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
.getPBEDataDecryptorFactory(passphrase); .getPBEDataDecryptorFactory(passphrase);
try { try {
InputStream decrypted = skesk.getDataStream(decryptorFactory); InputStream decrypted = skesk.getDataStream(decryptorFactory);
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData( SymmetricKeyAlgorithm sessionKeyAlgorithm = SymmetricKeyAlgorithm.requireFromId(
SymmetricKeyAlgorithm.requireFromId(skesk.getSymmetricAlgorithm(decryptorFactory))); skesk.getSymmetricAlgorithm(decryptorFactory));
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData); throwIfUnacceptable(sessionKeyAlgorithm);
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(sessionKeyAlgorithm);
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
return true; return true;
} catch (UnacceptableAlgorithmException e) {
throw e;
} catch (PGPException e) { } catch (PGPException e) {
// password mismatch? Try next password // Password mismatch?
} }
} }
} }
@ -299,19 +324,17 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
.getPublicKeyDataDecryptorFactory(privateKey); .getPublicKeyDataDecryptorFactory(privateKey);
try { try {
SymmetricKeyAlgorithm symAlg = SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)); SymmetricKeyAlgorithm symAlg = SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory));
if (!policy.getSymmetricKeyDecryptionAlgorithmPolicy().isAcceptable(symAlg)) { throwIfUnacceptable(symAlg);
throw new UnacceptableAlgorithmException("Symmetric-key algorithm " + symAlg + " is not acceptable.");
}
InputStream decrypted = pkesk.getDataStream(decryptorFactory); InputStream decrypted = pkesk.getDataStream(decryptorFactory);
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData( MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory))); SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)));
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData); nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
return true; return true;
} catch (PGPException e) { } catch (UnacceptableAlgorithmException e) {
if (e instanceof UnacceptableAlgorithmException) {
throw e; throw e;
} } catch (PGPException e) {
} }
} }
@ -327,7 +350,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
InputStream decrypted = pkesk.getDataStream(decryptorFactory); InputStream decrypted = pkesk.getDataStream(decryptorFactory);
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData( MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory))); SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)));
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData); nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
return true; return true;
} catch (PGPException e) { } catch (PGPException e) {
// hm :/ // hm :/
@ -339,6 +362,13 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
return false; return false;
} }
private void throwIfUnacceptable(SymmetricKeyAlgorithm algorithm)
throws UnacceptableAlgorithmException {
if (!policy.getSymmetricKeyDecryptionAlgorithmPolicy().isAcceptable(algorithm)) {
throw new UnacceptableAlgorithmException("Symmetric-Key algorithm " + algorithm + " is not acceptable for message decryption.");
}
}
private static InputStream buffer(InputStream inputStream) { private static InputStream buffer(InputStream inputStream) {
return new BufferedInputStream(inputStream); return new BufferedInputStream(inputStream);
} }
@ -370,16 +400,6 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
return null; return null;
} }
private PGPOnePassSignature readOnePassSignature()
throws PGPException, IOException {
return packetInputStream.readOnePassSignature();
}
private PGPSignature readSignature()
throws PGPException, IOException {
return packetInputStream.readSignature();
}
@Override @Override
public int read() throws IOException { public int read() throws IOException {
if (nestedInputStream == null) { if (nestedInputStream == null) {
@ -407,7 +427,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
} catch (PGPException e) { } catch (PGPException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
signatures.finish(); signatures.finish(metadata);
} }
return r; return r;
} }
@ -435,7 +455,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
} catch (PGPException e) { } catch (PGPException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
signatures.finish(); signatures.finish(metadata);
} }
return r; return r;
} }
@ -517,11 +537,11 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
// Furthermore, For 'OPS COMP(LIT("Foo")) SIG', the signature is updated with "Foo". CHAOS!!! // Furthermore, For 'OPS COMP(LIT("Foo")) SIG', the signature is updated with "Foo". CHAOS!!!
private static final class Signatures extends OutputStream { private static final class Signatures extends OutputStream {
final ConsumerOptions options; final ConsumerOptions options;
final List<SIG> detachedSignatures; final List<DetachedOrPrependedSignature> detachedSignatures;
final List<SIG> prependedSignatures; final List<DetachedOrPrependedSignature> prependedSignatures;
final List<OPS> onePassSignatures; final List<OnePassSignature> onePassSignatures;
final Stack<List<OPS>> opsUpdateStack; final Stack<List<OnePassSignature>> opsUpdateStack;
List<OPS> literalOPS = new ArrayList<>(); List<OnePassSignature> literalOPS = new ArrayList<>();
final List<PGPSignature> correspondingSignatures; final List<PGPSignature> correspondingSignatures;
boolean isLiteral = true; boolean isLiteral = true;
@ -546,19 +566,19 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
long keyId = SignatureUtils.determineIssuerKeyId(signature); long keyId = SignatureUtils.determineIssuerKeyId(signature);
PGPPublicKeyRing certificate = findCertificate(keyId); PGPPublicKeyRing certificate = findCertificate(keyId);
initialize(signature, certificate, keyId); initialize(signature, certificate, keyId);
this.detachedSignatures.add(new SIG(signature, certificate, keyId)); this.detachedSignatures.add(new DetachedOrPrependedSignature(signature, certificate, keyId));
} }
void addPrependedSignature(PGPSignature signature) { void addPrependedSignature(PGPSignature signature) {
long keyId = SignatureUtils.determineIssuerKeyId(signature); long keyId = SignatureUtils.determineIssuerKeyId(signature);
PGPPublicKeyRing certificate = findCertificate(keyId); PGPPublicKeyRing certificate = findCertificate(keyId);
initialize(signature, certificate, keyId); initialize(signature, certificate, keyId);
this.prependedSignatures.add(new SIG(signature, certificate, keyId)); this.prependedSignatures.add(new DetachedOrPrependedSignature(signature, certificate, keyId));
} }
void addOnePassSignature(PGPOnePassSignature signature) { void addOnePassSignature(PGPOnePassSignature signature) {
PGPPublicKeyRing certificate = findCertificate(signature.getKeyID()); PGPPublicKeyRing certificate = findCertificate(signature.getKeyID());
OPS ops = new OPS(signature, certificate, signature.getKeyID()); OnePassSignature ops = new OnePassSignature(signature, certificate, signature.getKeyID());
ops.init(certificate); ops.init(certificate);
onePassSignatures.add(ops); onePassSignatures.add(ops);
@ -568,9 +588,9 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
} }
} }
void addCorrespondingOnePassSignature(PGPSignature signature) { void addCorrespondingOnePassSignature(PGPSignature signature, MessageMetadata.Layer layer) {
for (int i = onePassSignatures.size() - 1; i >= 0; i--) { for (int i = onePassSignatures.size() - 1; i >= 0; i--) {
OPS onePassSignature = onePassSignatures.get(i); OnePassSignature onePassSignature = onePassSignatures.get(i);
if (onePassSignature.opSignature.getKeyID() != signature.getKeyID()) { if (onePassSignature.opSignature.getKeyID() != signature.getKeyID()) {
continue; continue;
} }
@ -579,8 +599,14 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
} }
boolean verified = onePassSignature.verify(signature); boolean verified = onePassSignature.verify(signature);
log("One-Pass-Signature by " + Long.toHexString(onePassSignature.opSignature.getKeyID()) + " is " + (verified ? "verified" : "unverified")); SignatureVerification verification = new SignatureVerification(signature,
log(onePassSignature.toString()); new SubkeyIdentifier(onePassSignature.certificate, onePassSignature.keyId));
if (verified) {
layer.addVerifiedSignature(verification);
} else {
layer.addFailedSignature(new SignatureVerification.Failure(verification,
new SignatureValidationException("Incorrect Signature.")));
}
break; break;
} }
} }
@ -597,11 +623,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
opsUpdateStack.pop(); opsUpdateStack.pop();
} }
private static void initialize(PGPSignature signature, PGPPublicKeyRing certificate, long keyId) { private static void initialize(@Nonnull PGPSignature signature, @Nonnull PGPPublicKeyRing certificate, long keyId) {
if (certificate == null) {
// SHIT
return;
}
PGPContentVerifierBuilderProvider verifierProvider = ImplementationFactory.getInstance() PGPContentVerifierBuilderProvider verifierProvider = ImplementationFactory.getInstance()
.getPGPContentVerifierBuilderProvider(); .getPGPContentVerifierBuilderProvider();
try { try {
@ -611,10 +633,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
} }
} }
private static void initialize(PGPOnePassSignature ops, PGPPublicKeyRing certificate) { private static void initialize(@Nonnull PGPOnePassSignature ops, @Nonnull PGPPublicKeyRing certificate) {
if (certificate == null) {
return;
}
PGPContentVerifierBuilderProvider verifierProvider = ImplementationFactory.getInstance() PGPContentVerifierBuilderProvider verifierProvider = ImplementationFactory.getInstance()
.getPGPContentVerifierBuilderProvider(); .getPGPContentVerifierBuilderProvider();
try { try {
@ -635,76 +654,74 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
} }
public void updateLiteral(byte b) { public void updateLiteral(byte b) {
for (OPS ops : literalOPS) { for (OnePassSignature ops : literalOPS) {
ops.update(b); ops.update(b);
} }
for (SIG detached : detachedSignatures) { for (DetachedOrPrependedSignature detached : detachedSignatures) {
detached.update(b); detached.update(b);
} }
for (DetachedOrPrependedSignature prepended : prependedSignatures) {
prepended.update(b);
}
} }
public void updateLiteral(byte[] b, int off, int len) { public void updateLiteral(byte[] b, int off, int len) {
for (OPS ops : literalOPS) { for (OnePassSignature ops : literalOPS) {
ops.update(b, off, len); ops.update(b, off, len);
} }
for (SIG detached : detachedSignatures) { for (DetachedOrPrependedSignature detached : detachedSignatures) {
detached.update(b, off, len); detached.update(b, off, len);
} }
for (DetachedOrPrependedSignature prepended : prependedSignatures) {
prepended.update(b, off, len);
}
} }
public void updatePacket(byte b) { public void updatePacket(byte b) {
for (SIG detached : detachedSignatures) {
detached.update(b);
}
for (SIG prepended : prependedSignatures) {
prepended.update(b);
}
for (int i = opsUpdateStack.size() - 1; i >= 0; i--) { for (int i = opsUpdateStack.size() - 1; i >= 0; i--) {
List<OPS> nestedOPSs = opsUpdateStack.get(i); List<OnePassSignature> nestedOPSs = opsUpdateStack.get(i);
for (OPS ops : nestedOPSs) { for (OnePassSignature ops : nestedOPSs) {
ops.update(b); ops.update(b);
} }
} }
} }
public void updatePacket(byte[] buf, int off, int len) { public void updatePacket(byte[] buf, int off, int len) {
for (SIG detached : detachedSignatures) {
detached.update(buf, off, len);
}
for (SIG prepended : prependedSignatures) {
prepended.update(buf, off, len);
}
for (int i = opsUpdateStack.size() - 1; i >= 0; i--) { for (int i = opsUpdateStack.size() - 1; i >= 0; i--) {
List<OPS> nestedOPSs = opsUpdateStack.get(i); List<OnePassSignature> nestedOPSs = opsUpdateStack.get(i);
for (OPS ops : nestedOPSs) { for (OnePassSignature ops : nestedOPSs) {
ops.update(buf, off, len); ops.update(buf, off, len);
} }
} }
} }
public void finish() { public void finish(MessageMetadata.Layer layer) {
for (SIG detached : detachedSignatures) { for (DetachedOrPrependedSignature detached : detachedSignatures) {
boolean verified = detached.verify(); boolean verified = detached.verify();
SignatureVerification verification = new SignatureVerification(
detached.signature, new SubkeyIdentifier(detached.certificate, detached.keyId));
if (verified) { if (verified) {
this.verified.add(detached.signature); layer.addVerifiedSignature(verification);
} else {
layer.addFailedSignature(new SignatureVerification.Failure(
verification, new SignatureValidationException("Incorrect Signature.")));
} }
log("Detached Signature by " + Long.toHexString(detached.signature.getKeyID()) + " is " + (verified ? "verified" : "unverified"));
log(detached.toString());
} }
for (SIG prepended : prependedSignatures) { for (DetachedOrPrependedSignature prepended : prependedSignatures) {
boolean verified = prepended.verify(); boolean verified = prepended.verify();
SignatureVerification verification = new SignatureVerification(
prepended.signature, new SubkeyIdentifier(prepended.certificate, prepended.keyId));
if (verified) { if (verified) {
this.verified.add(prepended.signature); layer.addVerifiedSignature(verification);
} else {
layer.addFailedSignature(new SignatureVerification.Failure(
verification, new SignatureValidationException("Incorrect Signature.")));
} }
log("Prepended Signature by " + Long.toHexString(prepended.signature.getKeyID()) + " is " + (verified ? "verified" : "unverified"));
log(prepended.toString());
} }
} }
@ -729,7 +746,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
} }
} }
static class SIG { static class DetachedOrPrependedSignature {
ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ByteArrayOutputStream bytes = new ByteArrayOutputStream();
PGPSignature signature; PGPSignature signature;
PGPPublicKeyRing certificate; PGPPublicKeyRing certificate;
@ -737,7 +754,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
boolean finished; boolean finished;
boolean valid; boolean valid;
public SIG(PGPSignature signature, PGPPublicKeyRing certificate, long keyId) { public DetachedOrPrependedSignature(PGPSignature signature, PGPPublicKeyRing certificate, long keyId) {
this.signature = signature; this.signature = signature;
this.certificate = certificate; this.certificate = certificate;
this.keyId = keyId; this.keyId = keyId;
@ -762,8 +779,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
public void update(byte b) { public void update(byte b) {
if (finished) { if (finished) {
log("Updating finished sig!"); throw new IllegalStateException("Already finished.");
return;
} }
signature.update(b); signature.update(b);
bytes.write(b); bytes.write(b);
@ -771,52 +787,14 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
public void update(byte[] bytes, int off, int len) { public void update(byte[] bytes, int off, int len) {
if (finished) { if (finished) {
log("Updating finished sig!"); throw new IllegalStateException("Already finished.");
return;
} }
signature.update(bytes, off, len); signature.update(bytes, off, len);
this.bytes.write(bytes, off, len); this.bytes.write(bytes, off, len);
} }
@Override
public String toString() {
String OPS = "c40d03000a01fbfcc82a015e733001";
String LIT_H = "cb28620000000000";
String LIT = "656e637279707420e28898207369676e20e28898207369676e20e28898207369676e";
String SIG1 = "c2c10400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267b0409ed8ea96dac66447bdff5b7b60c9f80a0ab91d257029153dc3b6d8c27b98162104d1a66e1a23b182c9980f788cfbfcc82a015e7330000029640c00846b5096d92474fd446cc7edaf9f14572cab93a80e12384c1e829f95debc6e8373c2ce5402be53dc1a18cf92a0ed909e0fb38855713ef8ffb13502ffac7c830fa254cc1aa6c666a97b0cc3bc176538f6913d3b8e8981a65cc42df10e0f39e4d0a06dfe961437b59a71892f4fca1116aed15123ea0d86a7b2ce47dd9d3ef22d920631bc011e82babe03ad5d72b3ba7f95bf646f20ccf6f7a4d95de37397c76c7d53741458e51ab6074007f61181c7b88b7c98f5b7510c8dfa3be01f4841501679478b15c5249d928e2a10d15ec63efa1500b994d5bfb32ffb174a976116930eb97a111e6dfd4c5e43e04a5d76ba74806a62fda63a8c3f53f6eebaf852892340e81dd08bbf348454a2cf525aeb512cf33aeeee78465ee4c442e41cc45ac4e3bb0c3333677aa60332ee7f464d9020f8554b82d619872477cca18d8431888f4ae8abe5894e9720f759c410cd7991db12703dc147040dd0d3758223e0b75de6ceae49c1a0c2c45efedeb7114ae785cc886afdc45c82172e4476e1ab5b86dc4314dd76";
String SIG1f = "c2c13b0400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267b0409ed8ea96dac66447bdff5b7b60c9f80a0ab91d257029153dc3b6d8c27b98162104d1a66e1a23b182c9980f788cfbfcc82a015e7330000029640c00846b5096d92474fd446cc7edaf9f14572cab93a80e12384c1e829f95debc6e8373c2ce5402be53dc1a18cf92a0ed909e0fb38855713ef8ffb13502ffac7c830fa254cc1aa6c666a97b0cc3bc176538f6913d3b8e8981a65cc42df10e0f39e4d0a06dfe961437b59a71892f4fca1116aed15123ea0d86a7b2ce47dd9d3ef22d920631bc011e82babe03ad5d72b3ba7f95bf646f20ccf6f7a4d95de37397c76c7d53741458e51ab6074007f61181c7b88b7c98f5b7510c8dfa3be01f4841501679478b15c5249d928e2a10d15ec63efa1500b994d5bfb32ffb174a976116930eb97a111e6dfd4c5e43e04a5d76ba74806a62fda63a8c3f53f6eebaf852892340e81dd08bbf348454a2cf525aeb512cf33aeeee78465ee4c442e41cc45ac4e3bb0c3333677aa60332ee7f464d9020f8554b82d619872477cca18d8431888f4ae8abe5894e9720f759c410cd7991db12703dc147040dd0d3758223e0b75de6ceae49c1a0c2c45efedeb7114ae785cc886afdc45c82172e4476e1ab5b86dc4314dd76";
String SIG2 = "c2c10400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267a4d9c117dc7ba3a7e9270856f128d2ab271743eac3cb5750b22a89bd5fd60753162104d1a66e1a23b182c9980f788cfbfcc82a015e73300000b8400bff796c20fa8b25ff7a42686338e06417a2966e85a0fc2723c928bef6cd19d34cf5e7d55ada33080613012dadb79e0278e59d9e7ed7d2d6102912a5f768c2e75b60099225c3d8bfe0c123240188b80dbee89b9b3bd5b13ccc662abc37e2129b6968adac9aba43aa778c0fe4fe337591ee87a96a29a013debc83555293c877144fc676aa1b03782c501949521a320adf6ad96c4f2e036b52a18369c637fdc49033696a84d03a69580b953187fce5aca6fb26fc8815da9f3b513bfe8e304f33ecb4b521aeb7d09c4a284ea66123bd0d6a358b2526d762ca110e1f7f20b3038d774b64d5cfd34e2213765828359d7afc5bf24d5270e99d80c3c1568fa01624b6ea1e9ce4e6890ce9bacf6611a45d41e2671f68f5b096446bf08d27ce75608425b2e3ab92146229ad1fcd8224aca5b5f73960506e7df07bfbf3664348e8ecbfb2eb467b9cfe412cb377a6ee2eb5fd11be9cf9208fe9a74c296f52cfa02a1eb0519ad9a8349bf6ccd6495feb7e391451bf96e08a0798883dee5974e47cbf3b51f111b6d3";
String SIG2f = "c2c13b0400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267a4d9c117dc7ba3a7e9270856f128d2ab271743eac3cb5750b22a89bd5fd60753162104d1a66e1a23b182c9980f788cfbfcc82a015e73300000b8400bff796c20fa8b25ff7a42686338e06417a2966e85a0fc2723c928bef6cd19d34cf5e7d55ada33080613012dadb79e0278e59d9e7ed7d2d6102912a5f768c2e75b60099225c3d8bfe0c123240188b80dbee89b9b3bd5b13ccc662abc37e2129b6968adac9aba43aa778c0fe4fe337591ee87a96a29a013debc83555293c877144fc676aa1b03782c501949521a320adf6ad96c4f2e036b52a18369c637fdc49033696a84d03a69580b953187fce5aca6fb26fc8815da9f3b513bfe8e304f33ecb4b521aeb7d09c4a284ea66123bd0d6a358b2526d762ca110e1f7f20b3038d774b64d5cfd34e2213765828359d7afc5bf24d5270e99d80c3c1568fa01624b6ea1e9ce4e6890ce9bacf6611a45d41e2671f68f5b096446bf08d27ce75608425b2e3ab92146229ad1fcd8224aca5b5f73960506e7df07bfbf3664348e8ecbfb2eb467b9cfe412cb377a6ee2eb5fd11be9cf9208fe9a74c296f52cfa02a1eb0519ad9a8349bf6ccd6495feb7e391451bf96e08a0798883dee5974e47cbf3b51f111b6d3";
String out = "";
String hex = Hex.toHexString(bytes.toByteArray());
while (hex.contains(OPS)) {
hex = hex.replace(OPS, "[OPS]");
}
while (hex.contains(LIT_H)) {
hex = hex.replace(LIT_H, "[LIT]");
}
while (hex.contains(LIT)) {
hex = hex.replace(LIT, "<content>");
}
while (hex.contains(SIG1)) {
hex = hex.replace(SIG1, "[SIG1]");
}
while (hex.contains(SIG1f)) {
hex = hex.replace(SIG1f, "[SIG1f]");
}
while (hex.contains(SIG2)) {
hex = hex.replace(SIG2, "[SIG2]");
}
while (hex.contains(SIG2f)) {
hex = hex.replace(SIG2f, "[SIG2f]");
} }
return out + hex; static class OnePassSignature {
}
}
static class OPS {
ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ByteArrayOutputStream bytes = new ByteArrayOutputStream();
PGPOnePassSignature opSignature; PGPOnePassSignature opSignature;
PGPSignature signature; PGPSignature signature;
@ -825,7 +803,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
boolean finished; boolean finished;
boolean valid; boolean valid;
public OPS(PGPOnePassSignature signature, PGPPublicKeyRing certificate, long keyId) { public OnePassSignature(PGPOnePassSignature signature, PGPPublicKeyRing certificate, long keyId) {
this.opSignature = signature; this.opSignature = signature;
this.certificate = certificate; this.certificate = certificate;
this.keyId = keyId; this.keyId = keyId;
@ -836,6 +814,10 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
} }
public boolean verify(PGPSignature signature) { public boolean verify(PGPSignature signature) {
if (finished) {
throw new IllegalStateException("Already finished.");
}
if (this.opSignature.getKeyID() != signature.getKeyID()) { if (this.opSignature.getKeyID() != signature.getKeyID()) {
// nope // nope
return false; return false;
@ -852,8 +834,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
public void update(byte b) { public void update(byte b) {
if (finished) { if (finished) {
log("Updating finished sig!"); throw new IllegalStateException("Already finished.");
return;
} }
opSignature.update(b); opSignature.update(b);
bytes.write(b); bytes.write(b);
@ -861,49 +842,11 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
public void update(byte[] bytes, int off, int len) { public void update(byte[] bytes, int off, int len) {
if (finished) { if (finished) {
log("Updating finished sig!"); throw new IllegalStateException("Already finished.");
return;
} }
opSignature.update(bytes, off, len); opSignature.update(bytes, off, len);
this.bytes.write(bytes, off, len); this.bytes.write(bytes, off, len);
} }
@Override
public String toString() {
String OPS = "c40d03000a01fbfcc82a015e733001";
String LIT_H = "cb28620000000000";
String LIT = "656e637279707420e28898207369676e20e28898207369676e20e28898207369676e";
String SIG1 = "c2c10400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267b0409ed8ea96dac66447bdff5b7b60c9f80a0ab91d257029153dc3b6d8c27b98162104d1a66e1a23b182c9980f788cfbfcc82a015e7330000029640c00846b5096d92474fd446cc7edaf9f14572cab93a80e12384c1e829f95debc6e8373c2ce5402be53dc1a18cf92a0ed909e0fb38855713ef8ffb13502ffac7c830fa254cc1aa6c666a97b0cc3bc176538f6913d3b8e8981a65cc42df10e0f39e4d0a06dfe961437b59a71892f4fca1116aed15123ea0d86a7b2ce47dd9d3ef22d920631bc011e82babe03ad5d72b3ba7f95bf646f20ccf6f7a4d95de37397c76c7d53741458e51ab6074007f61181c7b88b7c98f5b7510c8dfa3be01f4841501679478b15c5249d928e2a10d15ec63efa1500b994d5bfb32ffb174a976116930eb97a111e6dfd4c5e43e04a5d76ba74806a62fda63a8c3f53f6eebaf852892340e81dd08bbf348454a2cf525aeb512cf33aeeee78465ee4c442e41cc45ac4e3bb0c3333677aa60332ee7f464d9020f8554b82d619872477cca18d8431888f4ae8abe5894e9720f759c410cd7991db12703dc147040dd0d3758223e0b75de6ceae49c1a0c2c45efedeb7114ae785cc886afdc45c82172e4476e1ab5b86dc4314dd76";
String SIG1f = "c2c13b0400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267b0409ed8ea96dac66447bdff5b7b60c9f80a0ab91d257029153dc3b6d8c27b98162104d1a66e1a23b182c9980f788cfbfcc82a015e7330000029640c00846b5096d92474fd446cc7edaf9f14572cab93a80e12384c1e829f95debc6e8373c2ce5402be53dc1a18cf92a0ed909e0fb38855713ef8ffb13502ffac7c830fa254cc1aa6c666a97b0cc3bc176538f6913d3b8e8981a65cc42df10e0f39e4d0a06dfe961437b59a71892f4fca1116aed15123ea0d86a7b2ce47dd9d3ef22d920631bc011e82babe03ad5d72b3ba7f95bf646f20ccf6f7a4d95de37397c76c7d53741458e51ab6074007f61181c7b88b7c98f5b7510c8dfa3be01f4841501679478b15c5249d928e2a10d15ec63efa1500b994d5bfb32ffb174a976116930eb97a111e6dfd4c5e43e04a5d76ba74806a62fda63a8c3f53f6eebaf852892340e81dd08bbf348454a2cf525aeb512cf33aeeee78465ee4c442e41cc45ac4e3bb0c3333677aa60332ee7f464d9020f8554b82d619872477cca18d8431888f4ae8abe5894e9720f759c410cd7991db12703dc147040dd0d3758223e0b75de6ceae49c1a0c2c45efedeb7114ae785cc886afdc45c82172e4476e1ab5b86dc4314dd76";
String SIG2 = "c2c10400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267a4d9c117dc7ba3a7e9270856f128d2ab271743eac3cb5750b22a89bd5fd60753162104d1a66e1a23b182c9980f788cfbfcc82a015e73300000b8400bff796c20fa8b25ff7a42686338e06417a2966e85a0fc2723c928bef6cd19d34cf5e7d55ada33080613012dadb79e0278e59d9e7ed7d2d6102912a5f768c2e75b60099225c3d8bfe0c123240188b80dbee89b9b3bd5b13ccc662abc37e2129b6968adac9aba43aa778c0fe4fe337591ee87a96a29a013debc83555293c877144fc676aa1b03782c501949521a320adf6ad96c4f2e036b52a18369c637fdc49033696a84d03a69580b953187fce5aca6fb26fc8815da9f3b513bfe8e304f33ecb4b521aeb7d09c4a284ea66123bd0d6a358b2526d762ca110e1f7f20b3038d774b64d5cfd34e2213765828359d7afc5bf24d5270e99d80c3c1568fa01624b6ea1e9ce4e6890ce9bacf6611a45d41e2671f68f5b096446bf08d27ce75608425b2e3ab92146229ad1fcd8224aca5b5f73960506e7df07bfbf3664348e8ecbfb2eb467b9cfe412cb377a6ee2eb5fd11be9cf9208fe9a74c296f52cfa02a1eb0519ad9a8349bf6ccd6495feb7e391451bf96e08a0798883dee5974e47cbf3b51f111b6d3";
String SIG2f = "c2c13b0400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267a4d9c117dc7ba3a7e9270856f128d2ab271743eac3cb5750b22a89bd5fd60753162104d1a66e1a23b182c9980f788cfbfcc82a015e73300000b8400bff796c20fa8b25ff7a42686338e06417a2966e85a0fc2723c928bef6cd19d34cf5e7d55ada33080613012dadb79e0278e59d9e7ed7d2d6102912a5f768c2e75b60099225c3d8bfe0c123240188b80dbee89b9b3bd5b13ccc662abc37e2129b6968adac9aba43aa778c0fe4fe337591ee87a96a29a013debc83555293c877144fc676aa1b03782c501949521a320adf6ad96c4f2e036b52a18369c637fdc49033696a84d03a69580b953187fce5aca6fb26fc8815da9f3b513bfe8e304f33ecb4b521aeb7d09c4a284ea66123bd0d6a358b2526d762ca110e1f7f20b3038d774b64d5cfd34e2213765828359d7afc5bf24d5270e99d80c3c1568fa01624b6ea1e9ce4e6890ce9bacf6611a45d41e2671f68f5b096446bf08d27ce75608425b2e3ab92146229ad1fcd8224aca5b5f73960506e7df07bfbf3664348e8ecbfb2eb467b9cfe412cb377a6ee2eb5fd11be9cf9208fe9a74c296f52cfa02a1eb0519ad9a8349bf6ccd6495feb7e391451bf96e08a0798883dee5974e47cbf3b51f111b6d3";
String out = "last=" + opSignature.isContaining() + "\n";
String hex = Hex.toHexString(bytes.toByteArray());
while (hex.contains(OPS)) {
hex = hex.replace(OPS, "[OPS]");
}
while (hex.contains(LIT_H)) {
hex = hex.replace(LIT_H, "[LIT]");
}
while (hex.contains(LIT)) {
hex = hex.replace(LIT, "<content>");
}
while (hex.contains(SIG1)) {
hex = hex.replace(SIG1, "[SIG1]");
}
while (hex.contains(SIG1f)) {
hex = hex.replace(SIG1f, "[SIG1f]");
}
while (hex.contains(SIG2)) {
hex = hex.replace(SIG2, "[SIG2]");
}
while (hex.contains(SIG2f)) {
hex = hex.replace(SIG2f, "[SIG2f]");
}
return out + hex;
}
} }
} }
@ -916,7 +859,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
resultBuilder.setFileEncoding(m.getFormat()); resultBuilder.setFileEncoding(m.getFormat());
resultBuilder.setSessionKey(m.getSessionKey()); resultBuilder.setSessionKey(m.getSessionKey());
for (Signatures.OPS ops : signatures.onePassSignatures) { for (Signatures.OnePassSignature ops : signatures.onePassSignatures) {
if (!ops.finished) { if (!ops.finished) {
continue; continue;
} }
@ -930,7 +873,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
} }
} }
for (Signatures.SIG prep : signatures.prependedSignatures) { for (Signatures.DetachedOrPrependedSignature prep : signatures.prependedSignatures) {
if (!prep.finished) { if (!prep.finished) {
continue; continue;
} }
@ -944,7 +887,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
} }
} }
for (Signatures.SIG det : signatures.detachedSignatures) { for (Signatures.DetachedOrPrependedSignature det : signatures.detachedSignatures) {
if (!det.finished) { if (!det.finished) {
continue; continue;
} }
@ -964,7 +907,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
static void log(String message) { static void log(String message) {
LOGGER.debug(message); LOGGER.debug(message);
// CHECKSTYLE:OFF // CHECKSTYLE:OFF
// System.out.println(message); System.out.println(message);
// CHECKSTYLE:ON // CHECKSTYLE:ON
} }

View file

@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -331,6 +332,8 @@ public class OpenPgpMessageInputStreamTest {
assertEquals("", metadata.getFilename()); assertEquals("", metadata.getFilename());
JUtils.assertDateEquals(new Date(0L), metadata.getModificationDate()); JUtils.assertDateEquals(new Date(0L), metadata.getModificationDate());
assertEquals(StreamEncoding.BINARY, metadata.getFormat()); assertEquals(StreamEncoding.BINARY, metadata.getFormat());
assertTrue(metadata.getVerifiedSignatures().isEmpty());
assertTrue(metadata.getRejectedSignatures().isEmpty());
} }
@ParameterizedTest(name = "Process LIT LIT using {0}") @ParameterizedTest(name = "Process LIT LIT using {0}")
@ -349,6 +352,8 @@ public class OpenPgpMessageInputStreamTest {
assertEquals(PLAINTEXT, plain); assertEquals(PLAINTEXT, plain);
MessageMetadata metadata = result.getB(); MessageMetadata metadata = result.getB();
assertEquals(CompressionAlgorithm.ZIP, metadata.getCompressionAlgorithm()); assertEquals(CompressionAlgorithm.ZIP, metadata.getCompressionAlgorithm());
assertTrue(metadata.getVerifiedSignatures().isEmpty());
assertTrue(metadata.getRejectedSignatures().isEmpty());
} }
@ParameterizedTest(name = "Process COMP using {0}") @ParameterizedTest(name = "Process COMP using {0}")
@ -372,6 +377,8 @@ public class OpenPgpMessageInputStreamTest {
assertEquals(CompressionAlgorithm.BZIP2, compressionAlgorithms.next()); assertEquals(CompressionAlgorithm.BZIP2, compressionAlgorithms.next());
assertFalse(compressionAlgorithms.hasNext()); assertFalse(compressionAlgorithms.hasNext());
assertNull(metadata.getEncryptionAlgorithm()); assertNull(metadata.getEncryptionAlgorithm());
assertTrue(metadata.getVerifiedSignatures().isEmpty());
assertTrue(metadata.getRejectedSignatures().isEmpty());
} }
@ParameterizedTest(name = "Process SIG COMP(LIT) using {0}") @ParameterizedTest(name = "Process SIG COMP(LIT) using {0}")
@ -388,6 +395,8 @@ public class OpenPgpMessageInputStreamTest {
MessageMetadata metadata = result.getB(); MessageMetadata metadata = result.getB();
assertEquals(CompressionAlgorithm.ZIP, metadata.getCompressionAlgorithm()); assertEquals(CompressionAlgorithm.ZIP, metadata.getCompressionAlgorithm());
assertNull(metadata.getEncryptionAlgorithm()); assertNull(metadata.getEncryptionAlgorithm());
assertFalse(metadata.getVerifiedSignatures().isEmpty());
assertTrue(metadata.getRejectedSignatures().isEmpty());
} }
@ParameterizedTest(name = "Process SENC(LIT) using {0}") @ParameterizedTest(name = "Process SENC(LIT) using {0}")
@ -401,6 +410,8 @@ public class OpenPgpMessageInputStreamTest {
MessageMetadata metadata = result.getB(); MessageMetadata metadata = result.getB();
assertNull(metadata.getCompressionAlgorithm()); assertNull(metadata.getCompressionAlgorithm());
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm()); assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
assertTrue(metadata.getVerifiedSignatures().isEmpty());
assertTrue(metadata.getRejectedSignatures().isEmpty());
} }
@ParameterizedTest(name = "Process PENC(COMP(LIT)) using {0}") @ParameterizedTest(name = "Process PENC(COMP(LIT)) using {0}")
@ -415,6 +426,8 @@ public class OpenPgpMessageInputStreamTest {
MessageMetadata metadata = result.getB(); MessageMetadata metadata = result.getB();
assertEquals(CompressionAlgorithm.ZLIB, metadata.getCompressionAlgorithm()); assertEquals(CompressionAlgorithm.ZLIB, metadata.getCompressionAlgorithm());
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm()); assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
assertTrue(metadata.getVerifiedSignatures().isEmpty());
assertTrue(metadata.getRejectedSignatures().isEmpty());
} }
@ParameterizedTest(name = "Process OPS LIT SIG using {0}") @ParameterizedTest(name = "Process OPS LIT SIG using {0}")
@ -429,6 +442,8 @@ public class OpenPgpMessageInputStreamTest {
MessageMetadata metadata = result.getB(); MessageMetadata metadata = result.getB();
assertNull(metadata.getEncryptionAlgorithm()); assertNull(metadata.getEncryptionAlgorithm());
assertNull(metadata.getCompressionAlgorithm()); assertNull(metadata.getCompressionAlgorithm());
assertFalse(metadata.getVerifiedSignatures().isEmpty());
assertTrue(metadata.getRejectedSignatures().isEmpty());
} }
String BOB_KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" + String BOB_KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
@ -564,6 +579,8 @@ public class OpenPgpMessageInputStreamTest {
MessageMetadata metadata = result.getB(); MessageMetadata metadata = result.getB();
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm()); assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
assertNull(metadata.getCompressionAlgorithm()); assertNull(metadata.getCompressionAlgorithm());
assertFalse(metadata.getVerifiedSignatures().isEmpty());
assertTrue(metadata.getRejectedSignatures().isEmpty());
} }
@ParameterizedTest(name = "Process PENC(OPS OPS OPS LIT SIG SIG SIG) using {0}") @ParameterizedTest(name = "Process PENC(OPS OPS OPS LIT SIG SIG SIG) using {0}")
@ -627,6 +644,8 @@ public class OpenPgpMessageInputStreamTest {
MessageMetadata metadata = result.getB(); MessageMetadata metadata = result.getB();
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm()); assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
assertNull(metadata.getCompressionAlgorithm()); assertNull(metadata.getCompressionAlgorithm());
assertFalse(metadata.getVerifiedSignatures().isEmpty());
assertTrue(metadata.getRejectedSignatures().isEmpty());
} }
private static Tuple<String, MessageMetadata> processReadBuffered(String armoredMessage, ConsumerOptions options) private static Tuple<String, MessageMetadata> processReadBuffered(String armoredMessage, ConsumerOptions options)