mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-17 18:02:05 +01:00
Cleaning up and collect signature verifications
This commit is contained in:
parent
43c369f1f9
commit
a9f77ea100
3 changed files with 262 additions and 217 deletions
|
@ -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() {
|
||||
return findLiteralData().getFileName();
|
||||
}
|
||||
|
@ -132,6 +188,14 @@ public class MessageMetadata {
|
|||
public List<SignatureVerification.Failure> getFailedSignatures() {
|
||||
return new ArrayList<>(failedSignatures);
|
||||
}
|
||||
|
||||
void addVerifiedSignature(SignatureVerification signatureVerification) {
|
||||
verifiedSignatures.add(signatureVerification);
|
||||
}
|
||||
|
||||
void addFailedSignature(SignatureVerification.Failure failure) {
|
||||
failedSignatures.add(failure);
|
||||
}
|
||||
}
|
||||
|
||||
public interface Nested {
|
||||
|
@ -223,9 +287,11 @@ public class MessageMetadata {
|
|||
private abstract static class LayerIterator<O> implements Iterator<O> {
|
||||
private Nested current;
|
||||
Layer last = null;
|
||||
Message parent;
|
||||
|
||||
LayerIterator(Message message) {
|
||||
super();
|
||||
this.parent = message;
|
||||
this.current = message.child;
|
||||
if (matches(current)) {
|
||||
last = (Layer) current;
|
||||
|
@ -234,6 +300,9 @@ public class MessageMetadata {
|
|||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (parent != null && matches(parent)) {
|
||||
return true;
|
||||
}
|
||||
if (last == null) {
|
||||
findNext();
|
||||
}
|
||||
|
@ -242,6 +311,11 @@ public class MessageMetadata {
|
|||
|
||||
@Override
|
||||
public O next() {
|
||||
if (parent != null && matches(parent)) {
|
||||
O property = getProperty(parent);
|
||||
parent = null;
|
||||
return property;
|
||||
}
|
||||
if (last == null) {
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ import org.bouncycastle.openpgp.operator.PBEDataDecryptorFactory;
|
|||
import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider;
|
||||
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
|
||||
import org.bouncycastle.openpgp.operator.SessionKeyDataDecryptorFactory;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.algorithm.CompressionAlgorithm;
|
||||
import org.pgpainless.algorithm.EncryptionPurpose;
|
||||
|
@ -81,16 +80,27 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
private final MessageMetadata.Layer metadata;
|
||||
private final Policy policy;
|
||||
|
||||
public OpenPgpMessageInputStream(InputStream inputStream, ConsumerOptions options)
|
||||
public OpenPgpMessageInputStream(@Nonnull InputStream inputStream,
|
||||
@Nonnull ConsumerOptions options)
|
||||
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 {
|
||||
super(OpenPgpMetadata.getBuilder());
|
||||
|
||||
this.policy = PGPainless.getPolicy();
|
||||
this.policy = policy;
|
||||
this.options = options;
|
||||
this.metadata = metadata;
|
||||
this.signatures = new Signatures(options);
|
||||
|
@ -100,6 +110,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
this.signatures.addDetachedSignatures(options.getDetachedSignatures());
|
||||
}
|
||||
|
||||
// tee out packet bytes for signature verification
|
||||
packetInputStream = new TeeBCPGInputStream(BCPGInputStream.wrap(inputStream), signatures);
|
||||
|
||||
// *omnomnom*
|
||||
|
@ -125,37 +136,30 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
private void consumePackets()
|
||||
throws IOException, PGPException {
|
||||
OpenPgpPacket nextPacket;
|
||||
loop: while ((nextPacket = packetInputStream.nextPacketTag()) != null) {
|
||||
|
||||
loop: // we break this when we go deeper.
|
||||
while ((nextPacket = packetInputStream.nextPacketTag()) != null) {
|
||||
signatures.nextPacket(nextPacket);
|
||||
switch (nextPacket) {
|
||||
|
||||
// Literal Data - the literal data content is the new input stream
|
||||
case LIT:
|
||||
automaton.next(InputAlphabet.LiteralData);
|
||||
processLiteralData();
|
||||
break loop;
|
||||
|
||||
// Compressed Data - the content contains another OpenPGP message
|
||||
case COMP:
|
||||
automaton.next(InputAlphabet.CompressedData);
|
||||
processCompressedData();
|
||||
break loop;
|
||||
|
||||
// One Pass Signature
|
||||
case OPS:
|
||||
automaton.next(InputAlphabet.OnePassSignature);
|
||||
PGPOnePassSignature onePassSignature = readOnePassSignature();
|
||||
signatures.addOnePassSignature(onePassSignature);
|
||||
processOnePassSignature();
|
||||
break;
|
||||
|
||||
// Signature - either prepended to the message, or corresponding to a One Pass Signature
|
||||
case SIG:
|
||||
// true if Signature corresponds to OnePassSignature
|
||||
boolean isSigForOPS = automaton.peekStack() == StackAlphabet.ops;
|
||||
automaton.next(InputAlphabet.Signature);
|
||||
|
||||
processSignature(isSigForOPS);
|
||||
|
||||
processSignature();
|
||||
break;
|
||||
|
||||
// Encrypted Data (ESKs and SED/SEIPD are parsed the same by BC)
|
||||
|
@ -163,14 +167,13 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
case SKESK:
|
||||
case SED:
|
||||
case SEIPD:
|
||||
automaton.next(InputAlphabet.EncryptedData);
|
||||
if (processEncryptedData()) {
|
||||
break loop;
|
||||
}
|
||||
|
||||
throw new MissingDecryptionMethodException("No working decryption method found.");
|
||||
|
||||
// Marker Packets need to be skipped and ignored
|
||||
// Marker Packets need to be skipped and ignored
|
||||
case MARKER:
|
||||
packetInputStream.readMarker();
|
||||
break;
|
||||
|
@ -200,36 +203,51 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
}
|
||||
}
|
||||
|
||||
private void processSignature(boolean isSigForOPS) throws PGPException, IOException {
|
||||
PGPSignature signature = readSignature();
|
||||
if (isSigForOPS) {
|
||||
signatures.leaveNesting(); // TODO: Only leave nesting if all OPSs are dealt with
|
||||
signatures.addCorrespondingOnePassSignature(signature);
|
||||
} else {
|
||||
signatures.addPrependedSignature(signature);
|
||||
}
|
||||
private void processLiteralData() throws IOException {
|
||||
automaton.next(InputAlphabet.LiteralData);
|
||||
PGPLiteralData literalData = packetInputStream.readLiteralData();
|
||||
this.metadata.setChild(new MessageMetadata.LiteralData(
|
||||
literalData.getFileName(),
|
||||
literalData.getModificationTime(),
|
||||
StreamEncoding.requireFromCode(literalData.getFormat())));
|
||||
nestedInputStream = literalData.getDataStream();
|
||||
}
|
||||
|
||||
private void processCompressedData() throws IOException, PGPException {
|
||||
automaton.next(InputAlphabet.CompressedData);
|
||||
signatures.enterNesting();
|
||||
PGPCompressedData compressedData = packetInputStream.readCompressedData();
|
||||
MessageMetadata.CompressedData compressionLayer = new MessageMetadata.CompressedData(
|
||||
CompressionAlgorithm.fromId(compressedData.getAlgorithm()));
|
||||
InputStream decompressed = compressedData.getDataStream();
|
||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decompressed), options, compressionLayer);
|
||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decompressed), options, compressionLayer, policy);
|
||||
}
|
||||
|
||||
private void processLiteralData() throws IOException {
|
||||
PGPLiteralData literalData = packetInputStream.readLiteralData();
|
||||
this.metadata.setChild(new MessageMetadata.LiteralData(literalData.getFileName(), literalData.getModificationTime(),
|
||||
StreamEncoding.requireFromCode(literalData.getFormat())));
|
||||
nestedInputStream = literalData.getDataStream();
|
||||
private void processOnePassSignature() throws PGPException, IOException {
|
||||
automaton.next(InputAlphabet.OnePassSignature);
|
||||
PGPOnePassSignature onePassSignature = packetInputStream.readOnePassSignature();
|
||||
signatures.addOnePassSignature(onePassSignature);
|
||||
}
|
||||
|
||||
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 {
|
||||
automaton.next(InputAlphabet.EncryptedData);
|
||||
PGPEncryptedDataList encDataList = packetInputStream.readEncryptedDataList();
|
||||
|
||||
// TODO: Replace with !encDataList.isIntegrityProtected()
|
||||
// once BC ships it
|
||||
if (!encDataList.get(0).isIntegrityProtected()) {
|
||||
throw new MessageNotIntegrityProtectedException();
|
||||
}
|
||||
|
@ -239,24 +257,25 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
// Try session key
|
||||
if (options.getSessionKey() != null) {
|
||||
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()
|
||||
.getSessionKeyDataDecryptorFactory(sessionKey);
|
||||
// TODO: Replace with encDataList.addSessionKeyDecryptionMethod(sessionKey)
|
||||
PGPEncryptedData esk = esks.all().get(0);
|
||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(sessionKey.getAlgorithm());
|
||||
|
||||
try {
|
||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(sessionKey.getAlgorithm());
|
||||
// TODO: Use BCs new API once shipped
|
||||
PGPEncryptedData esk = esks.all().get(0);
|
||||
if (esk instanceof PGPPBEEncryptedData) {
|
||||
PGPPBEEncryptedData skesk = (PGPPBEEncryptedData) esk;
|
||||
InputStream decrypted = skesk.getDataStream(decryptorFactory);
|
||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData);
|
||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
||||
return true;
|
||||
} else if (esk instanceof PGPPublicKeyEncryptedData) {
|
||||
PGPPublicKeyEncryptedData pkesk = (PGPPublicKeyEncryptedData) esk;
|
||||
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData);
|
||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
||||
return true;
|
||||
} else {
|
||||
throw new RuntimeException("Unknown ESK class type: " + esk.getClass().getName());
|
||||
|
@ -268,19 +287,25 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
|
||||
// Try passwords
|
||||
for (PGPPBEEncryptedData skesk : esks.skesks) {
|
||||
SymmetricKeyAlgorithm kekAlgorithm = SymmetricKeyAlgorithm.requireFromId(skesk.getAlgorithm());
|
||||
throwIfUnacceptable(kekAlgorithm);
|
||||
for (Passphrase passphrase : options.getDecryptionPassphrases()) {
|
||||
PBEDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
||||
.getPBEDataDecryptorFactory(passphrase);
|
||||
try {
|
||||
InputStream decrypted = skesk.getDataStream(decryptorFactory);
|
||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
||||
SymmetricKeyAlgorithm.requireFromId(skesk.getSymmetricAlgorithm(decryptorFactory)));
|
||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData);
|
||||
return true;
|
||||
} catch (PGPException e) {
|
||||
// password mismatch? Try next password
|
||||
}
|
||||
PBEDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
||||
.getPBEDataDecryptorFactory(passphrase);
|
||||
|
||||
try {
|
||||
InputStream decrypted = skesk.getDataStream(decryptorFactory);
|
||||
SymmetricKeyAlgorithm sessionKeyAlgorithm = SymmetricKeyAlgorithm.requireFromId(
|
||||
skesk.getSymmetricAlgorithm(decryptorFactory));
|
||||
throwIfUnacceptable(sessionKeyAlgorithm);
|
||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(sessionKeyAlgorithm);
|
||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
||||
return true;
|
||||
} catch (UnacceptableAlgorithmException e) {
|
||||
throw e;
|
||||
} catch (PGPException e) {
|
||||
// Password mismatch?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,19 +324,17 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
.getPublicKeyDataDecryptorFactory(privateKey);
|
||||
try {
|
||||
SymmetricKeyAlgorithm symAlg = SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory));
|
||||
if (!policy.getSymmetricKeyDecryptionAlgorithmPolicy().isAcceptable(symAlg)) {
|
||||
throw new UnacceptableAlgorithmException("Symmetric-key algorithm " + symAlg + " is not acceptable.");
|
||||
}
|
||||
throwIfUnacceptable(symAlg);
|
||||
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
||||
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)));
|
||||
|
||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData);
|
||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
||||
return true;
|
||||
} catch (UnacceptableAlgorithmException e) {
|
||||
throw e;
|
||||
} catch (PGPException e) {
|
||||
if (e instanceof UnacceptableAlgorithmException) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,7 +350,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
||||
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)));
|
||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData);
|
||||
nestedInputStream = new OpenPgpMessageInputStream(buffer(decrypted), options, encryptedData, policy);
|
||||
return true;
|
||||
} catch (PGPException e) {
|
||||
// hm :/
|
||||
|
@ -339,6 +362,13 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
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) {
|
||||
return new BufferedInputStream(inputStream);
|
||||
}
|
||||
|
@ -370,16 +400,6 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
return null;
|
||||
}
|
||||
|
||||
private PGPOnePassSignature readOnePassSignature()
|
||||
throws PGPException, IOException {
|
||||
return packetInputStream.readOnePassSignature();
|
||||
}
|
||||
|
||||
private PGPSignature readSignature()
|
||||
throws PGPException, IOException {
|
||||
return packetInputStream.readSignature();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (nestedInputStream == null) {
|
||||
|
@ -407,7 +427,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
} catch (PGPException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
signatures.finish();
|
||||
signatures.finish(metadata);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -435,7 +455,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
} catch (PGPException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
signatures.finish();
|
||||
signatures.finish(metadata);
|
||||
}
|
||||
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!!!
|
||||
private static final class Signatures extends OutputStream {
|
||||
final ConsumerOptions options;
|
||||
final List<SIG> detachedSignatures;
|
||||
final List<SIG> prependedSignatures;
|
||||
final List<OPS> onePassSignatures;
|
||||
final Stack<List<OPS>> opsUpdateStack;
|
||||
List<OPS> literalOPS = new ArrayList<>();
|
||||
final List<DetachedOrPrependedSignature> detachedSignatures;
|
||||
final List<DetachedOrPrependedSignature> prependedSignatures;
|
||||
final List<OnePassSignature> onePassSignatures;
|
||||
final Stack<List<OnePassSignature>> opsUpdateStack;
|
||||
List<OnePassSignature> literalOPS = new ArrayList<>();
|
||||
final List<PGPSignature> correspondingSignatures;
|
||||
boolean isLiteral = true;
|
||||
|
||||
|
@ -546,19 +566,19 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
long keyId = SignatureUtils.determineIssuerKeyId(signature);
|
||||
PGPPublicKeyRing certificate = findCertificate(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) {
|
||||
long keyId = SignatureUtils.determineIssuerKeyId(signature);
|
||||
PGPPublicKeyRing certificate = findCertificate(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) {
|
||||
PGPPublicKeyRing certificate = findCertificate(signature.getKeyID());
|
||||
OPS ops = new OPS(signature, certificate, signature.getKeyID());
|
||||
OnePassSignature ops = new OnePassSignature(signature, certificate, signature.getKeyID());
|
||||
ops.init(certificate);
|
||||
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--) {
|
||||
OPS onePassSignature = onePassSignatures.get(i);
|
||||
OnePassSignature onePassSignature = onePassSignatures.get(i);
|
||||
if (onePassSignature.opSignature.getKeyID() != signature.getKeyID()) {
|
||||
continue;
|
||||
}
|
||||
|
@ -579,8 +599,14 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
}
|
||||
|
||||
boolean verified = onePassSignature.verify(signature);
|
||||
log("One-Pass-Signature by " + Long.toHexString(onePassSignature.opSignature.getKeyID()) + " is " + (verified ? "verified" : "unverified"));
|
||||
log(onePassSignature.toString());
|
||||
SignatureVerification verification = new SignatureVerification(signature,
|
||||
new SubkeyIdentifier(onePassSignature.certificate, onePassSignature.keyId));
|
||||
if (verified) {
|
||||
layer.addVerifiedSignature(verification);
|
||||
} else {
|
||||
layer.addFailedSignature(new SignatureVerification.Failure(verification,
|
||||
new SignatureValidationException("Incorrect Signature.")));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -597,11 +623,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
opsUpdateStack.pop();
|
||||
}
|
||||
|
||||
private static void initialize(PGPSignature signature, PGPPublicKeyRing certificate, long keyId) {
|
||||
if (certificate == null) {
|
||||
// SHIT
|
||||
return;
|
||||
}
|
||||
private static void initialize(@Nonnull PGPSignature signature, @Nonnull PGPPublicKeyRing certificate, long keyId) {
|
||||
PGPContentVerifierBuilderProvider verifierProvider = ImplementationFactory.getInstance()
|
||||
.getPGPContentVerifierBuilderProvider();
|
||||
try {
|
||||
|
@ -611,10 +633,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
}
|
||||
}
|
||||
|
||||
private static void initialize(PGPOnePassSignature ops, PGPPublicKeyRing certificate) {
|
||||
if (certificate == null) {
|
||||
return;
|
||||
}
|
||||
private static void initialize(@Nonnull PGPOnePassSignature ops, @Nonnull PGPPublicKeyRing certificate) {
|
||||
PGPContentVerifierBuilderProvider verifierProvider = ImplementationFactory.getInstance()
|
||||
.getPGPContentVerifierBuilderProvider();
|
||||
try {
|
||||
|
@ -635,76 +654,74 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
}
|
||||
|
||||
public void updateLiteral(byte b) {
|
||||
for (OPS ops : literalOPS) {
|
||||
for (OnePassSignature ops : literalOPS) {
|
||||
ops.update(b);
|
||||
}
|
||||
|
||||
for (SIG detached : detachedSignatures) {
|
||||
for (DetachedOrPrependedSignature detached : detachedSignatures) {
|
||||
detached.update(b);
|
||||
}
|
||||
|
||||
for (DetachedOrPrependedSignature prepended : prependedSignatures) {
|
||||
prepended.update(b);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateLiteral(byte[] b, int off, int len) {
|
||||
for (OPS ops : literalOPS) {
|
||||
for (OnePassSignature ops : literalOPS) {
|
||||
ops.update(b, off, len);
|
||||
}
|
||||
|
||||
for (SIG detached : detachedSignatures) {
|
||||
for (DetachedOrPrependedSignature detached : detachedSignatures) {
|
||||
detached.update(b, off, len);
|
||||
}
|
||||
|
||||
for (DetachedOrPrependedSignature prepended : prependedSignatures) {
|
||||
prepended.update(b, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
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--) {
|
||||
List<OPS> nestedOPSs = opsUpdateStack.get(i);
|
||||
for (OPS ops : nestedOPSs) {
|
||||
List<OnePassSignature> nestedOPSs = opsUpdateStack.get(i);
|
||||
for (OnePassSignature ops : nestedOPSs) {
|
||||
ops.update(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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--) {
|
||||
List<OPS> nestedOPSs = opsUpdateStack.get(i);
|
||||
for (OPS ops : nestedOPSs) {
|
||||
List<OnePassSignature> nestedOPSs = opsUpdateStack.get(i);
|
||||
for (OnePassSignature ops : nestedOPSs) {
|
||||
ops.update(buf, off, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void finish() {
|
||||
for (SIG detached : detachedSignatures) {
|
||||
public void finish(MessageMetadata.Layer layer) {
|
||||
for (DetachedOrPrependedSignature detached : detachedSignatures) {
|
||||
boolean verified = detached.verify();
|
||||
SignatureVerification verification = new SignatureVerification(
|
||||
detached.signature, new SubkeyIdentifier(detached.certificate, detached.keyId));
|
||||
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();
|
||||
SignatureVerification verification = new SignatureVerification(
|
||||
prepended.signature, new SubkeyIdentifier(prepended.certificate, prepended.keyId));
|
||||
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();
|
||||
PGPSignature signature;
|
||||
PGPPublicKeyRing certificate;
|
||||
|
@ -737,7 +754,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
boolean finished;
|
||||
boolean valid;
|
||||
|
||||
public SIG(PGPSignature signature, PGPPublicKeyRing certificate, long keyId) {
|
||||
public DetachedOrPrependedSignature(PGPSignature signature, PGPPublicKeyRing certificate, long keyId) {
|
||||
this.signature = signature;
|
||||
this.certificate = certificate;
|
||||
this.keyId = keyId;
|
||||
|
@ -762,8 +779,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
|
||||
public void update(byte b) {
|
||||
if (finished) {
|
||||
log("Updating finished sig!");
|
||||
return;
|
||||
throw new IllegalStateException("Already finished.");
|
||||
}
|
||||
signature.update(b);
|
||||
bytes.write(b);
|
||||
|
@ -771,52 +787,14 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
|
||||
public void update(byte[] bytes, int off, int len) {
|
||||
if (finished) {
|
||||
log("Updating finished sig!");
|
||||
return;
|
||||
throw new IllegalStateException("Already finished.");
|
||||
}
|
||||
signature.update(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 OPS {
|
||||
static class OnePassSignature {
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
PGPOnePassSignature opSignature;
|
||||
PGPSignature signature;
|
||||
|
@ -825,7 +803,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
boolean finished;
|
||||
boolean valid;
|
||||
|
||||
public OPS(PGPOnePassSignature signature, PGPPublicKeyRing certificate, long keyId) {
|
||||
public OnePassSignature(PGPOnePassSignature signature, PGPPublicKeyRing certificate, long keyId) {
|
||||
this.opSignature = signature;
|
||||
this.certificate = certificate;
|
||||
this.keyId = keyId;
|
||||
|
@ -836,6 +814,10 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
}
|
||||
|
||||
public boolean verify(PGPSignature signature) {
|
||||
if (finished) {
|
||||
throw new IllegalStateException("Already finished.");
|
||||
}
|
||||
|
||||
if (this.opSignature.getKeyID() != signature.getKeyID()) {
|
||||
// nope
|
||||
return false;
|
||||
|
@ -852,8 +834,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
|
||||
public void update(byte b) {
|
||||
if (finished) {
|
||||
log("Updating finished sig!");
|
||||
return;
|
||||
throw new IllegalStateException("Already finished.");
|
||||
}
|
||||
opSignature.update(b);
|
||||
bytes.write(b);
|
||||
|
@ -861,49 +842,11 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
|
||||
public void update(byte[] bytes, int off, int len) {
|
||||
if (finished) {
|
||||
log("Updating finished sig!");
|
||||
return;
|
||||
throw new IllegalStateException("Already finished.");
|
||||
}
|
||||
opSignature.update(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.setSessionKey(m.getSessionKey());
|
||||
|
||||
for (Signatures.OPS ops : signatures.onePassSignatures) {
|
||||
for (Signatures.OnePassSignature ops : signatures.onePassSignatures) {
|
||||
if (!ops.finished) {
|
||||
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) {
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
|
@ -964,7 +907,7 @@ public class OpenPgpMessageInputStream extends DecryptionStream {
|
|||
static void log(String message) {
|
||||
LOGGER.debug(message);
|
||||
// CHECKSTYLE:OFF
|
||||
// System.out.println(message);
|
||||
System.out.println(message);
|
||||
// CHECKSTYLE:ON
|
||||
}
|
||||
|
||||
|
|
|
@ -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.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -331,6 +332,8 @@ public class OpenPgpMessageInputStreamTest {
|
|||
assertEquals("", metadata.getFilename());
|
||||
JUtils.assertDateEquals(new Date(0L), metadata.getModificationDate());
|
||||
assertEquals(StreamEncoding.BINARY, metadata.getFormat());
|
||||
assertTrue(metadata.getVerifiedSignatures().isEmpty());
|
||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "Process LIT LIT using {0}")
|
||||
|
@ -349,6 +352,8 @@ public class OpenPgpMessageInputStreamTest {
|
|||
assertEquals(PLAINTEXT, plain);
|
||||
MessageMetadata metadata = result.getB();
|
||||
assertEquals(CompressionAlgorithm.ZIP, metadata.getCompressionAlgorithm());
|
||||
assertTrue(metadata.getVerifiedSignatures().isEmpty());
|
||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "Process COMP using {0}")
|
||||
|
@ -372,6 +377,8 @@ public class OpenPgpMessageInputStreamTest {
|
|||
assertEquals(CompressionAlgorithm.BZIP2, compressionAlgorithms.next());
|
||||
assertFalse(compressionAlgorithms.hasNext());
|
||||
assertNull(metadata.getEncryptionAlgorithm());
|
||||
assertTrue(metadata.getVerifiedSignatures().isEmpty());
|
||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "Process SIG COMP(LIT) using {0}")
|
||||
|
@ -388,6 +395,8 @@ public class OpenPgpMessageInputStreamTest {
|
|||
MessageMetadata metadata = result.getB();
|
||||
assertEquals(CompressionAlgorithm.ZIP, metadata.getCompressionAlgorithm());
|
||||
assertNull(metadata.getEncryptionAlgorithm());
|
||||
assertFalse(metadata.getVerifiedSignatures().isEmpty());
|
||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "Process SENC(LIT) using {0}")
|
||||
|
@ -401,6 +410,8 @@ public class OpenPgpMessageInputStreamTest {
|
|||
MessageMetadata metadata = result.getB();
|
||||
assertNull(metadata.getCompressionAlgorithm());
|
||||
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
|
||||
assertTrue(metadata.getVerifiedSignatures().isEmpty());
|
||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "Process PENC(COMP(LIT)) using {0}")
|
||||
|
@ -415,6 +426,8 @@ public class OpenPgpMessageInputStreamTest {
|
|||
MessageMetadata metadata = result.getB();
|
||||
assertEquals(CompressionAlgorithm.ZLIB, metadata.getCompressionAlgorithm());
|
||||
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
|
||||
assertTrue(metadata.getVerifiedSignatures().isEmpty());
|
||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "Process OPS LIT SIG using {0}")
|
||||
|
@ -429,6 +442,8 @@ public class OpenPgpMessageInputStreamTest {
|
|||
MessageMetadata metadata = result.getB();
|
||||
assertNull(metadata.getEncryptionAlgorithm());
|
||||
assertNull(metadata.getCompressionAlgorithm());
|
||||
assertFalse(metadata.getVerifiedSignatures().isEmpty());
|
||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
||||
}
|
||||
|
||||
String BOB_KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
||||
|
@ -564,6 +579,8 @@ public class OpenPgpMessageInputStreamTest {
|
|||
MessageMetadata metadata = result.getB();
|
||||
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
|
||||
assertNull(metadata.getCompressionAlgorithm());
|
||||
assertFalse(metadata.getVerifiedSignatures().isEmpty());
|
||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "Process PENC(OPS OPS OPS LIT SIG SIG SIG) using {0}")
|
||||
|
@ -627,6 +644,8 @@ public class OpenPgpMessageInputStreamTest {
|
|||
MessageMetadata metadata = result.getB();
|
||||
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
|
||||
assertNull(metadata.getCompressionAlgorithm());
|
||||
assertFalse(metadata.getVerifiedSignatures().isEmpty());
|
||||
assertTrue(metadata.getRejectedSignatures().isEmpty());
|
||||
}
|
||||
|
||||
private static Tuple<String, MessageMetadata> processReadBuffered(String armoredMessage, ConsumerOptions options)
|
||||
|
|
Loading…
Reference in a new issue