mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-23 19:38:00 +01:00
Add option to force handling of data as non-openpgp
This commit is contained in:
parent
8172aa1083
commit
230725f6ff
3 changed files with 38 additions and 37 deletions
|
@ -36,6 +36,7 @@ public class ConsumerOptions {
|
||||||
|
|
||||||
|
|
||||||
private boolean ignoreMDCErrors = false;
|
private boolean ignoreMDCErrors = false;
|
||||||
|
private boolean forceNonOpenPgpData = false;
|
||||||
|
|
||||||
private Date verifyNotBefore = null;
|
private Date verifyNotBefore = null;
|
||||||
private Date verifyNotAfter = new Date();
|
private Date verifyNotAfter = new Date();
|
||||||
|
@ -296,6 +297,21 @@ public class ConsumerOptions {
|
||||||
return ignoreMDCErrors;
|
return ignoreMDCErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force PGPainless to handle the data provided by the {@link InputStream} as non-OpenPGP data.
|
||||||
|
* This workaround might come in handy if PGPainless accidentally mistakes the data for binary OpenPGP data.
|
||||||
|
*
|
||||||
|
* @return options
|
||||||
|
*/
|
||||||
|
public ConsumerOptions forceNonOpenPgpData() {
|
||||||
|
this.forceNonOpenPgpData = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isForceNonOpenPgpData() {
|
||||||
|
return forceNonOpenPgpData;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the {@link MissingKeyPassphraseStrategy}.
|
* Specify the {@link MissingKeyPassphraseStrategy}.
|
||||||
* This strategy defines, how missing passphrases for unlocking secret keys are handled.
|
* This strategy defines, how missing passphrases for unlocking secret keys are handled.
|
||||||
|
|
|
@ -134,7 +134,7 @@ public final class DecryptionStreamFactory {
|
||||||
PGPObjectFactory objectFactory;
|
PGPObjectFactory objectFactory;
|
||||||
|
|
||||||
// Non-OpenPGP data. We are probably verifying detached signatures
|
// Non-OpenPGP data. We are probably verifying detached signatures
|
||||||
if (openPgpIn.isNonOpenPgp()) {
|
if (openPgpIn.isNonOpenPgp() || options.isForceNonOpenPgpData()) {
|
||||||
outerDecodingStream = openPgpIn;
|
outerDecodingStream = openPgpIn;
|
||||||
pgpInStream = wrapInVerifySignatureStream(outerDecodingStream, null);
|
pgpInStream = wrapInVerifySignatureStream(outerDecodingStream, null);
|
||||||
return new DecryptionStream(pgpInStream, resultBuilder, integrityProtectedEncryptedInputStream, null);
|
return new DecryptionStream(pgpInStream, resultBuilder, integrityProtectedEncryptedInputStream, null);
|
||||||
|
|
|
@ -18,7 +18,7 @@ public class OpenPgpInputStream extends BufferedInputStream {
|
||||||
private static final byte[] ARMOR_HEADER = "-----BEGIN PGP ".getBytes(Charset.forName("UTF8"));
|
private static final byte[] ARMOR_HEADER = "-----BEGIN PGP ".getBytes(Charset.forName("UTF8"));
|
||||||
|
|
||||||
// Buffer beginning bytes of the data
|
// Buffer beginning bytes of the data
|
||||||
public static final int MAX_BUFFER_SIZE = 8192;
|
public static final int MAX_BUFFER_SIZE = 8192 * 2;
|
||||||
|
|
||||||
private final byte[] buffer;
|
private final byte[] buffer;
|
||||||
private final int bufferLen;
|
private final int bufferLen;
|
||||||
|
@ -53,6 +53,14 @@ public class OpenPgpInputStream extends BufferedInputStream {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is still brittle.
|
||||||
|
* Basically we try to parse OpenPGP packets from the buffer.
|
||||||
|
* If we run into exceptions, then we know that the data is non-OpenPGP'ish.
|
||||||
|
*
|
||||||
|
* This breaks down though if we read plausible garbage where the data accidentally makes sense,
|
||||||
|
* or valid, yet incomplete packets (remember, we are still only working on a portion of the data).
|
||||||
|
*/
|
||||||
private void determineIsBinaryOpenPgp() {
|
private void determineIsBinaryOpenPgp() {
|
||||||
if (bufferLen == -1) {
|
if (bufferLen == -1) {
|
||||||
// Empty data
|
// Empty data
|
||||||
|
@ -62,47 +70,24 @@ public class OpenPgpInputStream extends BufferedInputStream {
|
||||||
try {
|
try {
|
||||||
ByteArrayInputStream bufferIn = new ByteArrayInputStream(buffer, 0, bufferLen);
|
ByteArrayInputStream bufferIn = new ByteArrayInputStream(buffer, 0, bufferLen);
|
||||||
PGPObjectFactory objectFactory = ImplementationFactory.getInstance().getPGPObjectFactory(bufferIn);
|
PGPObjectFactory objectFactory = ImplementationFactory.getInstance().getPGPObjectFactory(bufferIn);
|
||||||
|
|
||||||
|
boolean containsPackets = false;
|
||||||
while (objectFactory.nextObject() != null) {
|
while (objectFactory.nextObject() != null) {
|
||||||
// read all packets in buffer
|
containsPackets = true;
|
||||||
|
// read all packets in buffer - hope to confirm invalid data via thrown IOExceptions
|
||||||
}
|
}
|
||||||
containsOpenPgpPackets = true;
|
containsOpenPgpPackets = containsPackets;
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (e.getMessage().contains("premature end of stream in PartialInputStream")) {
|
String msg = e.getMessage();
|
||||||
// We *probably* hit valid, but large OpenPGP data
|
|
||||||
|
// If true, we *probably* hit valid, but large OpenPGP data (not sure though) :/
|
||||||
|
// Otherwise we hit garbage and can be sure that this is no OpenPGP data \o/
|
||||||
|
containsOpenPgpPackets = (msg != null && msg.contains("premature end of stream in PartialInputStream"));
|
||||||
|
|
||||||
// This is not an optimal way of determining the nature of data, but probably the best
|
// This is not an optimal way of determining the nature of data, but probably the best
|
||||||
// we can get from BC.
|
// we can do :/
|
||||||
containsOpenPgpPackets = true;
|
|
||||||
}
|
}
|
||||||
// else: seemingly random, non-OpenPGP data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean startsWith(byte[] bytes, byte[] subsequence, int bufferLen) {
|
|
||||||
return indexOfSubsequence(bytes, subsequence, bufferLen) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int indexOfSubsequence(byte[] bytes, byte[] subsequence, int bufferLen) {
|
|
||||||
if (bufferLen == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// Naive implementation
|
|
||||||
// TODO: Could be improved by using e.g. Knuth-Morris-Pratt algorithm.
|
|
||||||
for (int i = 0; i < bufferLen; i++) {
|
|
||||||
if ((i + subsequence.length) <= bytes.length) {
|
|
||||||
boolean found = true;
|
|
||||||
for (int j = 0; j < subsequence.length; j++) {
|
|
||||||
if (bytes[i + j] != subsequence[j]) {
|
|
||||||
found = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean startsWithIgnoringWhitespace(byte[] bytes, byte[] subsequence, int bufferLen) {
|
private boolean startsWithIgnoringWhitespace(byte[] bytes, byte[] subsequence, int bufferLen) {
|
||||||
|
|
Loading…
Reference in a new issue