diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 7f2d971ed..6f34816f1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.pgp; +import org.openintents.openpgp.OpenPgpDecryptMetadata; import org.spongycastle.bcpg.ArmoredInputStream; import org.spongycastle.openpgp.PGPCompressedData; import org.spongycastle.openpgp.PGPEncryptedData; @@ -45,6 +46,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.ProgressScaler; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; @@ -269,8 +271,8 @@ public class PgpDecryptVerify { // allow only specific keys for decryption? if (mAllowedKeyIds != null) { - Log.d(Constants.TAG, "encData.getKeyID():" + encData.getKeyID()); - Log.d(Constants.TAG, "allowedKeyIds: " + mAllowedKeyIds); + Log.d(Constants.TAG, "encData.getKeyID(): " + encData.getKeyID()); + Log.d(Constants.TAG, "mAllowedKeyIds: " + mAllowedKeyIds); Log.d(Constants.TAG, "masterKeyId: " + masterKeyId); if (!mAllowedKeyIds.contains(masterKeyId)) { @@ -344,7 +346,7 @@ public class PgpDecryptVerify { if (!secretEncryptionKey.unlock(mPassphrase)) { throw new WrongPassphraseException(); } - } catch(PgpGeneralException e) { + } catch (PgpGeneralException e) { throw new KeyExtractionException(); } currentProgress += 5; @@ -371,8 +373,9 @@ public class PgpDecryptVerify { if (dataChunk instanceof PGPCompressedData) { updateProgress(R.string.progress_decompressing_data, currentProgress, 100); - PGPObjectFactory fact = new PGPObjectFactory( - ((PGPCompressedData) dataChunk).getDataStream()); + PGPCompressedData compressedData = (PGPCompressedData) dataChunk; + + PGPObjectFactory fact = new PGPObjectFactory(compressedData.getDataStream()); dataChunk = fact.nextObject(); plainFact = fact; currentProgress += 10; @@ -410,8 +413,8 @@ public class PgpDecryptVerify { signatureResultBuilder.keyId(signingRing.getMasterKeyId()); try { signatureResultBuilder.userId(signingRing.getPrimaryUserIdWithFallback()); - } catch(PgpGeneralException e) { - Log.d(Constants.TAG, "No primary user id in key " + signingRing.getMasterKeyId()); + } catch (PgpGeneralException e) { + Log.d(Constants.TAG, "No primary user id in keyring with master key id " + signingRing.getMasterKeyId()); } signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0); @@ -433,6 +436,7 @@ public class PgpDecryptVerify { } if (dataChunk instanceof PGPSignatureList) { + // skip dataChunk = plainFact.nextObject(); } @@ -441,44 +445,67 @@ public class PgpDecryptVerify { PGPLiteralData literalData = (PGPLiteralData) dataChunk; - byte[] buffer = new byte[1 << 16]; - InputStream dataIn = literalData.getInputStream(); + // TODO: how to get the real original size? + // this is the encrypted size + long originalSize = mData.getSize() - mData.getStreamPosition(); + if (originalSize < 0) { + originalSize = 0; + } - int startProgress = currentProgress; - int endProgress = 100; + OpenPgpDecryptMetadata metadata = new OpenPgpDecryptMetadata( + literalData.getFileName(), + literalData.getModificationTime().getTime(), + literalData.getFormat(), + originalSize); + result.setDecryptMetadata(metadata); + + int endProgress; if (signature != null) { endProgress = 90; } else if (encryptedData.isIntegrityProtected()) { endProgress = 95; + } else { + endProgress = 100; } + ProgressScaler progressScaler = + new ProgressScaler(mProgressable, currentProgress, endProgress, 100); - int n; - // TODO: progress calculation is broken here! Try to rework it based on commented code! -// int progress = 0; - long startPos = mData.getStreamPosition(); - while ((n = dataIn.read(buffer)) > 0) { - mOutStream.write(buffer, 0, n); -// progress += n; + InputStream dataIn = literalData.getInputStream(); + + int alreadyWritten = 0; + long wholeSize = mData.getSize() - mData.getStreamPosition(); + Log.d(Constants.TAG, "mData.getStreamPosition(): " + mData.getStreamPosition()); + Log.d(Constants.TAG, "wholeSize: " + wholeSize); + + int length; + byte[] buffer = new byte[1 << 16]; + while ((length = dataIn.read(buffer)) > 0) { + mOutStream.write(buffer, 0, length); + + // update signature buffer if signature is also present if (signature != null) { try { - signature.update(buffer, 0, n); + signature.update(buffer, 0, length); } catch (SignatureException e) { - Log.d(Constants.TAG, "SIGNATURE_ERROR"); + Log.e(Constants.TAG, "SignatureException -> Not a valid signature!", e); signatureResultBuilder.validSignature(false); signature = null; } } - // TODO: dead code?! - // unknown size, but try to at least have a moving, slowing down progress bar -// currentProgress = startProgress + (endProgress - startProgress) * progress -// / (progress + 100000); - if (mData.getSize() - startPos == 0) { - currentProgress = endProgress; + + alreadyWritten += length; + if (wholeSize > 0) { + int progress = 100 * alreadyWritten / (int) wholeSize; + Log.d(Constants.TAG, "progress: " + progress); + + // stop at 100 for buggy sizes... + if (progress > 100) { + progress = 100; + } + progressScaler.setProgress(progress, 100); } else { - currentProgress = (int) (startProgress + (endProgress - startProgress) - * (mData.getStreamPosition() - startPos) / (mData.getSize() - startPos)); + // TODO: slow annealing to fake a progress? } - updateProgress(currentProgress, 100); } if (signature != null) { @@ -597,7 +624,7 @@ public class PgpDecryptVerify { signatureResultBuilder.keyId(signingRing.getMasterKeyId()); try { signatureResultBuilder.userId(signingRing.getPrimaryUserIdWithFallback()); - } catch(PgpGeneralException e) { + } catch (PgpGeneralException e) { Log.d(Constants.TAG, "No primary user id in key " + signingRing.getMasterKeyId()); } signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyResult.java index ad240e834..d16c6ecc0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyResult.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.pgp; import android.os.Parcel; import android.os.Parcelable; +import org.openintents.openpgp.OpenPgpDecryptMetadata; import org.openintents.openpgp.OpenPgpSignatureResult; public class PgpDecryptVerifyResult implements Parcelable { @@ -31,21 +32,22 @@ public class PgpDecryptVerifyResult implements Parcelable { long mKeyIdPassphraseNeeded; OpenPgpSignatureResult mSignatureResult; + OpenPgpDecryptMetadata mDecryptMetadata; public int getStatus() { return mStatus; } - public void setStatus(int mStatus) { - this.mStatus = mStatus; + public void setStatus(int status) { + mStatus = status; } public long getKeyIdPassphraseNeeded() { return mKeyIdPassphraseNeeded; } - public void setKeyIdPassphraseNeeded(long mKeyIdPassphraseNeeded) { - this.mKeyIdPassphraseNeeded = mKeyIdPassphraseNeeded; + public void setKeyIdPassphraseNeeded(long keyIdPassphraseNeeded) { + mKeyIdPassphraseNeeded = keyIdPassphraseNeeded; } public OpenPgpSignatureResult getSignatureResult() { @@ -53,7 +55,15 @@ public class PgpDecryptVerifyResult implements Parcelable { } public void setSignatureResult(OpenPgpSignatureResult signatureResult) { - this.mSignatureResult = signatureResult; + mSignatureResult = signatureResult; + } + + public OpenPgpDecryptMetadata getDecryptMetadata() { + return mDecryptMetadata; + } + + public void setDecryptMetadata(OpenPgpDecryptMetadata decryptMetadata) { + mDecryptMetadata = decryptMetadata; } public PgpDecryptVerifyResult() { @@ -64,6 +74,7 @@ public class PgpDecryptVerifyResult implements Parcelable { this.mStatus = b.mStatus; this.mKeyIdPassphraseNeeded = b.mKeyIdPassphraseNeeded; this.mSignatureResult = b.mSignatureResult; + this.mDecryptMetadata = b.mDecryptMetadata; } @@ -75,6 +86,7 @@ public class PgpDecryptVerifyResult implements Parcelable { dest.writeInt(mStatus); dest.writeLong(mKeyIdPassphraseNeeded); dest.writeParcelable(mSignatureResult, 0); + dest.writeParcelable(mDecryptMetadata, 0); } public static final Creator CREATOR = new Creator() { @@ -83,6 +95,7 @@ public class PgpDecryptVerifyResult implements Parcelable { vr.mStatus = source.readInt(); vr.mKeyIdPassphraseNeeded = source.readLong(); vr.mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader()); + vr.mDecryptMetadata = source.readParcelable(OpenPgpDecryptMetadata.class.getClassLoader()); return vr; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java index d8bf0d4d9..b42e832fa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -357,6 +357,7 @@ public class PgpSignEncrypt { BCPGOutputStream bcpgOut; if (enableEncryption) { /* actual encryption */ + updateProgress(R.string.progress_encrypting, 20, 100); encryptionOut = cPk.open(out, new byte[1 << 16]); @@ -379,27 +380,26 @@ public class PgpSignEncrypt { // file name not needed, so empty string pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, "", new Date(), new byte[1 << 16]); - updateProgress(R.string.progress_encrypting, 20, 100); - long progress = 0; - int n; + long alreadyWritten = 0; + int length; byte[] buffer = new byte[1 << 16]; InputStream in = mData.getInputStream(); - while ((n = in.read(buffer)) > 0) { - pOut.write(buffer, 0, n); + while ((length = in.read(buffer)) > 0) { + pOut.write(buffer, 0, length); // update signature buffer if signature is requested if (enableSignature) { if (mSignatureForceV3) { - signatureV3Generator.update(buffer, 0, n); + signatureV3Generator.update(buffer, 0, length); } else { - signatureGenerator.update(buffer, 0, n); + signatureGenerator.update(buffer, 0, length); } } - progress += n; + alreadyWritten += length; if (mData.getSize() != 0) { - updateProgress((int) (20 + (95 - 20) * progress / mData.getSize()), 100); + updateProgress((int) (20 + (95 - 20) * alreadyWritten / mData.getSize()), 100); } }