diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp')
3 files changed, 54 insertions, 25 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java index 0709d4f62..2d28f70e0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyOperation.java @@ -346,14 +346,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(); @@ -387,6 +387,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) { @@ -396,6 +397,11 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp // update signature buffer if signature is also present signatureChecker.updateSignatureData(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; // noinspection ConstantConditions, TODO progress if (wholeSize > 0) { @@ -408,6 +414,17 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp } } + // 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); @@ -940,4 +957,16 @@ public class PgpDecryptVerifyOperation extends BaseOperation<PgpDecryptVerifyInp 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; + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java index 406c64ae8..ecc190d97 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -53,6 +53,7 @@ import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Passphrase; import org.sufficientlysecure.keychain.util.ProgressScaler; +import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; @@ -361,7 +362,7 @@ public class PgpSignEncryptOperation extends BaseOperation { long alreadyWritten = 0; int length; byte[] buffer = new byte[1 << 16]; - InputStream in = inputData.getInputStream(); + InputStream in = new BufferedInputStream(inputData.getInputStream()); while ((length = in.read(buffer)) > 0) { pOut.write(buffer, 0, length); @@ -389,7 +390,7 @@ public class PgpSignEncryptOperation extends BaseOperation { // write -----BEGIN PGP SIGNED MESSAGE----- armorOut.beginClearText(input.getSignatureHashAlgorithm()); - InputStream in = inputData.getInputStream(); + InputStream in = new BufferedInputStream(inputData.getInputStream()); final BufferedReader reader = new BufferedReader(new InputStreamReader(in)); // update signature buffer with first line @@ -421,7 +422,7 @@ public class PgpSignEncryptOperation extends BaseOperation { updateProgress(R.string.progress_signing, 8, 100); log.add(LogType.MSG_PSE_SIGNING_DETACHED, indent); - InputStream in = inputData.getInputStream(); + InputStream in = new BufferedInputStream(inputData.getInputStream()); // handle output stream separately for detached signatures detachedByteOut = new ByteArrayOutputStream(); @@ -458,7 +459,7 @@ public class PgpSignEncryptOperation extends BaseOperation { updateProgress(R.string.progress_signing, 8, 100); log.add(LogType.MSG_PSE_SIGNING, indent); - InputStream in = inputData.getInputStream(); + InputStream in = new BufferedInputStream(inputData.getInputStream()); if (enableCompression) { compressGen = new PGPCompressedDataGenerator(input.getCompressionAlgorithm()); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 96778649c..c967a5abc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -18,6 +18,23 @@ package org.sufficientlysecure.keychain.pgp; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Comparator; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.TimeZone; +import java.util.TreeSet; + import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.SignatureSubpacketTags; @@ -43,23 +60,6 @@ import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Utf8Util; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Comparator; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; -import java.util.TimeZone; -import java.util.TreeSet; - /** Wrapper around PGPKeyRing class, to be constructed from bytes. * * This class and its relatives UncachedPublicKey and UncachedSecretKey are @@ -78,8 +78,7 @@ import java.util.TreeSet; * @see org.sufficientlysecure.keychain.pgp.UncachedSecretKey * */ -@SuppressWarnings("unchecked") -public class UncachedKeyRing implements Serializable { +public class UncachedKeyRing { final PGPKeyRing mRing; final boolean mIsSecret; |