decryptverify: add trivial detection of pgp ascii-armored data
This commit is contained in:
@@ -535,14 +535,14 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
||||
if (!"".equals(originalFilename)) {
|
||||
log.add(LogType.MSG_DC_CLEAR_META_FILE, indent + 1, originalFilename);
|
||||
}
|
||||
log.add(LogType.MSG_DC_CLEAR_META_MIME, indent + 1,
|
||||
mimeType);
|
||||
log.add(LogType.MSG_DC_CLEAR_META_TIME, indent + 1,
|
||||
new Date(literalData.getModificationTime().getTime()).toString());
|
||||
|
||||
// return here if we want to decrypt the metadata only
|
||||
if (input.isDecryptMetadataOnly()) {
|
||||
|
||||
log.add(LogType.MSG_DC_CLEAR_META_MIME, indent + 1, mimeType);
|
||||
|
||||
// this operation skips the entire stream to find the data length!
|
||||
Long originalSize = literalData.findDataLength();
|
||||
|
||||
@@ -584,6 +584,7 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
||||
long wholeSize = 0; // TODO inputData.getSize() - inputData.getStreamPosition();
|
||||
int length;
|
||||
byte[] buffer = new byte[1 << 16];
|
||||
byte[] firstBytes = new byte[48];
|
||||
while ((length = dataIn.read(buffer)) > 0) {
|
||||
// Log.d(Constants.TAG, "read bytes: " + length);
|
||||
if (out != null) {
|
||||
@@ -595,7 +596,13 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
||||
signature.update(buffer, 0, length);
|
||||
}
|
||||
|
||||
// note down first couple of bytes for "magic bytes" file type detection
|
||||
if (alreadyWritten == 0) {
|
||||
System.arraycopy(buffer, 0, firstBytes, 0, length > firstBytes.length ? firstBytes.length : length);
|
||||
}
|
||||
|
||||
alreadyWritten += length;
|
||||
|
||||
if (wholeSize > 0) {
|
||||
long progress = 100 * alreadyWritten / wholeSize;
|
||||
// stop at 100% for wrong file sizes...
|
||||
@@ -607,6 +614,17 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
||||
// TODO: slow annealing to fake a progress?
|
||||
}
|
||||
|
||||
// special treatment to detect pgp mime types
|
||||
if (matchesPrefix(firstBytes, "-----BEGIN PGP PUBLIC KEY BLOCK-----")
|
||||
|| matchesPrefix(firstBytes, "-----BEGIN PGP PRIVATE KEY BLOCK-----")) {
|
||||
mimeType = "application/pgp-keys";
|
||||
} else if (matchesPrefix(firstBytes, "-----BEGIN PGP MESSAGE-----")) {
|
||||
// this is NOT pgp/encrypted, see RFC 3156!
|
||||
mimeType = "application/pgp-message";
|
||||
}
|
||||
|
||||
log.add(LogType.MSG_DC_CLEAR_META_MIME, indent + 1, mimeType);
|
||||
|
||||
metadata = new OpenPgpMetadata(
|
||||
originalFilename, mimeType, literalData.getModificationTime().getTime(), alreadyWritten, charset);
|
||||
|
||||
@@ -1291,4 +1309,17 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp
|
||||
String nl = System.getProperty("line.separator");
|
||||
return nl.getBytes();
|
||||
}
|
||||
|
||||
/// Convenience method - Trivially checks if a byte array matches the bytes of a plain text string
|
||||
// Assumes data.length >= needle.length()
|
||||
static boolean matchesPrefix(byte[] data, String needle) {
|
||||
byte[] needleBytes = needle.getBytes();
|
||||
for (int i = 0; i < needle.length(); i++) {
|
||||
if (data[i] != needleBytes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -354,6 +354,9 @@ public class ExportTest {
|
||||
"backup_" + KeyFormattingUtils.convertKeyIdToHex(mStaticRing1.getMasterKeyId()) + ".pub.asc",
|
||||
result.getDecryptionMetadata().getFilename());
|
||||
|
||||
assertEquals("mime type for pgp keys must be correctly detected",
|
||||
"application/pgp-keys", result.getDecryptionMetadata().getMimeType());
|
||||
|
||||
TestingUtils.assertArrayEqualsPrefix("exported data must start with ascii armor header",
|
||||
"-----BEGIN PGP PUBLIC KEY BLOCK-----\n".getBytes(), result.getOutputBytes());
|
||||
TestingUtils.assertArrayEqualsSuffix("exported data must end with ascii armor header",
|
||||
|
||||
Reference in New Issue
Block a user