mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-25 12:27:58 +01:00
2/3 the way to working sig verification
This commit is contained in:
parent
1448e7a29e
commit
a1feedcc84
5 changed files with 353 additions and 279 deletions
|
@ -0,0 +1,38 @@
|
||||||
|
package org.pgpainless.decryption_verification;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class DelayedTeeInputStreamInputStream extends InputStream {
|
||||||
|
|
||||||
|
private int last = -1;
|
||||||
|
private final InputStream inputStream;
|
||||||
|
private final OutputStream outputStream;
|
||||||
|
|
||||||
|
public DelayedTeeInputStreamInputStream(InputStream inputStream, OutputStream outputStream) {
|
||||||
|
this.inputStream = inputStream;
|
||||||
|
this.outputStream = outputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
if (last != -1) {
|
||||||
|
outputStream.write(last);
|
||||||
|
}
|
||||||
|
last = inputStream.read();
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Squeeze the last byte out and update the output stream.
|
||||||
|
*
|
||||||
|
* @throws IOException in case of an IO error
|
||||||
|
*/
|
||||||
|
public void squeeze() throws IOException {
|
||||||
|
if (last != -1) {
|
||||||
|
outputStream.write(last);
|
||||||
|
}
|
||||||
|
last = -1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,6 @@ import org.bouncycastle.openpgp.PGPEncryptedData;
|
||||||
import org.bouncycastle.openpgp.PGPEncryptedDataList;
|
import org.bouncycastle.openpgp.PGPEncryptedDataList;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPLiteralData;
|
import org.bouncycastle.openpgp.PGPLiteralData;
|
||||||
import org.bouncycastle.openpgp.PGPObjectFactory;
|
|
||||||
import org.bouncycastle.openpgp.PGPOnePassSignature;
|
import org.bouncycastle.openpgp.PGPOnePassSignature;
|
||||||
import org.bouncycastle.openpgp.PGPPBEEncryptedData;
|
import org.bouncycastle.openpgp.PGPPBEEncryptedData;
|
||||||
import org.bouncycastle.openpgp.PGPPrivateKey;
|
import org.bouncycastle.openpgp.PGPPrivateKey;
|
||||||
|
@ -53,7 +52,6 @@ import org.pgpainless.key.info.KeyRingInfo;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.protection.UnlockSecretKey;
|
import org.pgpainless.key.protection.UnlockSecretKey;
|
||||||
import org.pgpainless.signature.SignatureUtils;
|
import org.pgpainless.signature.SignatureUtils;
|
||||||
import org.pgpainless.util.ArmorUtils;
|
|
||||||
import org.pgpainless.util.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
import org.pgpainless.util.Tuple;
|
import org.pgpainless.util.Tuple;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -68,6 +66,7 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
protected final OpenPgpMetadata.Builder resultBuilder;
|
protected final OpenPgpMetadata.Builder resultBuilder;
|
||||||
// Pushdown Automaton to verify validity of OpenPGP packet sequence in an OpenPGP message
|
// Pushdown Automaton to verify validity of OpenPGP packet sequence in an OpenPGP message
|
||||||
protected final PDA automaton = new PDA();
|
protected final PDA automaton = new PDA();
|
||||||
|
protected final DelayedTeeInputStreamInputStream delayedTee;
|
||||||
// InputStream of OpenPGP packets of the current layer
|
// InputStream of OpenPGP packets of the current layer
|
||||||
protected final BCPGInputStream packetInputStream;
|
protected final BCPGInputStream packetInputStream;
|
||||||
// InputStream of a nested data packet
|
// InputStream of a nested data packet
|
||||||
|
@ -96,8 +95,9 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
this.signatures.addDetachedSignatures(options.getDetachedSignatures());
|
this.signatures.addDetachedSignatures(options.getDetachedSignatures());
|
||||||
}
|
}
|
||||||
|
|
||||||
BCPGInputStream bcpg = BCPGInputStream.wrap(inputStream);
|
delayedTee = new DelayedTeeInputStreamInputStream(inputStream, signatures);
|
||||||
this.packetInputStream = new TeeBCPGInputStream(bcpg, signatures);
|
BCPGInputStream bcpg = BCPGInputStream.wrap(delayedTee);
|
||||||
|
this.packetInputStream = bcpg;
|
||||||
|
|
||||||
// *omnomnom*
|
// *omnomnom*
|
||||||
consumePackets();
|
consumePackets();
|
||||||
|
@ -121,22 +121,15 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
*/
|
*/
|
||||||
private void consumePackets()
|
private void consumePackets()
|
||||||
throws IOException, PGPException {
|
throws IOException, PGPException {
|
||||||
int tag;
|
|
||||||
loop: while ((tag = nextTag()) != -1) {
|
|
||||||
OpenPgpPacket nextPacket;
|
OpenPgpPacket nextPacket;
|
||||||
try {
|
loop: while ((nextPacket = nextPacketTag()) != null) {
|
||||||
nextPacket = OpenPgpPacket.requireFromTag(tag);
|
|
||||||
} catch (NoSuchElementException e) {
|
|
||||||
log("Invalid tag: " + tag);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
log(nextPacket.toString());
|
|
||||||
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);
|
automaton.next(InputAlphabet.LiteralData);
|
||||||
|
delayedTee.squeeze();
|
||||||
processLiteralData();
|
processLiteralData();
|
||||||
break loop;
|
break loop;
|
||||||
|
|
||||||
|
@ -145,12 +138,14 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
automaton.next(InputAlphabet.CompressedData);
|
automaton.next(InputAlphabet.CompressedData);
|
||||||
signatures.commitNested();
|
signatures.commitNested();
|
||||||
processCompressedData();
|
processCompressedData();
|
||||||
|
delayedTee.squeeze();
|
||||||
break loop;
|
break loop;
|
||||||
|
|
||||||
// One Pass Signature
|
// One Pass Signature
|
||||||
case OPS:
|
case OPS:
|
||||||
automaton.next(InputAlphabet.OnePassSignatures);
|
automaton.next(InputAlphabet.OnePassSignatures);
|
||||||
PGPOnePassSignature onePassSignature = readOnePassSignature();
|
PGPOnePassSignature onePassSignature = readOnePassSignature();
|
||||||
|
delayedTee.squeeze();
|
||||||
signatures.addOnePassSignature(onePassSignature);
|
signatures.addOnePassSignature(onePassSignature);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -160,6 +155,7 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
automaton.next(InputAlphabet.Signatures);
|
automaton.next(InputAlphabet.Signatures);
|
||||||
|
|
||||||
PGPSignature signature = readSignature();
|
PGPSignature signature = readSignature();
|
||||||
|
delayedTee.squeeze();
|
||||||
processSignature(signature, isSigForOPS);
|
processSignature(signature, isSigForOPS);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -170,6 +166,7 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
case SED:
|
case SED:
|
||||||
case SEIPD:
|
case SEIPD:
|
||||||
automaton.next(InputAlphabet.EncryptedData);
|
automaton.next(InputAlphabet.EncryptedData);
|
||||||
|
delayedTee.squeeze();
|
||||||
if (processEncryptedData()) {
|
if (processEncryptedData()) {
|
||||||
break loop;
|
break loop;
|
||||||
}
|
}
|
||||||
|
@ -179,6 +176,7 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
// Marker Packets need to be skipped and ignored
|
// Marker Packets need to be skipped and ignored
|
||||||
case MARKER:
|
case MARKER:
|
||||||
packetInputStream.readPacket(); // skip
|
packetInputStream.readPacket(); // skip
|
||||||
|
delayedTee.squeeze();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Key Packets are illegal in this context
|
// Key Packets are illegal in this context
|
||||||
|
@ -206,6 +204,23 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private OpenPgpPacket nextPacketTag() throws IOException {
|
||||||
|
int tag = nextTag();
|
||||||
|
if (tag == -1) {
|
||||||
|
log("EOF");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
OpenPgpPacket packet;
|
||||||
|
try {
|
||||||
|
packet = OpenPgpPacket.requireFromTag(tag);
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
log("Invalid tag: " + tag);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
log(packet.toString());
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
private void processSignature(PGPSignature signature, boolean isSigForOPS) {
|
private void processSignature(PGPSignature signature, boolean isSigForOPS) {
|
||||||
if (isSigForOPS) {
|
if (isSigForOPS) {
|
||||||
signatures.popNested();
|
signatures.popNested();
|
||||||
|
@ -229,41 +244,6 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
nestedInputStream = literalData.getDataStream();
|
nestedInputStream = literalData.getDataStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void debugEncryptedData() throws PGPException, IOException {
|
|
||||||
PGPEncryptedDataList encDataList = new PGPEncryptedDataList(packetInputStream);
|
|
||||||
|
|
||||||
// TODO: Replace with !encDataList.isIntegrityProtected()
|
|
||||||
if (!encDataList.get(0).isIntegrityProtected()) {
|
|
||||||
throw new MessageNotIntegrityProtectedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
SortedESKs esks = new SortedESKs(encDataList);
|
|
||||||
for (PGPPublicKeyEncryptedData pkesk : esks.pkesks) {
|
|
||||||
long keyId = pkesk.getKeyID();
|
|
||||||
PGPSecretKeyRing decryptionKeys = getDecryptionKey(keyId);
|
|
||||||
if (decryptionKeys == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SecretKeyRingProtector protector = options.getSecretKeyProtector(decryptionKeys);
|
|
||||||
PGPSecretKey decryptionKey = decryptionKeys.getSecretKey(keyId);
|
|
||||||
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(decryptionKey, protector);
|
|
||||||
|
|
||||||
PublicKeyDataDecryptorFactory decryptorFactory = ImplementationFactory.getInstance()
|
|
||||||
.getPublicKeyDataDecryptorFactory(privateKey);
|
|
||||||
try {
|
|
||||||
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
|
||||||
InputStream decoder = PGPUtil.getDecoderStream(decrypted);
|
|
||||||
PGPObjectFactory objectFactory = ImplementationFactory.getInstance()
|
|
||||||
.getPGPObjectFactory(decoder);
|
|
||||||
objectFactory.nextObject();
|
|
||||||
objectFactory.nextObject();
|
|
||||||
objectFactory.nextObject();
|
|
||||||
} catch (PGPException e) {
|
|
||||||
// hm :/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean processEncryptedData() throws IOException, PGPException {
|
private boolean processEncryptedData() throws IOException, PGPException {
|
||||||
PGPEncryptedDataList encDataList = new PGPEncryptedDataList(packetInputStream);
|
PGPEncryptedDataList encDataList = new PGPEncryptedDataList(packetInputStream);
|
||||||
|
|
||||||
|
@ -553,12 +533,13 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
// for literal data. UUUUUGLY!!!!
|
// for literal data. UUUUUGLY!!!!
|
||||||
private static final class Signatures extends OutputStream {
|
private static final class Signatures extends OutputStream {
|
||||||
final ConsumerOptions options;
|
final ConsumerOptions options;
|
||||||
final List<PGPSignature> detachedSignatures;
|
final List<SIG> detachedSignatures;
|
||||||
final List<PGPSignature> prependedSignatures;
|
final List<SIG> prependedSignatures;
|
||||||
final List<OPS> onePassSignatures;
|
final List<OPS> onePassSignatures;
|
||||||
final Stack<List<OPS>> opsUpdateStack;
|
final Stack<List<OPS>> opsUpdateStack;
|
||||||
List<OPS> literalOPS = new ArrayList<>();
|
List<OPS> literalOPS = new ArrayList<>();
|
||||||
final List<PGPSignature> correspondingSignatures;
|
final List<PGPSignature> correspondingSignatures;
|
||||||
|
boolean isLiteral = true;
|
||||||
|
|
||||||
private Signatures(ConsumerOptions options) {
|
private Signatures(ConsumerOptions options) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
@ -579,14 +560,14 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
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(signature);
|
this.detachedSignatures.add(new SIG(signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
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(signature);
|
this.prependedSignatures.add(new SIG(signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addOnePassSignature(PGPOnePassSignature signature) {
|
void addOnePassSignature(PGPOnePassSignature signature) {
|
||||||
|
@ -630,7 +611,7 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
opsUpdateStack.pop();
|
opsUpdateStack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize(PGPSignature signature, PGPPublicKeyRing certificate, long keyId) {
|
private static void initialize(PGPSignature signature, PGPPublicKeyRing certificate, long keyId) {
|
||||||
if (certificate == null) {
|
if (certificate == null) {
|
||||||
// SHIT
|
// SHIT
|
||||||
return;
|
return;
|
||||||
|
@ -672,7 +653,7 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
ops.update(b);
|
ops.update(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PGPSignature detached : detachedSignatures) {
|
for (SIG detached : detachedSignatures) {
|
||||||
detached.update(b);
|
detached.update(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -682,13 +663,22 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
ops.update(b, off, len);
|
ops.update(b, off, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PGPSignature detached : detachedSignatures) {
|
for (SIG detached : detachedSignatures) {
|
||||||
detached.update(b, off, len);
|
detached.update(b, off, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updatePacket(byte b) {
|
public void updatePacket(byte b) {
|
||||||
for (List<OPS> nestedOPSs : opsUpdateStack) {
|
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) {
|
for (OPS ops : nestedOPSs) {
|
||||||
ops.update(b);
|
ops.update(b);
|
||||||
}
|
}
|
||||||
|
@ -696,6 +686,14 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
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<OPS> nestedOPSs = opsUpdateStack.get(i);
|
||||||
for (OPS ops : nestedOPSs) {
|
for (OPS ops : nestedOPSs) {
|
||||||
|
@ -705,24 +703,16 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish() {
|
public void finish() {
|
||||||
for (PGPSignature detached : detachedSignatures) {
|
for (SIG detached : detachedSignatures) {
|
||||||
boolean verified = false;
|
boolean verified = detached.verify();
|
||||||
try {
|
log("Detached Signature by " + Long.toHexString(detached.signature.getKeyID()) + " is " + (verified ? "verified" : "unverified"));
|
||||||
verified = detached.verify();
|
System.out.println(detached);
|
||||||
} catch (PGPException e) {
|
|
||||||
log("Cannot verify detached signature.", e);
|
|
||||||
}
|
|
||||||
log("Detached Signature by " + Long.toHexString(detached.getKeyID()) + " is " + (verified ? "verified" : "unverified"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PGPSignature prepended : prependedSignatures) {
|
for (SIG prepended : prependedSignatures) {
|
||||||
boolean verified = false;
|
boolean verified = prepended.verify();
|
||||||
try {
|
log("Prepended Signature by " + Long.toHexString(prepended.signature.getKeyID()) + " is " + (verified ? "verified" : "unverified"));
|
||||||
verified = prepended.verify();
|
System.out.println(prepended);
|
||||||
} catch (PGPException e) {
|
|
||||||
log("Cannot verify prepended signature.", e);
|
|
||||||
}
|
|
||||||
log("Prepended Signature by " + Long.toHexString(prepended.getKeyID()) + " is " + (verified ? "verified" : "unverified"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,9 +728,92 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
|
|
||||||
public void nextPacket(OpenPgpPacket nextPacket) {
|
public void nextPacket(OpenPgpPacket nextPacket) {
|
||||||
if (nextPacket == OpenPgpPacket.LIT) {
|
if (nextPacket == OpenPgpPacket.LIT) {
|
||||||
|
isLiteral = true;
|
||||||
if (literalOPS.isEmpty() && !opsUpdateStack.isEmpty()) {
|
if (literalOPS.isEmpty() && !opsUpdateStack.isEmpty()) {
|
||||||
literalOPS = opsUpdateStack.pop();
|
literalOPS = opsUpdateStack.pop();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
isLiteral = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SIG {
|
||||||
|
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||||
|
PGPSignature signature;
|
||||||
|
boolean finished;
|
||||||
|
boolean valid;
|
||||||
|
|
||||||
|
public SIG(PGPSignature signature) {
|
||||||
|
this.signature = signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(PGPPublicKeyRing certificate) {
|
||||||
|
initialize(signature, certificate, signature.getKeyID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean verify() {
|
||||||
|
finished = true;
|
||||||
|
try {
|
||||||
|
valid = this.signature.verify();
|
||||||
|
} catch (PGPException e) {
|
||||||
|
log("Cannot verify SIG " + signature.getKeyID());
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(byte b) {
|
||||||
|
if (finished) {
|
||||||
|
log("Updating finished sig!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
signature.update(b);
|
||||||
|
bytes.write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(byte[] bytes, int off, int len) {
|
||||||
|
if (finished) {
|
||||||
|
log("Updating finished sig!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -796,8 +869,10 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
String LIT_H = "cb28620000000000";
|
String LIT_H = "cb28620000000000";
|
||||||
String LIT = "656e637279707420e28898207369676e20e28898207369676e20e28898207369676e";
|
String LIT = "656e637279707420e28898207369676e20e28898207369676e20e28898207369676e";
|
||||||
String SIG1 = "c2c10400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267b0409ed8ea96dac66447bdff5b7b60c9f80a0ab91d257029153dc3b6d8c27b98162104d1a66e1a23b182c9980f788cfbfcc82a015e7330000029640c00846b5096d92474fd446cc7edaf9f14572cab93a80e12384c1e829f95debc6e8373c2ce5402be53dc1a18cf92a0ed909e0fb38855713ef8ffb13502ffac7c830fa254cc1aa6c666a97b0cc3bc176538f6913d3b8e8981a65cc42df10e0f39e4d0a06dfe961437b59a71892f4fca1116aed15123ea0d86a7b2ce47dd9d3ef22d920631bc011e82babe03ad5d72b3ba7f95bf646f20ccf6f7a4d95de37397c76c7d53741458e51ab6074007f61181c7b88b7c98f5b7510c8dfa3be01f4841501679478b15c5249d928e2a10d15ec63efa1500b994d5bfb32ffb174a976116930eb97a111e6dfd4c5e43e04a5d76ba74806a62fda63a8c3f53f6eebaf852892340e81dd08bbf348454a2cf525aeb512cf33aeeee78465ee4c442e41cc45ac4e3bb0c3333677aa60332ee7f464d9020f8554b82d619872477cca18d8431888f4ae8abe5894e9720f759c410cd7991db12703dc147040dd0d3758223e0b75de6ceae49c1a0c2c45efedeb7114ae785cc886afdc45c82172e4476e1ab5b86dc4314dd76";
|
String SIG1 = "c2c10400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267b0409ed8ea96dac66447bdff5b7b60c9f80a0ab91d257029153dc3b6d8c27b98162104d1a66e1a23b182c9980f788cfbfcc82a015e7330000029640c00846b5096d92474fd446cc7edaf9f14572cab93a80e12384c1e829f95debc6e8373c2ce5402be53dc1a18cf92a0ed909e0fb38855713ef8ffb13502ffac7c830fa254cc1aa6c666a97b0cc3bc176538f6913d3b8e8981a65cc42df10e0f39e4d0a06dfe961437b59a71892f4fca1116aed15123ea0d86a7b2ce47dd9d3ef22d920631bc011e82babe03ad5d72b3ba7f95bf646f20ccf6f7a4d95de37397c76c7d53741458e51ab6074007f61181c7b88b7c98f5b7510c8dfa3be01f4841501679478b15c5249d928e2a10d15ec63efa1500b994d5bfb32ffb174a976116930eb97a111e6dfd4c5e43e04a5d76ba74806a62fda63a8c3f53f6eebaf852892340e81dd08bbf348454a2cf525aeb512cf33aeeee78465ee4c442e41cc45ac4e3bb0c3333677aa60332ee7f464d9020f8554b82d619872477cca18d8431888f4ae8abe5894e9720f759c410cd7991db12703dc147040dd0d3758223e0b75de6ceae49c1a0c2c45efedeb7114ae785cc886afdc45c82172e4476e1ab5b86dc4314dd76";
|
||||||
|
String SIG1f = "c2c13b0400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267b0409ed8ea96dac66447bdff5b7b60c9f80a0ab91d257029153dc3b6d8c27b98162104d1a66e1a23b182c9980f788cfbfcc82a015e7330000029640c00846b5096d92474fd446cc7edaf9f14572cab93a80e12384c1e829f95debc6e8373c2ce5402be53dc1a18cf92a0ed909e0fb38855713ef8ffb13502ffac7c830fa254cc1aa6c666a97b0cc3bc176538f6913d3b8e8981a65cc42df10e0f39e4d0a06dfe961437b59a71892f4fca1116aed15123ea0d86a7b2ce47dd9d3ef22d920631bc011e82babe03ad5d72b3ba7f95bf646f20ccf6f7a4d95de37397c76c7d53741458e51ab6074007f61181c7b88b7c98f5b7510c8dfa3be01f4841501679478b15c5249d928e2a10d15ec63efa1500b994d5bfb32ffb174a976116930eb97a111e6dfd4c5e43e04a5d76ba74806a62fda63a8c3f53f6eebaf852892340e81dd08bbf348454a2cf525aeb512cf33aeeee78465ee4c442e41cc45ac4e3bb0c3333677aa60332ee7f464d9020f8554b82d619872477cca18d8431888f4ae8abe5894e9720f759c410cd7991db12703dc147040dd0d3758223e0b75de6ceae49c1a0c2c45efedeb7114ae785cc886afdc45c82172e4476e1ab5b86dc4314dd76";
|
||||||
String SIG2 = "c2c10400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267a4d9c117dc7ba3a7e9270856f128d2ab271743eac3cb5750b22a89bd5fd60753162104d1a66e1a23b182c9980f788cfbfcc82a015e73300000b8400bff796c20fa8b25ff7a42686338e06417a2966e85a0fc2723c928bef6cd19d34cf5e7d55ada33080613012dadb79e0278e59d9e7ed7d2d6102912a5f768c2e75b60099225c3d8bfe0c123240188b80dbee89b9b3bd5b13ccc662abc37e2129b6968adac9aba43aa778c0fe4fe337591ee87a96a29a013debc83555293c877144fc676aa1b03782c501949521a320adf6ad96c4f2e036b52a18369c637fdc49033696a84d03a69580b953187fce5aca6fb26fc8815da9f3b513bfe8e304f33ecb4b521aeb7d09c4a284ea66123bd0d6a358b2526d762ca110e1f7f20b3038d774b64d5cfd34e2213765828359d7afc5bf24d5270e99d80c3c1568fa01624b6ea1e9ce4e6890ce9bacf6611a45d41e2671f68f5b096446bf08d27ce75608425b2e3ab92146229ad1fcd8224aca5b5f73960506e7df07bfbf3664348e8ecbfb2eb467b9cfe412cb377a6ee2eb5fd11be9cf9208fe9a74c296f52cfa02a1eb0519ad9a8349bf6ccd6495feb7e391451bf96e08a0798883dee5974e47cbf3b51f111b6d3";
|
String SIG2 = "c2c10400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267a4d9c117dc7ba3a7e9270856f128d2ab271743eac3cb5750b22a89bd5fd60753162104d1a66e1a23b182c9980f788cfbfcc82a015e73300000b8400bff796c20fa8b25ff7a42686338e06417a2966e85a0fc2723c928bef6cd19d34cf5e7d55ada33080613012dadb79e0278e59d9e7ed7d2d6102912a5f768c2e75b60099225c3d8bfe0c123240188b80dbee89b9b3bd5b13ccc662abc37e2129b6968adac9aba43aa778c0fe4fe337591ee87a96a29a013debc83555293c877144fc676aa1b03782c501949521a320adf6ad96c4f2e036b52a18369c637fdc49033696a84d03a69580b953187fce5aca6fb26fc8815da9f3b513bfe8e304f33ecb4b521aeb7d09c4a284ea66123bd0d6a358b2526d762ca110e1f7f20b3038d774b64d5cfd34e2213765828359d7afc5bf24d5270e99d80c3c1568fa01624b6ea1e9ce4e6890ce9bacf6611a45d41e2671f68f5b096446bf08d27ce75608425b2e3ab92146229ad1fcd8224aca5b5f73960506e7df07bfbf3664348e8ecbfb2eb467b9cfe412cb377a6ee2eb5fd11be9cf9208fe9a74c296f52cfa02a1eb0519ad9a8349bf6ccd6495feb7e391451bf96e08a0798883dee5974e47cbf3b51f111b6d3";
|
||||||
String out = signature.getKeyID() + " last=" + signature.isContaining() + "\n";
|
String SIG2f = "c2c13b0400010a006f058262c806350910fbfcc82a015e7330471400000000001e002073616c74406e6f746174696f6e732e736571756f69612d7067702e6f7267a4d9c117dc7ba3a7e9270856f128d2ab271743eac3cb5750b22a89bd5fd60753162104d1a66e1a23b182c9980f788cfbfcc82a015e73300000b8400bff796c20fa8b25ff7a42686338e06417a2966e85a0fc2723c928bef6cd19d34cf5e7d55ada33080613012dadb79e0278e59d9e7ed7d2d6102912a5f768c2e75b60099225c3d8bfe0c123240188b80dbee89b9b3bd5b13ccc662abc37e2129b6968adac9aba43aa778c0fe4fe337591ee87a96a29a013debc83555293c877144fc676aa1b03782c501949521a320adf6ad96c4f2e036b52a18369c637fdc49033696a84d03a69580b953187fce5aca6fb26fc8815da9f3b513bfe8e304f33ecb4b521aeb7d09c4a284ea66123bd0d6a358b2526d762ca110e1f7f20b3038d774b64d5cfd34e2213765828359d7afc5bf24d5270e99d80c3c1568fa01624b6ea1e9ce4e6890ce9bacf6611a45d41e2671f68f5b096446bf08d27ce75608425b2e3ab92146229ad1fcd8224aca5b5f73960506e7df07bfbf3664348e8ecbfb2eb467b9cfe412cb377a6ee2eb5fd11be9cf9208fe9a74c296f52cfa02a1eb0519ad9a8349bf6ccd6495feb7e391451bf96e08a0798883dee5974e47cbf3b51f111b6d3";
|
||||||
|
String out = "last=" + signature.isContaining() + "\n";
|
||||||
|
|
||||||
String hex = Hex.toHexString(bytes.toByteArray());
|
String hex = Hex.toHexString(bytes.toByteArray());
|
||||||
while (hex.contains(OPS)) {
|
while (hex.contains(OPS)) {
|
||||||
|
@ -812,9 +887,15 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
while (hex.contains(SIG1)) {
|
while (hex.contains(SIG1)) {
|
||||||
hex = hex.replace(SIG1, "[SIG1]");
|
hex = hex.replace(SIG1, "[SIG1]");
|
||||||
}
|
}
|
||||||
|
while (hex.contains(SIG1f)) {
|
||||||
|
hex = hex.replace(SIG1f, "[SIG1f]");
|
||||||
|
}
|
||||||
while (hex.contains(SIG2)) {
|
while (hex.contains(SIG2)) {
|
||||||
hex = hex.replace(SIG2, "[SIG2]");
|
hex = hex.replace(SIG2, "[SIG2]");
|
||||||
}
|
}
|
||||||
|
while (hex.contains(SIG2f)) {
|
||||||
|
hex = hex.replace(SIG2f, "[SIG2f]");
|
||||||
|
}
|
||||||
|
|
||||||
return out + hex;
|
return out + hex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
package org.pgpainless.decryption_verification;
|
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.BCPGInputStream;
|
|
||||||
import org.pgpainless.util.ArmorUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
public class TeeBCPGInputStream extends BCPGInputStream {
|
|
||||||
|
|
||||||
private final OutputStream out;
|
|
||||||
|
|
||||||
public TeeBCPGInputStream(InputStream in, OutputStream outputStream) {
|
|
||||||
super(in);
|
|
||||||
this.out = outputStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read() throws IOException {
|
|
||||||
int r = super.read();
|
|
||||||
if (r != -1) {
|
|
||||||
out.write(r);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read(byte[] buf, int off, int len) throws IOException {
|
|
||||||
int r = super.read(buf, off, len);
|
|
||||||
if (r > 0) {
|
|
||||||
out.write(buf, off, r);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,7 +4,6 @@ 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;
|
||||||
|
@ -143,11 +142,11 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
"-----BEGIN PGP MESSAGE-----\n" +
|
"-----BEGIN PGP MESSAGE-----\n" +
|
||||||
"Version: PGPainless\n" +
|
"Version: PGPainless\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"hF4Dyqa/GWUy6WsSAQdAQ62BwmUt8Iby0+jvrLhMgST79KR/as+dyl0nf1uki2sw\n" +
|
"hF4Dyqa/GWUy6WsSAQdAuGt49sQwdAHH3jPx11V3wSh7Amur3TbnONiQYJmMo3Qw\n" +
|
||||||
"Thg1Ojtf0hOyJgcpQ4nP2Q0wYFR0F1sCydaIlTGreYZHlGtybP7/Ml6KNZILTRWP\n" +
|
"87yBnZCsaB7evxLBgi6PpF3tiytHM60xlrPeKKPpJhu60vNafRM2OOwqk7AdcZw4\n" +
|
||||||
"0kYBkGBgK7oQWRIVyoF2POvEP6EX1X8nvQk7O3NysVdRVbnia7gE3AzRYuha4kxs\n" +
|
"0kYBEhiioO2btSuafNrQEjYzAgC7K6l7aPCcQObNp4ofryXu1P5vN+vUZp357hyS\n" +
|
||||||
"pI6xJkntLMS3K6him1Y9FHINIASFSB+C\n" +
|
"6zZqP+0wJQ9yJZMvFTtFeSaSi0oMP2sb\n" +
|
||||||
"=5p00\n" +
|
"=LvRL\n" +
|
||||||
"-----END PGP MESSAGE-----";
|
"-----END PGP MESSAGE-----";
|
||||||
|
|
||||||
public static final String OPS_LIT_SIG = "" +
|
public static final String OPS_LIT_SIG = "" +
|
||||||
|
@ -170,8 +169,8 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
// genKey();
|
// genKey();
|
||||||
// genSIG_LIT();
|
// genSIG_LIT();
|
||||||
// genSENC_LIT();
|
// genSENC_LIT();
|
||||||
// genPENC_COMP_LIT();
|
genPENC_COMP_LIT();
|
||||||
genOPS_LIT_SIG();
|
// genOPS_LIT_SIG();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void genLIT() throws IOException {
|
public static void genLIT() throws IOException {
|
||||||
|
@ -433,10 +432,7 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
assertNull(metadata.getCompressionAlgorithm());
|
assertNull(metadata.getCompressionAlgorithm());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = "Process PENC(OPS OPS OPS LIT SIG SIG SIG) using {0}")
|
String BOB_KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
||||||
@MethodSource("provideMessageProcessors")
|
|
||||||
public void testProcessOPS_OPS_OPS_LIT_SIG_SIG_SIG(Processor processor) throws IOException, PGPException {
|
|
||||||
String KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
|
||||||
"Comment: Bob's OpenPGP Transferable Secret Key\n" +
|
"Comment: Bob's OpenPGP Transferable Secret Key\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"lQVYBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv\n" +
|
"lQVYBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv\n" +
|
||||||
|
@ -518,6 +514,62 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
"xqAY9Bwizt4FWgXuLm1a4+So4V9j1TRCXd12Uc2l2RNmgDE=\n" +
|
"xqAY9Bwizt4FWgXuLm1a4+So4V9j1TRCXd12Uc2l2RNmgDE=\n" +
|
||||||
"=miES\n" +
|
"=miES\n" +
|
||||||
"-----END PGP PRIVATE KEY BLOCK-----";
|
"-----END PGP PRIVATE KEY BLOCK-----";
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "Process PENC(OPS OPS LIT SIG SIG) using {0}")
|
||||||
|
@MethodSource("provideMessageProcessors")
|
||||||
|
public void testProcessPENC_OPS_OPS_LIT_SIG_SIG(Processor processor) throws IOException, PGPException {
|
||||||
|
String MSG = "-----BEGIN PGP MESSAGE-----\n" +
|
||||||
|
"\n" +
|
||||||
|
"wcDMA3wvqk35PDeyAQv/RhY9sgxMXj1UxumNMOeN+1+c5bB5e3jSrvA93L8yLFqB\n" +
|
||||||
|
"uF4MsFnHNgu3bS+/a3Z63MRdgS3wOxaRrvEE3y0Q316rP0OQxj9c2mMPZdHlIxjL\n" +
|
||||||
|
"KJMzQ6Ofs4kdtapo7plFqKBEEvnp7rF1hFAPxi0/Z+ekuhhOnWg6dZpAZH+s5Li0\n" +
|
||||||
|
"rKUltzFJ0bxPe6LCuwyYnzKnNBJJsQdKwcvX2Ip8+6lTX/DjQR1s5nhIe76GaNcU\n" +
|
||||||
|
"OvXITOynDsGgNfAmrqTVfrVgDvOVgvj46UPAwS02uYNNk8pWlcy4iGYIlQBUHD6P\n" +
|
||||||
|
"k1ieG7ETWsJvStceFqLQVgSDErAga/YXXAJnNUF3PnOxgOlVewdxDCoEeu+3OdQE\n" +
|
||||||
|
"j7hqmTTo3iA5GaTKCOi07NwXoXRhEMN3X6XDI5+ovqzAYaPkITxtqZzoNVKMT5hi\n" +
|
||||||
|
"tRKl0qwHbMsfHRCQesDmDPU4MlI7TH2iX2jMPxaepyAI++NMW7H6w8bYEFaE0O9v\n" +
|
||||||
|
"tiTL2gcYv4O/pGd3isWb0sOkAdz7HkKDdFCUdVMwP25z6dwhEy+oR/q1Le1CjCE/\n" +
|
||||||
|
"kY1bmJCTBmJwf86YGZElxFuvCTUBBX6ChI7+o18fljQE7eIS0GjXkQ1j2zEXxgGy\n" +
|
||||||
|
"Lhq7yCr6XEIVUj0x8J4LU2RthtgyToOH7EjLRUbqBG2PZD5K7L7b+ueLSkCfM5Gr\n" +
|
||||||
|
"isGbTTj6e+TLy6rXGxlNmNDoojpfp/5rRCxrmqPOjBZrNcio8rG19PfBkaw1IXu9\n" +
|
||||||
|
"fV9klsIxQyiOmUIl7sc74tTBwdIq8F6FJ7sJIScSCrzMjy+J+VLaBl1LyKs9cWDr\n" +
|
||||||
|
"vUqHvc9diwFWjbtZ8wQn9TQug5X4m6sT+pl+7UALAGWdyI9ySlSvVmVnGROKehkV\n" +
|
||||||
|
"5VfRds1ICH9Y4XAD7ylzF4dJ0gadtgwD97HLmfApP9IFD/sC4Oy2fu/ERky3Qqrw\n" +
|
||||||
|
"nvxDpFZBAzNiTR5VXlEPH2DeQUL0tyJJtq5InjqJm/F2K6O11Xk/HSm9VP3Bnhbc\n" +
|
||||||
|
"djaA7GTTYTq2MjPIDYq+ujPkD/WDp5a/2MIWS10ucgZIcLEwJeU/OY+98W/ogrd5\n" +
|
||||||
|
"tg03XkKLcGuK6sGv1iYsOGw1vI6RKAkI1j7YBXb7Twb3Ueq/lcRvutgMx/O5k0L5\n" +
|
||||||
|
"+d3kl6XJVQVKneft7C6DEu6boiGQCTtloJFxaJ9POqq6DzTQ5hSGvBNiUuek3HV7\n" +
|
||||||
|
"lHH544/ONgCufprT3cUSU0CW9EVbeHq3st3wKwxT5ei8nd8R+TuwaPI3TBSqeV03\n" +
|
||||||
|
"9fz5x9U2a22Uh53/qux2vAl8DyZHw7VWTP/Bu3eWHiDBEQIQY9BbRMYc7ueNwPii\n" +
|
||||||
|
"EROFOrHikkDr8UPwNC9FmpLd4vmQQfioY1bAuFvDckTrRFRp2ft+8m0oWLuF+3IH\n" +
|
||||||
|
"lJ2ph3w62VbIOmG0dxtI626n32NcPwk6shCP/gtW1ixuLr1OpiEe5slt2eNiPoTG\n" +
|
||||||
|
"CX5UnxzwUkyJ9KgLr3uFkMUwITCF9d2HbnHRaYqVDbQBpZW0wmgtpkTp2tNTExvp\n" +
|
||||||
|
"T2kx8LNHxAYNoSX+OOWvWzimkCO9MUfjpa0i5kVNxHronNcb1hKAU6X/2r2Mt3C4\n" +
|
||||||
|
"sv2m08spJBQJWnaa/8paYm+c8JS8oACD9SK/8Y4E1kNM3yEgk8dM2BLHKN3xkyT6\n" +
|
||||||
|
"iPXHKKgEHivTdpDa8gY81uoqorRHt5gNPDqL/p2ttFquBbQUtRvDCMkvqif5DADS\n" +
|
||||||
|
"wvLnnlOohCnQbFsNtWg5G6UUQ0TYbt6bixHpNcYIuFEJubJOJTuh/paxPgI3xx1q\n" +
|
||||||
|
"AdrStz97gowgNanOc+Quyt+zmb5cFQdAPLj76xv/W9zd4N601C1NE6+UhZ6mx/Ut\n" +
|
||||||
|
"wboetRk4HNcTRmBci5gjNoqB5oQnyAyqhHL1yiD3YmwwELnRwE8563HrHEpU6ziq\n" +
|
||||||
|
"D1pPMF6YBcmSuHp8FubPeef8iGHYEJQscRTIy/sb6YQjgShjE4VXfGJ2vOz3KRfU\n" +
|
||||||
|
"s7O7MH2b1YkDPsTDuLoDjBzDRoA+2vi034km9Qdcs3w8+vrydw4=\n" +
|
||||||
|
"=mdYs\n" +
|
||||||
|
"-----END PGP MESSAGE-----\n";
|
||||||
|
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(BOB_KEY);
|
||||||
|
PGPPublicKeyRing certificate = PGPainless.extractCertificate(secretKeys);
|
||||||
|
|
||||||
|
Tuple<String, MessageMetadata> result = processor.process(MSG, ConsumerOptions.get()
|
||||||
|
.addVerificationCert(certificate)
|
||||||
|
.addDecryptionKey(secretKeys));
|
||||||
|
String plain = result.getA();
|
||||||
|
assertEquals("encrypt ∘ sign ∘ sign", plain);
|
||||||
|
MessageMetadata metadata = result.getB();
|
||||||
|
assertEquals(SymmetricKeyAlgorithm.AES_256, metadata.getEncryptionAlgorithm());
|
||||||
|
assertNull(metadata.getCompressionAlgorithm());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "Process PENC(OPS OPS OPS LIT SIG SIG SIG) using {0}")
|
||||||
|
@MethodSource("provideMessageProcessors")
|
||||||
|
public void testProcessOPS_OPS_OPS_LIT_SIG_SIG_SIG(Processor processor) throws IOException, PGPException {
|
||||||
String MSG = "-----BEGIN PGP MESSAGE-----\n" +
|
String MSG = "-----BEGIN PGP MESSAGE-----\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"wcDMA3wvqk35PDeyAQwA0yaEgydkAMEfl7rDTYVGanLKiFiWIs34mkF+LB8qR5eY\n" +
|
"wcDMA3wvqk35PDeyAQwA0yaEgydkAMEfl7rDTYVGanLKiFiWIs34mkF+LB8qR5eY\n" +
|
||||||
|
@ -565,7 +617,7 @@ public class OpenPgpMessageInputStreamTest {
|
||||||
"x12WVuyITVU3fCfHp6/0A6wPtJezCvoodqPlw/3fd5eSVYzb5C3v564uhz4=\n" +
|
"x12WVuyITVU3fCfHp6/0A6wPtJezCvoodqPlw/3fd5eSVYzb5C3v564uhz4=\n" +
|
||||||
"=JP9T\n" +
|
"=JP9T\n" +
|
||||||
"-----END PGP MESSAGE-----";
|
"-----END PGP MESSAGE-----";
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(KEY);
|
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(BOB_KEY);
|
||||||
PGPPublicKeyRing certificate = PGPainless.extractCertificate(secretKeys);
|
PGPPublicKeyRing certificate = PGPainless.extractCertificate(secretKeys);
|
||||||
|
|
||||||
Tuple<String, MessageMetadata> result = processor.process(MSG, ConsumerOptions.get()
|
Tuple<String, MessageMetadata> result = processor.process(MSG, ConsumerOptions.get()
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
package org.pgpainless.decryption_verification;
|
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.ArmoredInputStream;
|
|
||||||
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
|
||||||
import org.bouncycastle.bcpg.BCPGInputStream;
|
|
||||||
import org.bouncycastle.bcpg.Packet;
|
|
||||||
import org.bouncycastle.openpgp.PGPCompressedData;
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.pgpainless.algorithm.OpenPgpPacket;
|
|
||||||
import org.pgpainless.util.ArmoredInputStreamFactory;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class TeeBCPGInputStreamTest {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(TeeBCPGInputStreamTest.class);
|
|
||||||
private static final String INBAND_SIGNED = "-----BEGIN PGP MESSAGE-----\n" +
|
|
||||||
"Version: PGPainless\n" +
|
|
||||||
"\n" +
|
|
||||||
"owGbwMvMyCUWdXSHvVTUtXbG0yJJDCDgkZqTk6+jEJ5flJOiyNVRysIoxsXAxsqU\n" +
|
|
||||||
"GDiVjUGRUwCmQUyRRWnOn9Z/PIseF3Yz6cCEL05nZDj1OClo75WVTjNmJPemW6qV\n" +
|
|
||||||
"6ki//1K1++2s0qTP+0N11O4z/BVLDDdxnmQryS+5VXjBX7/0Hxnm/eqeX6Zum35r\n" +
|
|
||||||
"M8e7ufwA\n" +
|
|
||||||
"=RDiy\n" +
|
|
||||||
"-----END PGP MESSAGE-----";
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() throws IOException, PGPException {
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
ArmoredOutputStream armorOut = new ArmoredOutputStream(out);
|
|
||||||
|
|
||||||
ByteArrayInputStream bytesIn = new ByteArrayInputStream(INBAND_SIGNED.getBytes(StandardCharsets.UTF_8));
|
|
||||||
ArmoredInputStream armorIn = ArmoredInputStreamFactory.get(bytesIn);
|
|
||||||
BCPGInputStream bcpgIn = new BCPGInputStream(armorIn);
|
|
||||||
TeeBCPGInputStream teeIn = new TeeBCPGInputStream(bcpgIn, armorOut);
|
|
||||||
|
|
||||||
ByteArrayOutputStream nestedOut = new ByteArrayOutputStream();
|
|
||||||
ArmoredOutputStream nestedArmorOut = new ArmoredOutputStream(nestedOut);
|
|
||||||
|
|
||||||
PGPCompressedData compressedData = new PGPCompressedData(teeIn);
|
|
||||||
InputStream nestedStream = compressedData.getDataStream();
|
|
||||||
BCPGInputStream nestedBcpgIn = new BCPGInputStream(nestedStream);
|
|
||||||
TeeBCPGInputStream nestedTeeIn = new TeeBCPGInputStream(nestedBcpgIn, nestedArmorOut);
|
|
||||||
|
|
||||||
int tag;
|
|
||||||
while ((tag = nestedTeeIn.nextPacketTag()) != -1) {
|
|
||||||
LOGGER.debug(OpenPgpPacket.requireFromTag(tag).toString());
|
|
||||||
Packet packet = nestedTeeIn.readPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
nestedArmorOut.close();
|
|
||||||
LOGGER.debug(nestedOut.toString());
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue