diff options
Diffstat (limited to 'OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java')
-rw-r--r-- | OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java | 196 |
1 files changed, 90 insertions, 106 deletions
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 252be1036..571729bc5 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -18,38 +18,16 @@ package org.sufficientlysecure.keychain.pgp; import android.content.Context; - import org.openintents.openpgp.OpenPgpSignatureResult; import org.spongycastle.bcpg.ArmoredInputStream; import org.spongycastle.bcpg.SignatureSubpacketTags; -import org.spongycastle.openpgp.PGPCompressedData; -import org.spongycastle.openpgp.PGPEncryptedData; -import org.spongycastle.openpgp.PGPEncryptedDataList; -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPLiteralData; -import org.spongycastle.openpgp.PGPObjectFactory; -import org.spongycastle.openpgp.PGPOnePassSignature; -import org.spongycastle.openpgp.PGPOnePassSignatureList; -import org.spongycastle.openpgp.PGPPBEEncryptedData; -import org.spongycastle.openpgp.PGPPrivateKey; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPPublicKeyEncryptedData; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.spongycastle.openpgp.PGPSignature; -import org.spongycastle.openpgp.PGPSignatureList; -import org.spongycastle.openpgp.PGPSignatureSubpacketVector; +import org.spongycastle.openpgp.*; import org.spongycastle.openpgp.PGPUtil; import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory; import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider; import org.spongycastle.openpgp.operator.PublicKeyDataDecryptorFactory; -import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; -import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; -import org.spongycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder; -import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; -import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder; +import org.spongycastle.openpgp.operator.jcajce.*; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; @@ -59,12 +37,7 @@ import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressDialogUpdater; -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.*; import java.security.SignatureException; import java.util.Iterator; @@ -72,57 +45,57 @@ import java.util.Iterator; * This class uses a Builder pattern! */ public class PgpDecryptVerify { - private Context context; - private InputData data; - private OutputStream outStream; + private Context mContext; + private InputData mData; + private OutputStream mOutStream; - private ProgressDialogUpdater progressDialogUpdater; - private boolean assumeSymmetric; - private String passphrase; - private long enforcedKeyId; + private ProgressDialogUpdater mProgressDialogUpdater; + private boolean mAssumeSymmetric; + private String mPassphrase; + private long mEnforcedKeyId; private PgpDecryptVerify(Builder builder) { // private Constructor can only be called from Builder - this.context = builder.context; - this.data = builder.data; - this.outStream = builder.outStream; - - this.progressDialogUpdater = builder.progressDialogUpdater; - this.assumeSymmetric = builder.assumeSymmetric; - this.passphrase = builder.passphrase; - this.enforcedKeyId = builder.enforcedKeyId; + this.mContext = builder.mContext; + this.mData = builder.mData; + this.mOutStream = builder.mOutStream; + + this.mProgressDialogUpdater = builder.mProgressDialogUpdater; + this.mAssumeSymmetric = builder.mAssumeSymmetric; + this.mPassphrase = builder.mPassphrase; + this.mEnforcedKeyId = builder.mEnforcedKeyId; } public static class Builder { // mandatory parameter - private Context context; - private InputData data; - private OutputStream outStream; + private Context mContext; + private InputData mData; + private OutputStream mOutStream; // optional - private ProgressDialogUpdater progressDialogUpdater = null; - private boolean assumeSymmetric = false; - private String passphrase = ""; - private long enforcedKeyId = 0; + private ProgressDialogUpdater mProgressDialogUpdater = null; + private boolean mAssumeSymmetric = false; + private String mPassphrase = ""; + private long mEnforcedKeyId = 0; public Builder(Context context, InputData data, OutputStream outStream) { - this.context = context; - this.data = data; - this.outStream = outStream; + this.mContext = context; + this.mData = data; + this.mOutStream = outStream; } public Builder progressDialogUpdater(ProgressDialogUpdater progressDialogUpdater) { - this.progressDialogUpdater = progressDialogUpdater; + this.mProgressDialogUpdater = progressDialogUpdater; return this; } public Builder assumeSymmetric(boolean assumeSymmetric) { - this.assumeSymmetric = assumeSymmetric; + this.mAssumeSymmetric = assumeSymmetric; return this; } public Builder passphrase(String passphrase) { - this.passphrase = passphrase; + this.mPassphrase = passphrase; return this; } @@ -134,7 +107,7 @@ public class PgpDecryptVerify { * @return */ public Builder enforcedKeyId(long enforcedKeyId) { - this.enforcedKeyId = enforcedKeyId; + this.mEnforcedKeyId = enforcedKeyId; return this; } @@ -144,14 +117,14 @@ public class PgpDecryptVerify { } public void updateProgress(int message, int current, int total) { - if (progressDialogUpdater != null) { - progressDialogUpdater.setProgress(message, current, total); + if (mProgressDialogUpdater != null) { + mProgressDialogUpdater.setProgress(message, current, total); } } public void updateProgress(int current, int total) { - if (progressDialogUpdater != null) { - progressDialogUpdater.setProgress(current, total); + if (mProgressDialogUpdater != null) { + mProgressDialogUpdater.setProgress(current, total); } } @@ -196,7 +169,7 @@ public class PgpDecryptVerify { public PgpDecryptVerifyResult execute() throws IOException, PgpGeneralException, PGPException, SignatureException { // automatically works with ascii armor input and binary - InputStream in = PGPUtil.getDecoderStream(data.getInputStream()); + InputStream in = PGPUtil.getDecoderStream(mData.getInputStream()); if (in instanceof ArmoredInputStream) { ArmoredInputStream aIn = (ArmoredInputStream) in; // it is ascii armored @@ -240,7 +213,7 @@ public class PgpDecryptVerify { } if (enc == null) { - throw new PgpGeneralException(context.getString(R.string.error_invalid_data)); + throw new PgpGeneralException(mContext.getString(R.string.error_invalid_data)); } InputStream clear; @@ -250,7 +223,7 @@ public class PgpDecryptVerify { // TODO: currently we always only look at the first known key or symmetric encryption, // there might be more... - if (assumeSymmetric) { + if (mAssumeSymmetric) { PGPPBEEncryptedData pbe = null; Iterator<?> it = enc.getEncryptedDataObjects(); // find secret key @@ -264,7 +237,7 @@ public class PgpDecryptVerify { if (pbe == null) { throw new PgpGeneralException( - context.getString(R.string.error_no_symmetric_encryption_packet)); + mContext.getString(R.string.error_no_symmetric_encryption_packet)); } updateProgress(R.string.progress_preparing_streams, currentProgress, 100); @@ -273,7 +246,7 @@ public class PgpDecryptVerify { .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(); PBEDataDecryptorFactory decryptorFactory = new JcePBEDataDecryptorFactoryBuilder( digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( - passphrase.toCharArray()); + mPassphrase.toCharArray()); clear = pbe.getDataStream(decryptorFactory); @@ -290,33 +263,37 @@ public class PgpDecryptVerify { Object obj = it.next(); if (obj instanceof PGPPublicKeyEncryptedData) { PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj; - secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, encData.getKeyID()); + secretKey = ProviderHelper.getPGPSecretKeyByKeyId(mContext, encData.getKeyID()); if (secretKey != null) { // secret key exists in database // allow only a specific key for decryption? - if (enforcedKeyId != 0) { + if (mEnforcedKeyId != 0) { // TODO: improve this code! get master key directly! - PGPSecretKeyRing secretKeyRing = ProviderHelper.getPGPSecretKeyRingByKeyId(context, encData.getKeyID()); + PGPSecretKeyRing secretKeyRing = + ProviderHelper.getPGPSecretKeyRingByKeyId(mContext, encData.getKeyID()); long masterKeyId = PgpKeyHelper.getMasterKey(secretKeyRing).getKeyID(); Log.d(Constants.TAG, "encData.getKeyID():" + encData.getKeyID()); - Log.d(Constants.TAG, "enforcedKeyId: " + enforcedKeyId); + Log.d(Constants.TAG, "enforcedKeyId: " + mEnforcedKeyId); Log.d(Constants.TAG, "masterKeyId: " + masterKeyId); - if (enforcedKeyId != masterKeyId) { - throw new PgpGeneralException(context.getString(R.string.error_no_secret_key_found)); + if (mEnforcedKeyId != masterKeyId) { + throw new PgpGeneralException( + mContext.getString(R.string.error_no_secret_key_found)); } } pbe = encData; // if no passphrase was explicitly set try to get it from the cache service - if (passphrase == null) { + if (mPassphrase == null) { // returns "" if key has no passphrase - passphrase = PassphraseCacheService.getCachedPassphrase(context, encData.getKeyID()); + mPassphrase = + PassphraseCacheService.getCachedPassphrase(mContext, encData.getKeyID()); - // if passphrase was not cached, return here indicating that a passphrase is missing! - if (passphrase == null) { + // if passphrase was not cached, return here + // indicating that a passphrase is missing! + if (mPassphrase == null) { returnData.setKeyPassphraseNeeded(true); return returnData; } @@ -330,7 +307,7 @@ public class PgpDecryptVerify { } if (secretKey == null) { - throw new PgpGeneralException(context.getString(R.string.error_no_secret_key_found)); + throw new PgpGeneralException(mContext.getString(R.string.error_no_secret_key_found)); } currentProgress += 5; @@ -339,14 +316,14 @@ public class PgpDecryptVerify { try { PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( - passphrase.toCharArray()); + mPassphrase.toCharArray()); privateKey = secretKey.extractPrivateKey(keyDecryptor); } catch (PGPException e) { - throw new PGPException(context.getString(R.string.error_wrong_passphrase)); + throw new PGPException(mContext.getString(R.string.error_wrong_passphrase)); } if (privateKey == null) { throw new PgpGeneralException( - context.getString(R.string.error_could_not_extract_private_key)); + mContext.getString(R.string.error_could_not_extract_private_key)); } currentProgress += 5; updateProgress(R.string.progress_preparing_streams, currentProgress, 100); @@ -386,7 +363,7 @@ public class PgpDecryptVerify { for (int i = 0; i < sigList.size(); ++i) { signature = sigList.get(i); signatureKey = ProviderHelper - .getPGPPublicKeyByKeyId(context, signature.getKeyID()); + .getPGPPublicKeyByKeyId(mContext, signature.getKeyID()); if (signatureKeyId == 0) { signatureKeyId = signature.getKeyID(); } @@ -397,7 +374,7 @@ public class PgpDecryptVerify { signatureKeyId = signature.getKeyID(); String userId = null; PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId( - context, signatureKeyId); + mContext, signatureKeyId); if (signKeyRing != null) { userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing)); } @@ -409,7 +386,8 @@ public class PgpDecryptVerify { signatureResult.setKeyId(signatureKeyId); if (signature != null) { - JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider() + JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = + new JcaPGPContentVerifierBuilderProvider() .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); signature.init(contentVerifierBuilderProvider, signatureKey); @@ -444,9 +422,9 @@ public class PgpDecryptVerify { int n; // TODO: progress calculation is broken here! Try to rework it based on commented code! // int progress = 0; - long startPos = data.getStreamPosition(); + long startPos = mData.getStreamPosition(); while ((n = dataIn.read(buffer)) > 0) { - outStream.write(buffer, 0, n); + mOutStream.write(buffer, 0, n); // progress += n; if (signature != null) { try { @@ -460,11 +438,11 @@ public class PgpDecryptVerify { // unknown size, but try to at least have a moving, slowing down progress bar // currentProgress = startProgress + (endProgress - startProgress) * progress // / (progress + 100000); - if (data.getSize() - startPos == 0) { + if (mData.getSize() - startPos == 0) { currentProgress = endProgress; } else { currentProgress = (int) (startProgress + (endProgress - startProgress) - * (data.getStreamPosition() - startPos) / (data.getSize() - startPos)); + * (mData.getStreamPosition() - startPos) / (mData.getSize() - startPos)); } updateProgress(currentProgress, 100); } @@ -480,7 +458,7 @@ public class PgpDecryptVerify { signatureResult.setSignatureOnly(false); //Now check binding signatures - boolean validKeyBinding = verifyKeyBinding(context, messageSignature, signatureKey); + boolean validKeyBinding = verifyKeyBinding(mContext, messageSignature, signatureKey); boolean validSignature = signature.verify(messageSignature); // TODO: implement CERTIFIED! @@ -499,7 +477,7 @@ public class PgpDecryptVerify { } else { // failed Log.d(Constants.TAG, "Integrity verification: failed!"); - throw new PgpGeneralException(context.getString(R.string.error_integrity_check_failed)); + throw new PgpGeneralException(mContext.getString(R.string.error_integrity_check_failed)); } } else { // no integrity check @@ -555,21 +533,21 @@ public class PgpDecryptVerify { out.close(); byte[] clearText = out.toByteArray(); - outStream.write(clearText); + mOutStream.write(clearText); updateProgress(R.string.progress_processing_signature, 60, 100); PGPObjectFactory pgpFact = new PGPObjectFactory(aIn); PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject(); if (sigList == null) { - throw new PgpGeneralException(context.getString(R.string.error_corrupt_data)); + throw new PgpGeneralException(mContext.getString(R.string.error_corrupt_data)); } PGPSignature signature = null; long signatureKeyId = 0; PGPPublicKey signatureKey = null; for (int i = 0; i < sigList.size(); ++i) { signature = sigList.get(i); - signatureKey = ProviderHelper.getPGPPublicKeyByKeyId(context, signature.getKeyID()); + signatureKey = ProviderHelper.getPGPPublicKeyByKeyId(mContext, signature.getKeyID()); if (signatureKeyId == 0) { signatureKeyId = signature.getKeyID(); } @@ -579,7 +557,7 @@ public class PgpDecryptVerify { } else { signatureKeyId = signature.getKeyID(); String userId = null; - PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(context, + PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(mContext, signatureKeyId); if (signKeyRing != null) { userId = PgpKeyHelper.getMainUserId(PgpKeyHelper.getMasterKey(signKeyRing)); @@ -623,7 +601,7 @@ public class PgpDecryptVerify { } //Now check binding signatures - boolean validKeyBinding = verifyKeyBinding(context, signature, signatureKey); + boolean validKeyBinding = verifyKeyBinding(mContext, signature, signatureKey); boolean validSignature = signature.verify(); if (validSignature & validKeyBinding) { @@ -638,7 +616,8 @@ public class PgpDecryptVerify { return returnData; } - private static boolean verifyKeyBinding(Context context, PGPSignature signature, PGPPublicKey signatureKey) { + private static boolean verifyKeyBinding(Context context, + PGPSignature signature, PGPPublicKey signatureKey) { long signatureKeyId = signature.getKeyID(); boolean validKeyBinding = false; @@ -673,7 +652,8 @@ public class PgpDecryptVerify { //about keys without subkey signing. Can't get it to import a slightly broken one //either, so we will err on bad subkey binding here. PGPSignature sig = itr.next(); - if (sig.getKeyID() == masterPublicKey.getKeyID() && sig.getSignatureType() == PGPSignature.SUBKEY_BINDING) { + if (sig.getKeyID() == masterPublicKey.getKeyID() && + sig.getSignatureType() == PGPSignature.SUBKEY_BINDING) { //check and if ok, check primary key binding. try { sig.init(contentVerifierBuilderProvider, masterPublicKey); @@ -684,34 +664,37 @@ public class PgpDecryptVerify { continue; } - if (validTempSubkeyBinding) + if (validTempSubkeyBinding) { validSubkeyBinding = true; + } if (validTempSubkeyBinding) { validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getUnhashedSubPackets(), masterPublicKey, signingPublicKey); - if (validPrimaryKeyBinding) + if (validPrimaryKeyBinding) { break; + } validPrimaryKeyBinding = verifyPrimaryKeyBinding(sig.getHashedSubPackets(), masterPublicKey, signingPublicKey); - if (validPrimaryKeyBinding) + if (validPrimaryKeyBinding) { break; + } } } } return (validSubkeyBinding & validPrimaryKeyBinding); } - private static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector Pkts, - PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) { + private static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector pkts, + PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) { boolean validPrimaryKeyBinding = false; JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider() .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); PGPSignatureList eSigList; - if (Pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) { + if (pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) { try { - eSigList = Pkts.getEmbeddedSignatures(); + eSigList = pkts.getEmbeddedSignatures(); } catch (IOException e) { return false; } catch (PGPException e) { @@ -723,8 +706,9 @@ public class PgpDecryptVerify { try { emSig.init(contentVerifierBuilderProvider, signingPublicKey); validPrimaryKeyBinding = emSig.verifyCertification(masterPublicKey, signingPublicKey); - if (validPrimaryKeyBinding) + if (validPrimaryKeyBinding) { break; + } } catch (PGPException e) { continue; } catch (SignatureException e) { |