From e542c37eb3a673e72775f4eab26ca093281e5656 Mon Sep 17 00:00:00 2001 From: Thialfihar Date: Tue, 4 May 2010 14:07:18 +0000 Subject: [PATCH] use buffers for encryption, so large files work as well... also showing encryption progress with better accuracy, which is especially useful for large encryptions Fixes issue 18. --- src/org/thialfihar/android/apg/Apg.java | 47 +++++++++---------- .../android/apg/DecryptFileActivity.java | 7 +-- .../android/apg/EncryptFileActivity.java | 21 +++++---- .../android/apg/EncryptMessageActivity.java | 6 +-- .../thialfihar/android/apg/MainActivity.java | 3 ++ 5 files changed, 41 insertions(+), 43 deletions(-) diff --git a/src/org/thialfihar/android/apg/Apg.java b/src/org/thialfihar/android/apg/Apg.java index 612f663ce..ea19c1cbe 100644 --- a/src/org/thialfihar/android/apg/Apg.java +++ b/src/org/thialfihar/android/apg/Apg.java @@ -1198,6 +1198,7 @@ public class Apg { } public static void encrypt(InputStream inStream, OutputStream outStream, + long dataLength, boolean armored, long encryptionKeyIds[], long signatureKeyId, String signaturePassPhrase, @@ -1240,23 +1241,13 @@ public class Apg { if (signaturePassPhrase == null) { throw new GeneralException("no pass phrase given"); } + progress.setProgress("extracting signature key...", 0, 100); signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(), new BouncyCastleProvider()); } PGPSignatureGenerator signatureGenerator = null; - progress.setProgress("preparing data...", 0, 100); - - ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); - int n = 0; - byte[] buffer = new byte[1 << 16]; - while ((n = inStream.read(buffer)) > 0) { - byteOut.write(buffer, 0, n); - } - byteOut.close(); - byte messageData[] = byteOut.toByteArray(); - - progress.setProgress("preparing streams...", 20, 100); + progress.setProgress("preparing streams...", 5, 100); // encryptFile and compress input file content PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(symmetricAlgorithm, true, new SecureRandom(), @@ -1275,7 +1266,7 @@ public class Apg { encryptOut = cPk.open(out, new byte[1 << 16]); if (signatureKeyId != 0) { - progress.setProgress("preparing signature...", 30, 100); + progress.setProgress("preparing signature...", 10, 100); signatureGenerator = new PGPSignatureGenerator(signingKey.getPublicKey().getAlgorithm(), hashAlgorithm, @@ -1298,19 +1289,27 @@ public class Apg { PGPLiteralDataGenerator literalGen = new PGPLiteralDataGenerator(); // file name not needed, so empty string OutputStream pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, "", - messageData.length, new Date()); + new Date(), new byte[1 << 16]); - progress.setProgress("encrypting...", 40, 100); - pOut.write(messageData); - - if (signatureKeyId != 0) { - progress.setProgress("finishing signature...", 70, 100); - signatureGenerator.update(messageData); + progress.setProgress("encrypting...", 20, 100); + long done = 0; + int n = 0; + byte[] buffer = new byte[1 << 16]; + while ((n = inStream.read(buffer)) > 0) { + pOut.write(buffer, 0, n); + if (signatureKeyId != 0) { + signatureGenerator.update(buffer, 0, n); + } + done += n; + if (dataLength != 0) { + progress.setProgress((int) (20 + (95 - 20) * done / dataLength), 100); + } } literalGen.close(); if (signatureKeyId != 0) { + progress.setProgress("generating signature...", 95, 100); signatureGenerator.generate().encode(pOut); } compressGen.close(); @@ -1516,7 +1515,7 @@ public class Apg { throw new GeneralException("couldn't find a packet with symmetric encryption"); } - progress.setProgress("decrypting data...", 20, 100); + progress.setProgress("preparing streams...", 20, 100); clear = pbe.getDataStream(passPhrase.toCharArray(), new BouncyCastleProvider()); encryptedData = pbe; } else { @@ -1550,7 +1549,7 @@ public class Apg { throw new PGPException("wrong pass phrase"); } - progress.setProgress("decrypting data...", 30, 100); + progress.setProgress("preparing streams...", 30, 100); clear = pbe.getDataStream(privateKey, new BouncyCastleProvider()); encryptedData = pbe; } @@ -1606,9 +1605,9 @@ public class Apg { } if (dataChunk instanceof PGPLiteralData) { - progress.setProgress("unpacking data...", 70, 100); + progress.setProgress("decrypting data...", 70, 100); PGPLiteralData literalData = (PGPLiteralData) dataChunk; - BufferedOutputStream out = new BufferedOutputStream(outStream); + OutputStream out = outStream; byte[] buffer = new byte[1 << 16]; InputStream dataIn = literalData.getInputStream(); diff --git a/src/org/thialfihar/android/apg/DecryptFileActivity.java b/src/org/thialfihar/android/apg/DecryptFileActivity.java index 49f039423..369d623d2 100644 --- a/src/org/thialfihar/android/apg/DecryptFileActivity.java +++ b/src/org/thialfihar/android/apg/DecryptFileActivity.java @@ -183,14 +183,9 @@ public class DecryptFileActivity extends BaseActivity { try { InputStream in = new FileInputStream(mInputFilename); - ByteArrayOutputStream out = new ByteArrayOutputStream(); + OutputStream out = new FileOutputStream(mOutputFilename); data = Apg.decrypt(in, out, Apg.getPassPhrase(), this, mAssumeSymmetricEncryption); - - out.close(); - OutputStream fileOut = new FileOutputStream(mOutputFilename); - fileOut.write(out.toByteArray()); - fileOut.close(); } catch (PGPException e) { error = e.getMessage(); } catch (IOException e) { diff --git a/src/org/thialfihar/android/apg/EncryptFileActivity.java b/src/org/thialfihar/android/apg/EncryptFileActivity.java index 5168f760f..a4974c263 100644 --- a/src/org/thialfihar/android/apg/EncryptFileActivity.java +++ b/src/org/thialfihar/android/apg/EncryptFileActivity.java @@ -333,7 +333,7 @@ public class EncryptFileActivity extends BaseActivity { } InputStream in = new FileInputStream(mInputFilename); - ByteArrayOutputStream out = new ByteArrayOutputStream(); + OutputStream out = new FileOutputStream(mOutputFilename); String passPhrase = null; if (mEncryptionMode.getCheckedRadioButtonId() == R.id.use_symmetric) { @@ -342,17 +342,18 @@ public class EncryptFileActivity extends BaseActivity { passPhrase = null; } } - Apg.encrypt(in, out, mAsciiArmour.isChecked(), - mEncryptionKeyIds, getSecretKeyId(), - Apg.getPassPhrase(), this, - ((Choice) mAlgorithm.getSelectedItem()).getId(), - getDefaultHashAlgorithm(), - passPhrase); + + File file = new File(mInputFilename); + long fileSize = file.length(); + + Apg.encrypt(in, out, fileSize, mAsciiArmour.isChecked(), + mEncryptionKeyIds, getSecretKeyId(), + Apg.getPassPhrase(), this, + ((Choice) mAlgorithm.getSelectedItem()).getId(), + getDefaultHashAlgorithm(), + passPhrase); out.close(); - OutputStream fileOut = new FileOutputStream(mOutputFilename); - fileOut.write(out.toByteArray()); - fileOut.close(); } catch (FileNotFoundException e) { error = "file not found: " + e.getMessage(); } diff --git a/src/org/thialfihar/android/apg/EncryptMessageActivity.java b/src/org/thialfihar/android/apg/EncryptMessageActivity.java index 367de3856..028a928f6 100644 --- a/src/org/thialfihar/android/apg/EncryptMessageActivity.java +++ b/src/org/thialfihar/android/apg/EncryptMessageActivity.java @@ -193,12 +193,12 @@ public class EncryptMessageActivity extends BaseActivity { message = message.replaceFirst("\n*$", "\n"); } - ByteArrayInputStream in = - new ByteArrayInputStream(Strings.toUTF8ByteArray(message)); + byte[] byteData = Strings.toUTF8ByteArray(message); + ByteArrayInputStream in = new ByteArrayInputStream(byteData); ByteArrayOutputStream out = new ByteArrayOutputStream(); if (encryptIt) { - Apg.encrypt(in, out, true, mEncryptionKeyIds, getSecretKeyId(), + Apg.encrypt(in, out, byteData.length, true, mEncryptionKeyIds, getSecretKeyId(), Apg.getPassPhrase(), this, getDefaultEncryptionAlgorithm(), getDefaultHashAlgorithm(), null); diff --git a/src/org/thialfihar/android/apg/MainActivity.java b/src/org/thialfihar/android/apg/MainActivity.java index 9b1f7afa4..31035a5d9 100644 --- a/src/org/thialfihar/android/apg/MainActivity.java +++ b/src/org/thialfihar/android/apg/MainActivity.java @@ -221,6 +221,9 @@ public class MainActivity extends BaseActivity { SpannableString info = new SpannableString("Read the warnings!\n\n" + "Changes:\n" + + "* fixed several crashes\n" + + "* can encrypt large files\n" + + "* better progress bar calculation\n" + "\n" + "WARNING: be careful editing your existing keys, as they " + "WILL be stripped of certificates right now.\n" +