Introduction of metadata api, starting to fix decryption progress

This commit is contained in:
Dominik Schürmann 2014-08-10 20:44:02 +02:00
parent 1abae04cda
commit b0821a3ddd
3 changed files with 84 additions and 44 deletions

View File

@ -18,6 +18,7 @@
package org.sufficientlysecure.keychain.pgp; package org.sufficientlysecure.keychain.pgp;
import org.openintents.openpgp.OpenPgpDecryptMetadata;
import org.spongycastle.bcpg.ArmoredInputStream; import org.spongycastle.bcpg.ArmoredInputStream;
import org.spongycastle.openpgp.PGPCompressedData; import org.spongycastle.openpgp.PGPCompressedData;
import org.spongycastle.openpgp.PGPEncryptedData; 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.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -269,8 +271,8 @@ public class PgpDecryptVerify {
// allow only specific keys for decryption? // allow only specific keys for decryption?
if (mAllowedKeyIds != null) { if (mAllowedKeyIds != null) {
Log.d(Constants.TAG, "encData.getKeyID():" + encData.getKeyID()); Log.d(Constants.TAG, "encData.getKeyID(): " + encData.getKeyID());
Log.d(Constants.TAG, "allowedKeyIds: " + mAllowedKeyIds); Log.d(Constants.TAG, "mAllowedKeyIds: " + mAllowedKeyIds);
Log.d(Constants.TAG, "masterKeyId: " + masterKeyId); Log.d(Constants.TAG, "masterKeyId: " + masterKeyId);
if (!mAllowedKeyIds.contains(masterKeyId)) { if (!mAllowedKeyIds.contains(masterKeyId)) {
@ -344,7 +346,7 @@ public class PgpDecryptVerify {
if (!secretEncryptionKey.unlock(mPassphrase)) { if (!secretEncryptionKey.unlock(mPassphrase)) {
throw new WrongPassphraseException(); throw new WrongPassphraseException();
} }
} catch(PgpGeneralException e) { } catch (PgpGeneralException e) {
throw new KeyExtractionException(); throw new KeyExtractionException();
} }
currentProgress += 5; currentProgress += 5;
@ -371,8 +373,9 @@ public class PgpDecryptVerify {
if (dataChunk instanceof PGPCompressedData) { if (dataChunk instanceof PGPCompressedData) {
updateProgress(R.string.progress_decompressing_data, currentProgress, 100); updateProgress(R.string.progress_decompressing_data, currentProgress, 100);
PGPObjectFactory fact = new PGPObjectFactory( PGPCompressedData compressedData = (PGPCompressedData) dataChunk;
((PGPCompressedData) dataChunk).getDataStream());
PGPObjectFactory fact = new PGPObjectFactory(compressedData.getDataStream());
dataChunk = fact.nextObject(); dataChunk = fact.nextObject();
plainFact = fact; plainFact = fact;
currentProgress += 10; currentProgress += 10;
@ -410,8 +413,8 @@ public class PgpDecryptVerify {
signatureResultBuilder.keyId(signingRing.getMasterKeyId()); signatureResultBuilder.keyId(signingRing.getMasterKeyId());
try { try {
signatureResultBuilder.userId(signingRing.getPrimaryUserIdWithFallback()); signatureResultBuilder.userId(signingRing.getPrimaryUserIdWithFallback());
} catch(PgpGeneralException e) { } catch (PgpGeneralException e) {
Log.d(Constants.TAG, "No primary user id in key " + signingRing.getMasterKeyId()); Log.d(Constants.TAG, "No primary user id in keyring with master key id " + signingRing.getMasterKeyId());
} }
signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0); signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0);
@ -433,6 +436,7 @@ public class PgpDecryptVerify {
} }
if (dataChunk instanceof PGPSignatureList) { if (dataChunk instanceof PGPSignatureList) {
// skip
dataChunk = plainFact.nextObject(); dataChunk = plainFact.nextObject();
} }
@ -441,44 +445,67 @@ public class PgpDecryptVerify {
PGPLiteralData literalData = (PGPLiteralData) dataChunk; PGPLiteralData literalData = (PGPLiteralData) dataChunk;
byte[] buffer = new byte[1 << 16]; // TODO: how to get the real original size?
InputStream dataIn = literalData.getInputStream(); // this is the encrypted size
long originalSize = mData.getSize() - mData.getStreamPosition();
if (originalSize < 0) {
originalSize = 0;
}
int startProgress = currentProgress; OpenPgpDecryptMetadata metadata = new OpenPgpDecryptMetadata(
int endProgress = 100; literalData.getFileName(),
literalData.getModificationTime().getTime(),
literalData.getFormat(),
originalSize);
result.setDecryptMetadata(metadata);
int endProgress;
if (signature != null) { if (signature != null) {
endProgress = 90; endProgress = 90;
} else if (encryptedData.isIntegrityProtected()) { } else if (encryptedData.isIntegrityProtected()) {
endProgress = 95; endProgress = 95;
} else {
endProgress = 100;
} }
ProgressScaler progressScaler =
new ProgressScaler(mProgressable, currentProgress, endProgress, 100);
int n; InputStream dataIn = literalData.getInputStream();
// TODO: progress calculation is broken here! Try to rework it based on commented code!
// int progress = 0; int alreadyWritten = 0;
long startPos = mData.getStreamPosition(); long wholeSize = mData.getSize() - mData.getStreamPosition();
while ((n = dataIn.read(buffer)) > 0) { Log.d(Constants.TAG, "mData.getStreamPosition(): " + mData.getStreamPosition());
mOutStream.write(buffer, 0, n); Log.d(Constants.TAG, "wholeSize: " + wholeSize);
// progress += n;
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) { if (signature != null) {
try { try {
signature.update(buffer, 0, n); signature.update(buffer, 0, length);
} catch (SignatureException e) { } catch (SignatureException e) {
Log.d(Constants.TAG, "SIGNATURE_ERROR"); Log.e(Constants.TAG, "SignatureException -> Not a valid signature!", e);
signatureResultBuilder.validSignature(false); signatureResultBuilder.validSignature(false);
signature = null; signature = null;
} }
} }
// TODO: dead code?!
// unknown size, but try to at least have a moving, slowing down progress bar alreadyWritten += length;
// currentProgress = startProgress + (endProgress - startProgress) * progress if (wholeSize > 0) {
// / (progress + 100000); int progress = 100 * alreadyWritten / (int) wholeSize;
if (mData.getSize() - startPos == 0) { Log.d(Constants.TAG, "progress: " + progress);
currentProgress = endProgress;
// stop at 100 for buggy sizes...
if (progress > 100) {
progress = 100;
}
progressScaler.setProgress(progress, 100);
} else { } else {
currentProgress = (int) (startProgress + (endProgress - startProgress) // TODO: slow annealing to fake a progress?
* (mData.getStreamPosition() - startPos) / (mData.getSize() - startPos));
} }
updateProgress(currentProgress, 100);
} }
if (signature != null) { if (signature != null) {
@ -597,7 +624,7 @@ public class PgpDecryptVerify {
signatureResultBuilder.keyId(signingRing.getMasterKeyId()); signatureResultBuilder.keyId(signingRing.getMasterKeyId());
try { try {
signatureResultBuilder.userId(signingRing.getPrimaryUserIdWithFallback()); signatureResultBuilder.userId(signingRing.getPrimaryUserIdWithFallback());
} catch(PgpGeneralException e) { } catch (PgpGeneralException e) {
Log.d(Constants.TAG, "No primary user id in key " + signingRing.getMasterKeyId()); Log.d(Constants.TAG, "No primary user id in key " + signingRing.getMasterKeyId());
} }
signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0); signatureResultBuilder.signatureKeyCertified(signingRing.getVerified() > 0);

View File

@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.pgp;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import org.openintents.openpgp.OpenPgpDecryptMetadata;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
public class PgpDecryptVerifyResult implements Parcelable { public class PgpDecryptVerifyResult implements Parcelable {
@ -31,21 +32,22 @@ public class PgpDecryptVerifyResult implements Parcelable {
long mKeyIdPassphraseNeeded; long mKeyIdPassphraseNeeded;
OpenPgpSignatureResult mSignatureResult; OpenPgpSignatureResult mSignatureResult;
OpenPgpDecryptMetadata mDecryptMetadata;
public int getStatus() { public int getStatus() {
return mStatus; return mStatus;
} }
public void setStatus(int mStatus) { public void setStatus(int status) {
this.mStatus = mStatus; mStatus = status;
} }
public long getKeyIdPassphraseNeeded() { public long getKeyIdPassphraseNeeded() {
return mKeyIdPassphraseNeeded; return mKeyIdPassphraseNeeded;
} }
public void setKeyIdPassphraseNeeded(long mKeyIdPassphraseNeeded) { public void setKeyIdPassphraseNeeded(long keyIdPassphraseNeeded) {
this.mKeyIdPassphraseNeeded = mKeyIdPassphraseNeeded; mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
} }
public OpenPgpSignatureResult getSignatureResult() { public OpenPgpSignatureResult getSignatureResult() {
@ -53,7 +55,15 @@ public class PgpDecryptVerifyResult implements Parcelable {
} }
public void setSignatureResult(OpenPgpSignatureResult signatureResult) { public void setSignatureResult(OpenPgpSignatureResult signatureResult) {
this.mSignatureResult = signatureResult; mSignatureResult = signatureResult;
}
public OpenPgpDecryptMetadata getDecryptMetadata() {
return mDecryptMetadata;
}
public void setDecryptMetadata(OpenPgpDecryptMetadata decryptMetadata) {
mDecryptMetadata = decryptMetadata;
} }
public PgpDecryptVerifyResult() { public PgpDecryptVerifyResult() {
@ -64,6 +74,7 @@ public class PgpDecryptVerifyResult implements Parcelable {
this.mStatus = b.mStatus; this.mStatus = b.mStatus;
this.mKeyIdPassphraseNeeded = b.mKeyIdPassphraseNeeded; this.mKeyIdPassphraseNeeded = b.mKeyIdPassphraseNeeded;
this.mSignatureResult = b.mSignatureResult; this.mSignatureResult = b.mSignatureResult;
this.mDecryptMetadata = b.mDecryptMetadata;
} }
@ -75,6 +86,7 @@ public class PgpDecryptVerifyResult implements Parcelable {
dest.writeInt(mStatus); dest.writeInt(mStatus);
dest.writeLong(mKeyIdPassphraseNeeded); dest.writeLong(mKeyIdPassphraseNeeded);
dest.writeParcelable(mSignatureResult, 0); dest.writeParcelable(mSignatureResult, 0);
dest.writeParcelable(mDecryptMetadata, 0);
} }
public static final Creator<PgpDecryptVerifyResult> CREATOR = new Creator<PgpDecryptVerifyResult>() { public static final Creator<PgpDecryptVerifyResult> CREATOR = new Creator<PgpDecryptVerifyResult>() {
@ -83,6 +95,7 @@ public class PgpDecryptVerifyResult implements Parcelable {
vr.mStatus = source.readInt(); vr.mStatus = source.readInt();
vr.mKeyIdPassphraseNeeded = source.readLong(); vr.mKeyIdPassphraseNeeded = source.readLong();
vr.mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader()); vr.mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
vr.mDecryptMetadata = source.readParcelable(OpenPgpDecryptMetadata.class.getClassLoader());
return vr; return vr;
} }

View File

@ -357,6 +357,7 @@ public class PgpSignEncrypt {
BCPGOutputStream bcpgOut; BCPGOutputStream bcpgOut;
if (enableEncryption) { if (enableEncryption) {
/* actual encryption */ /* actual encryption */
updateProgress(R.string.progress_encrypting, 20, 100);
encryptionOut = cPk.open(out, new byte[1 << 16]); encryptionOut = cPk.open(out, new byte[1 << 16]);
@ -379,27 +380,26 @@ public class PgpSignEncrypt {
// file name not needed, so empty string // file name not needed, so empty string
pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, "", new Date(), pOut = literalGen.open(bcpgOut, PGPLiteralData.BINARY, "", new Date(),
new byte[1 << 16]); new byte[1 << 16]);
updateProgress(R.string.progress_encrypting, 20, 100);
long progress = 0; long alreadyWritten = 0;
int n; int length;
byte[] buffer = new byte[1 << 16]; byte[] buffer = new byte[1 << 16];
InputStream in = mData.getInputStream(); InputStream in = mData.getInputStream();
while ((n = in.read(buffer)) > 0) { while ((length = in.read(buffer)) > 0) {
pOut.write(buffer, 0, n); pOut.write(buffer, 0, length);
// update signature buffer if signature is requested // update signature buffer if signature is requested
if (enableSignature) { if (enableSignature) {
if (mSignatureForceV3) { if (mSignatureForceV3) {
signatureV3Generator.update(buffer, 0, n); signatureV3Generator.update(buffer, 0, length);
} else { } else {
signatureGenerator.update(buffer, 0, n); signatureGenerator.update(buffer, 0, length);
} }
} }
progress += n; alreadyWritten += length;
if (mData.getSize() != 0) { if (mData.getSize() != 0) {
updateProgress((int) (20 + (95 - 20) * progress / mData.getSize()), 100); updateProgress((int) (20 + (95 - 20) * alreadyWritten / mData.getSize()), 100);
} }
} }