mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-19 10:52:05 +01:00
Wip: Work on OPS verification
This commit is contained in:
parent
e25f6e1712
commit
45555bf82d
1 changed files with 133 additions and 67 deletions
|
@ -56,6 +56,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -64,15 +65,19 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(OpenPgpMessageInputStream.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(OpenPgpMessageInputStream.class);
|
||||||
|
|
||||||
protected final PDA automaton = new PDA();
|
// Options to consume the data
|
||||||
protected final ConsumerOptions options;
|
protected final ConsumerOptions options;
|
||||||
protected final OpenPgpMetadata.Builder resultBuilder;
|
protected final OpenPgpMetadata.Builder resultBuilder;
|
||||||
protected final BCPGInputStream bcpgIn;
|
// Pushdown Automaton to verify validity of OpenPGP packet sequence in an OpenPGP message
|
||||||
protected InputStream in;
|
protected final PDA automaton = new PDA();
|
||||||
|
// InputStream of OpenPGP packets of the current layer
|
||||||
|
protected final BCPGInputStream packetInputStream;
|
||||||
|
// InputStream of a nested data packet
|
||||||
|
protected InputStream nestedInputStream;
|
||||||
|
|
||||||
private boolean closed = false;
|
private boolean closed = false;
|
||||||
|
|
||||||
private Signatures signatures;
|
private final Signatures signatures;
|
||||||
private MessageMetadata.Layer metadata;
|
private MessageMetadata.Layer metadata;
|
||||||
|
|
||||||
public OpenPgpMessageInputStream(InputStream inputStream, ConsumerOptions options)
|
public OpenPgpMessageInputStream(InputStream inputStream, ConsumerOptions options)
|
||||||
|
@ -82,31 +87,45 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
|
|
||||||
OpenPgpMessageInputStream(InputStream inputStream, ConsumerOptions options, MessageMetadata.Layer metadata)
|
OpenPgpMessageInputStream(InputStream inputStream, ConsumerOptions options, MessageMetadata.Layer metadata)
|
||||||
throws PGPException, IOException {
|
throws PGPException, IOException {
|
||||||
// TODO: Use BCPGInputStream.wrap(inputStream);
|
|
||||||
if (inputStream instanceof BCPGInputStream) {
|
|
||||||
this.bcpgIn = (BCPGInputStream) inputStream;
|
|
||||||
} else {
|
|
||||||
this.bcpgIn = new BCPGInputStream(inputStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
this.resultBuilder = OpenPgpMetadata.getBuilder();
|
this.resultBuilder = OpenPgpMetadata.getBuilder();
|
||||||
this.signatures = new Signatures(options);
|
this.signatures = new Signatures(options);
|
||||||
this.signatures.addDetachedSignatures(options.getDetachedSignatures());
|
|
||||||
|
|
||||||
consumePackets(); // nom nom nom
|
// Add detached signatures only on the outermost OpenPgpMessageInputStream
|
||||||
|
if (metadata instanceof MessageMetadata.Message) {
|
||||||
|
this.signatures.addDetachedSignatures(options.getDetachedSignatures());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Use BCPGInputStream.wrap(inputStream);
|
||||||
|
BCPGInputStream bcpg = null;
|
||||||
|
if (inputStream instanceof BCPGInputStream) {
|
||||||
|
bcpg = (BCPGInputStream) inputStream;
|
||||||
|
} else {
|
||||||
|
bcpg = new BCPGInputStream(inputStream);
|
||||||
|
}
|
||||||
|
this.packetInputStream = new TeeBCPGInputStream(bcpg, signatures);
|
||||||
|
|
||||||
|
// *omnomnom*
|
||||||
|
consumePackets();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method consumes OpenPGP packets from the current {@link BCPGInputStream}.
|
* Consume OpenPGP packets from the current {@link BCPGInputStream}.
|
||||||
* Once it reaches a "nested" OpenPGP packet (Literal Data, Compressed Data, Encrypted Data), it sets <pre>in</pre>
|
* Once an OpenPGP packet with nested data (Literal Data, Compressed Data, Encrypted Data) is reached,
|
||||||
* to the nested stream and breaks the loop.
|
* set <pre>nestedInputStream</pre> to the nested stream and breaks the loop.
|
||||||
* The nested stream is either a simple {@link InputStream} (in case of Literal Data), or another
|
* The nested stream is either a simple {@link InputStream} (in case of Literal Data), or another
|
||||||
* {@link OpenPgpMessageInputStream} in case of Compressed and Encrypted Data.
|
* {@link OpenPgpMessageInputStream} in case of Compressed and Encrypted Data.
|
||||||
|
* Once the nested data is processed, this method is called again to consume the remainder
|
||||||
|
* of packets following the nested data packet.
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException in case of an IO error
|
||||||
* @throws PGPException
|
* @throws PGPException in case of an OpenPGP error
|
||||||
|
* @throws MissingDecryptionMethodException if there is an encrypted data packet which cannot be decrypted
|
||||||
|
* due to missing decryption methods (no key, no password, no sessionkey)
|
||||||
|
* @throws MalformedOpenPgpMessageException if the message is made of an invalid packet sequence which
|
||||||
|
* does not follow the packet syntax of RFC4880.
|
||||||
*/
|
*/
|
||||||
private void consumePackets()
|
private void consumePackets()
|
||||||
throws IOException, PGPException {
|
throws IOException, PGPException {
|
||||||
|
@ -127,17 +146,23 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
processCompressedData();
|
processCompressedData();
|
||||||
break loop;
|
break loop;
|
||||||
|
|
||||||
// One Pass Signatures
|
// One Pass Signature
|
||||||
case OPS:
|
case OPS:
|
||||||
automaton.next(InputAlphabet.OnePassSignatures);
|
automaton.next(InputAlphabet.OnePassSignatures);
|
||||||
signatures.addOnePassSignatures(readOnePassSignatures());
|
signatures.addOnePassSignature(readOnePassSignature());
|
||||||
|
// signatures.addOnePassSignatures(readOnePassSignatures());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Signatures - either prepended to the message, or corresponding to the One Pass Signatures
|
// Signature - either prepended to the message, or corresponding to a One Pass Signature
|
||||||
case SIG:
|
case SIG:
|
||||||
boolean isSigForOPS = automaton.peekStack() == StackAlphabet.ops;
|
boolean isSigForOPS = automaton.peekStack() == StackAlphabet.ops;
|
||||||
automaton.next(InputAlphabet.Signatures);
|
automaton.next(InputAlphabet.Signatures);
|
||||||
processSignature(isSigForOPS);
|
PGPSignature signature = readSignature();
|
||||||
|
processSignature(signature, isSigForOPS);
|
||||||
|
/*
|
||||||
|
PGPSignatureList signatureList = readSignatures();
|
||||||
|
processSignatures(signatureList, isSigForOPS);
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Encrypted Data (ESKs and SED/SEIPD are parsed the same by BC)
|
// Encrypted Data (ESKs and SED/SEIPD are parsed the same by BC)
|
||||||
|
@ -154,7 +179,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:
|
||||||
bcpgIn.readPacket(); // skip
|
packetInputStream.readPacket(); // skip
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Key Packets are illegal in this context
|
// Key Packets are illegal in this context
|
||||||
|
@ -182,8 +207,15 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processSignature(boolean isSigForOPS) throws IOException {
|
private void processSignature(PGPSignature signature, boolean isSigForOPS) {
|
||||||
PGPSignatureList signatureList = readSignatures();
|
if (isSigForOPS) {
|
||||||
|
signatures.addOnePassCorrespondingSignature(signature);
|
||||||
|
} else {
|
||||||
|
signatures.addPrependedSignature(signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processSignatures(PGPSignatureList signatureList, boolean isSigForOPS) throws IOException {
|
||||||
if (isSigForOPS) {
|
if (isSigForOPS) {
|
||||||
signatures.addOnePassCorrespondingSignatures(signatureList);
|
signatures.addOnePassCorrespondingSignatures(signatureList);
|
||||||
} else {
|
} else {
|
||||||
|
@ -192,21 +224,21 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processCompressedData() throws IOException, PGPException {
|
private void processCompressedData() throws IOException, PGPException {
|
||||||
PGPCompressedData compressedData = new PGPCompressedData(bcpgIn);
|
PGPCompressedData compressedData = new PGPCompressedData(packetInputStream);
|
||||||
MessageMetadata.CompressedData compressionLayer = new MessageMetadata.CompressedData(
|
MessageMetadata.CompressedData compressionLayer = new MessageMetadata.CompressedData(
|
||||||
CompressionAlgorithm.fromId(compressedData.getAlgorithm()));
|
CompressionAlgorithm.fromId(compressedData.getAlgorithm()));
|
||||||
in = new OpenPgpMessageInputStream(compressedData.getDataStream(), options, compressionLayer);
|
nestedInputStream = new OpenPgpMessageInputStream(compressedData.getDataStream(), options, compressionLayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processLiteralData() throws IOException {
|
private void processLiteralData() throws IOException {
|
||||||
PGPLiteralData literalData = new PGPLiteralData(bcpgIn);
|
PGPLiteralData literalData = new PGPLiteralData(packetInputStream);
|
||||||
this.metadata.setChild(new MessageMetadata.LiteralData(literalData.getFileName(), literalData.getModificationTime(),
|
this.metadata.setChild(new MessageMetadata.LiteralData(literalData.getFileName(), literalData.getModificationTime(),
|
||||||
StreamEncoding.requireFromCode(literalData.getFormat())));
|
StreamEncoding.requireFromCode(literalData.getFormat())));
|
||||||
in = literalData.getDataStream();
|
nestedInputStream = literalData.getDataStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean processEncryptedData() throws IOException, PGPException {
|
private boolean processEncryptedData() throws IOException, PGPException {
|
||||||
PGPEncryptedDataList encDataList = new PGPEncryptedDataList(bcpgIn);
|
PGPEncryptedDataList encDataList = new PGPEncryptedDataList(packetInputStream);
|
||||||
|
|
||||||
// TODO: Replace with !encDataList.isIntegrityProtected()
|
// TODO: Replace with !encDataList.isIntegrityProtected()
|
||||||
if (!encDataList.get(0).isIntegrityProtected()) {
|
if (!encDataList.get(0).isIntegrityProtected()) {
|
||||||
|
@ -225,11 +257,11 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(options.getSessionKey().getAlgorithm());
|
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(options.getSessionKey().getAlgorithm());
|
||||||
if (esk instanceof PGPPBEEncryptedData) {
|
if (esk instanceof PGPPBEEncryptedData) {
|
||||||
PGPPBEEncryptedData skesk = (PGPPBEEncryptedData) esk;
|
PGPPBEEncryptedData skesk = (PGPPBEEncryptedData) esk;
|
||||||
in = new OpenPgpMessageInputStream(skesk.getDataStream(decryptorFactory), options, encryptedData);
|
nestedInputStream = new OpenPgpMessageInputStream(skesk.getDataStream(decryptorFactory), options, encryptedData);
|
||||||
return true;
|
return true;
|
||||||
} else if (esk instanceof PGPPublicKeyEncryptedData) {
|
} else if (esk instanceof PGPPublicKeyEncryptedData) {
|
||||||
PGPPublicKeyEncryptedData pkesk = (PGPPublicKeyEncryptedData) esk;
|
PGPPublicKeyEncryptedData pkesk = (PGPPublicKeyEncryptedData) esk;
|
||||||
in = new OpenPgpMessageInputStream(pkesk.getDataStream(decryptorFactory), options, encryptedData);
|
nestedInputStream = new OpenPgpMessageInputStream(pkesk.getDataStream(decryptorFactory), options, encryptedData);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Unknown ESK class type: " + esk.getClass().getName());
|
throw new RuntimeException("Unknown ESK class type: " + esk.getClass().getName());
|
||||||
|
@ -248,7 +280,7 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
InputStream decrypted = skesk.getDataStream(decryptorFactory);
|
InputStream decrypted = skesk.getDataStream(decryptorFactory);
|
||||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
||||||
SymmetricKeyAlgorithm.requireFromId(skesk.getSymmetricAlgorithm(decryptorFactory)));
|
SymmetricKeyAlgorithm.requireFromId(skesk.getSymmetricAlgorithm(decryptorFactory)));
|
||||||
in = new OpenPgpMessageInputStream(decrypted, options, encryptedData);
|
nestedInputStream = new OpenPgpMessageInputStream(decrypted, options, encryptedData);
|
||||||
return true;
|
return true;
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
// password mismatch? Try next password
|
// password mismatch? Try next password
|
||||||
|
@ -274,7 +306,7 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
||||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
||||||
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)));
|
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)));
|
||||||
in = new OpenPgpMessageInputStream(decrypted, options, encryptedData);
|
nestedInputStream = new OpenPgpMessageInputStream(decrypted, options, encryptedData);
|
||||||
return true;
|
return true;
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
// hm :/
|
// hm :/
|
||||||
|
@ -293,7 +325,7 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
InputStream decrypted = pkesk.getDataStream(decryptorFactory);
|
||||||
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
MessageMetadata.EncryptedData encryptedData = new MessageMetadata.EncryptedData(
|
||||||
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)));
|
SymmetricKeyAlgorithm.requireFromId(pkesk.getSymmetricAlgorithm(decryptorFactory)));
|
||||||
in = new OpenPgpMessageInputStream(decrypted, options, encryptedData);
|
nestedInputStream = new OpenPgpMessageInputStream(decrypted, options, encryptedData);
|
||||||
return true;
|
return true;
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
// hm :/
|
// hm :/
|
||||||
|
@ -307,7 +339,7 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
|
|
||||||
private int nextTag() throws IOException {
|
private int nextTag() throws IOException {
|
||||||
try {
|
try {
|
||||||
return bcpgIn.nextPacketTag();
|
return packetInputStream.nextPacketTag();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if ("Stream closed".equals(e.getMessage())) {
|
if ("Stream closed".equals(e.getMessage())) {
|
||||||
// ZipInflater Streams sometimes close under our feet -.-
|
// ZipInflater Streams sometimes close under our feet -.-
|
||||||
|
@ -345,13 +377,23 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PGPOnePassSignature readOnePassSignature()
|
||||||
|
throws PGPException, IOException {
|
||||||
|
return new PGPOnePassSignature(packetInputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PGPSignature readSignature()
|
||||||
|
throws PGPException, IOException {
|
||||||
|
return new PGPSignature(packetInputStream);
|
||||||
|
}
|
||||||
|
|
||||||
private PGPOnePassSignatureListWrapper readOnePassSignatures() throws IOException {
|
private PGPOnePassSignatureListWrapper readOnePassSignatures() throws IOException {
|
||||||
List<Boolean> encapsulating = new ArrayList<>();
|
List<Boolean> encapsulating = new ArrayList<>();
|
||||||
ByteArrayOutputStream buf = new ByteArrayOutputStream();
|
ByteArrayOutputStream buf = new ByteArrayOutputStream();
|
||||||
BCPGOutputStream bcpgOut = new BCPGOutputStream(buf);
|
BCPGOutputStream bcpgOut = new BCPGOutputStream(buf);
|
||||||
int tag;
|
int tag;
|
||||||
while ((tag = nextTag()) == PacketTags.ONE_PASS_SIGNATURE || tag == PacketTags.MARKER) {
|
while ((tag = nextTag()) == PacketTags.ONE_PASS_SIGNATURE || tag == PacketTags.MARKER) {
|
||||||
Packet packet = bcpgIn.readPacket();
|
Packet packet = packetInputStream.readPacket();
|
||||||
if (tag == PacketTags.ONE_PASS_SIGNATURE) {
|
if (tag == PacketTags.ONE_PASS_SIGNATURE) {
|
||||||
OnePassSignaturePacket sigPacket = (OnePassSignaturePacket) packet;
|
OnePassSignaturePacket sigPacket = (OnePassSignaturePacket) packet;
|
||||||
byte[] bytes = sigPacket.getEncoded();
|
byte[] bytes = sigPacket.getEncoded();
|
||||||
|
@ -371,7 +413,7 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
BCPGOutputStream bcpgOut = new BCPGOutputStream(buf);
|
BCPGOutputStream bcpgOut = new BCPGOutputStream(buf);
|
||||||
int tag = nextTag();
|
int tag = nextTag();
|
||||||
while (tag == PacketTags.SIGNATURE || tag == PacketTags.MARKER) {
|
while (tag == PacketTags.SIGNATURE || tag == PacketTags.MARKER) {
|
||||||
Packet packet = bcpgIn.readPacket();
|
Packet packet = packetInputStream.readPacket();
|
||||||
if (tag == PacketTags.SIGNATURE) {
|
if (tag == PacketTags.SIGNATURE) {
|
||||||
SignaturePacket sigPacket = (SignaturePacket) packet;
|
SignaturePacket sigPacket = (SignaturePacket) packet;
|
||||||
sigPacket.encode(bcpgOut);
|
sigPacket.encode(bcpgOut);
|
||||||
|
@ -387,14 +429,14 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
if (in == null) {
|
if (nestedInputStream == null) {
|
||||||
automaton.assertValid();
|
automaton.assertValid();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
try {
|
try {
|
||||||
r = in.read();
|
r = nestedInputStream.read();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
r = -1;
|
r = -1;
|
||||||
}
|
}
|
||||||
|
@ -403,9 +445,9 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
byte b = (byte) r;
|
byte b = (byte) r;
|
||||||
signatures.update(b);
|
signatures.update(b);
|
||||||
} else {
|
} else {
|
||||||
in.close();
|
nestedInputStream.close();
|
||||||
collectMetadata();
|
collectMetadata();
|
||||||
in = null;
|
nestedInputStream = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
consumePackets();
|
consumePackets();
|
||||||
|
@ -421,16 +463,16 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
public int read(byte[] b, int off, int len)
|
public int read(byte[] b, int off, int len)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
if (in == null) {
|
if (nestedInputStream == null) {
|
||||||
automaton.assertValid();
|
automaton.assertValid();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int r = in.read(b, off, len);
|
int r = nestedInputStream.read(b, off, len);
|
||||||
if (r == -1) {
|
if (r == -1) {
|
||||||
in.close();
|
nestedInputStream.close();
|
||||||
collectMetadata();
|
collectMetadata();
|
||||||
in = null;
|
nestedInputStream = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
consumePackets();
|
consumePackets();
|
||||||
|
@ -449,10 +491,10 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in != null) {
|
if (nestedInputStream != null) {
|
||||||
in.close();
|
nestedInputStream.close();
|
||||||
collectMetadata();
|
collectMetadata();
|
||||||
in = null;
|
nestedInputStream = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -467,8 +509,8 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void collectMetadata() {
|
private void collectMetadata() {
|
||||||
if (in instanceof OpenPgpMessageInputStream) {
|
if (nestedInputStream instanceof OpenPgpMessageInputStream) {
|
||||||
OpenPgpMessageInputStream child = (OpenPgpMessageInputStream) in;
|
OpenPgpMessageInputStream child = (OpenPgpMessageInputStream) nestedInputStream;
|
||||||
MessageMetadata.Layer childLayer = child.metadata;
|
MessageMetadata.Layer childLayer = child.metadata;
|
||||||
this.metadata.setChild((MessageMetadata.Nested) childLayer);
|
this.metadata.setChild((MessageMetadata.Nested) childLayer);
|
||||||
}
|
}
|
||||||
|
@ -533,13 +575,14 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class Signatures {
|
private static final class Signatures extends OutputStream {
|
||||||
final ConsumerOptions options;
|
final ConsumerOptions options;
|
||||||
List<PGPSignature> detachedSignatures = new ArrayList<>();
|
List<PGPSignature> detachedSignatures = new ArrayList<>();
|
||||||
List<PGPSignature> prependedSignatures = new ArrayList<>();
|
List<PGPSignature> prependedSignatures = new ArrayList<>();
|
||||||
List<PGPOnePassSignature> onePassSignatures = new ArrayList<>();
|
List<List<PGPOnePassSignature>> onePassSignatures = new ArrayList<>();
|
||||||
List<PGPSignature> correspondingSignatures = new ArrayList<>();
|
List<PGPSignature> correspondingSignatures = new ArrayList<>();
|
||||||
|
|
||||||
|
boolean lastOpsIsContaining = true;
|
||||||
|
|
||||||
private Signatures(ConsumerOptions options) {
|
private Signatures(ConsumerOptions options) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
@ -547,28 +590,44 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
|
|
||||||
void addDetachedSignatures(Collection<PGPSignature> signatures) {
|
void addDetachedSignatures(Collection<PGPSignature> signatures) {
|
||||||
for (PGPSignature signature : signatures) {
|
for (PGPSignature signature : signatures) {
|
||||||
long keyId = SignatureUtils.determineIssuerKeyId(signature);
|
addDetachedSignature(signature);
|
||||||
PGPPublicKeyRing certificate = findCertificate(keyId);
|
|
||||||
initialize(signature, certificate, keyId);
|
|
||||||
}
|
}
|
||||||
this.detachedSignatures.addAll(signatures);
|
}
|
||||||
|
|
||||||
|
void addDetachedSignature(PGPSignature signature) {
|
||||||
|
long keyId = SignatureUtils.determineIssuerKeyId(signature);
|
||||||
|
PGPPublicKeyRing certificate = findCertificate(keyId);
|
||||||
|
initialize(signature, certificate, keyId);
|
||||||
|
this.detachedSignatures.add(signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPrependedSignatures(PGPSignatureList signatures) {
|
void addPrependedSignatures(PGPSignatureList signatures) {
|
||||||
for (PGPSignature signature : signatures) {
|
for (PGPSignature signature : signatures) {
|
||||||
long keyId = SignatureUtils.determineIssuerKeyId(signature);
|
addPrependedSignature(signature);
|
||||||
PGPPublicKeyRing certificate = findCertificate(keyId);
|
|
||||||
initialize(signature, certificate, keyId);
|
|
||||||
this.prependedSignatures.add(signature);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addOnePassSignatures(PGPOnePassSignatureListWrapper signatures) {
|
void addPrependedSignature(PGPSignature signature) {
|
||||||
for (PGPOnePassSignature ops : signatures.list) {
|
long keyId = SignatureUtils.determineIssuerKeyId(signature);
|
||||||
PGPPublicKeyRing certificate = findCertificate(ops.getKeyID());
|
PGPPublicKeyRing certificate = findCertificate(keyId);
|
||||||
initialize(ops, certificate);
|
initialize(signature, certificate, keyId);
|
||||||
this.onePassSignatures.add(ops);
|
this.prependedSignatures.add(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addOnePassSignature(PGPOnePassSignature signature) {
|
||||||
|
List<PGPOnePassSignature> list;
|
||||||
|
if (lastOpsIsContaining) {
|
||||||
|
list = new ArrayList<>();
|
||||||
|
onePassSignatures.add(list);
|
||||||
|
} else {
|
||||||
|
list = onePassSignatures.get(onePassSignatures.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PGPPublicKeyRing certificate = findCertificate(signature.getKeyID());
|
||||||
|
initialize(signature, certificate);
|
||||||
|
list.add(signature);
|
||||||
|
|
||||||
|
// lastOpsIsContaining = signature.isContaining();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addOnePassCorrespondingSignatures(PGPSignatureList signatures) {
|
void addOnePassCorrespondingSignatures(PGPSignatureList signatures) {
|
||||||
|
@ -618,8 +677,10 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
for (PGPSignature prepended : prependedSignatures) {
|
for (PGPSignature prepended : prependedSignatures) {
|
||||||
prepended.update(b);
|
prepended.update(b);
|
||||||
}
|
}
|
||||||
for (PGPOnePassSignature ops : onePassSignatures) {
|
for (List<PGPOnePassSignature> opss : onePassSignatures) {
|
||||||
ops.update(b);
|
for (PGPOnePassSignature ops : opss) {
|
||||||
|
ops.update(b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (PGPSignature detached : detachedSignatures) {
|
for (PGPSignature detached : detachedSignatures) {
|
||||||
detached.update(b);
|
detached.update(b);
|
||||||
|
@ -660,5 +721,10 @@ public class OpenPgpMessageInputStream extends InputStream {
|
||||||
LOGGER.debug("One-Pass-Signature by " + Long.toHexString(ops.getKeyID()) + " is " + (verified ? "verified" : "unverified"));
|
LOGGER.debug("One-Pass-Signature by " + Long.toHexString(ops.getKeyID()) + " is " + (verified ? "verified" : "unverified"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(int b) throws IOException {
|
||||||
|
update((byte) b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue