diff options
Diffstat (limited to 'OpenPGP-Keychain/src/main/java/org')
5 files changed, 117 insertions, 117 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 d06898c89..741c1323a 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,16 +18,38 @@ 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.*; +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.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.*; +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.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; @@ -37,7 +59,12 @@ import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ProgressDialogUpdater; -import java.io.*; +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.security.SignatureException; import java.util.Iterator; @@ -50,7 +77,7 @@ public class PgpDecryptVerify { private OutputStream mOutStream; private ProgressDialogUpdater mProgressDialogUpdater; - private boolean mAssumeSymmetric; + private boolean mAllowSymmetricDecryption; private String mPassphrase; private long mEnforcedKeyId; @@ -61,7 +88,7 @@ public class PgpDecryptVerify { this.mOutStream = builder.mOutStream; this.mProgressDialogUpdater = builder.mProgressDialogUpdater; - this.mAssumeSymmetric = builder.mAssumeSymmetric; + this.mAllowSymmetricDecryption = builder.mAllowSymmetricDecryption; this.mPassphrase = builder.mPassphrase; this.mEnforcedKeyId = builder.mEnforcedKeyId; } @@ -74,7 +101,7 @@ public class PgpDecryptVerify { // optional private ProgressDialogUpdater mProgressDialogUpdater = null; - private boolean mAssumeSymmetric = false; + private boolean mAllowSymmetricDecryption = false; private String mPassphrase = null; private long mEnforcedKeyId = 0; @@ -89,8 +116,8 @@ public class PgpDecryptVerify { return this; } - public Builder assumeSymmetric(boolean assumeSymmetric) { - this.mAssumeSymmetric = assumeSymmetric; + public Builder allowSymmetricDecryption(boolean allowSymmetricDecryption) { + this.mAllowSymmetricDecryption = allowSymmetricDecryption; return this; } @@ -128,35 +155,6 @@ public class PgpDecryptVerify { } } - public static boolean hasSymmetricEncryption(Context context, InputStream inputStream) - throws PgpGeneralException, IOException { - InputStream in = PGPUtil.getDecoderStream(inputStream); - PGPObjectFactory pgpF = new PGPObjectFactory(in); - PGPEncryptedDataList enc; - Object o = pgpF.nextObject(); - - // the first object might be a PGP marker packet. - if (o instanceof PGPEncryptedDataList) { - enc = (PGPEncryptedDataList) o; - } else { - enc = (PGPEncryptedDataList) pgpF.nextObject(); - } - - if (enc == null) { - throw new PgpGeneralException(context.getString(R.string.error_invalid_data)); - } - - Iterator<?> it = enc.getEncryptedDataObjects(); - while (it.hasNext()) { - Object obj = it.next(); - if (obj instanceof PGPPBEEncryptedData) { - return true; - } - } - - return false; - } - /** * Decrypts and/or verifies data based on parameters of class * @@ -221,25 +219,78 @@ public class PgpDecryptVerify { currentProgress += 5; - // TODO: currently we always only look at the first known key or symmetric encryption, - // there might be more... - if (mAssumeSymmetric) { - PGPPBEEncryptedData pbe = null; - Iterator<?> it = enc.getEncryptedDataObjects(); - // find secret key - while (it.hasNext()) { - Object obj = it.next(); - if (obj instanceof PGPPBEEncryptedData) { - pbe = (PGPPBEEncryptedData) obj; + PGPPublicKeyEncryptedData encryptedDataAsymmetric = null; + PGPPBEEncryptedData encryptedDataSymmetric = null; + PGPSecretKey secretKey = null; + Iterator<?> it = enc.getEncryptedDataObjects(); + boolean symmetricPacketFound = false; + // find secret key + while (it.hasNext()) { + Object obj = it.next(); + if (obj instanceof PGPPublicKeyEncryptedData) { + updateProgress(R.string.progress_finding_key, currentProgress, 100); + + PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj; + secretKey = ProviderHelper.getPGPSecretKeyByKeyId(mContext, encData.getKeyID()); + if (secretKey != null) { + // secret key exists in database + + // allow only a specific key for decryption? + if (mEnforcedKeyId != 0) { + // TODO: improve this code! get master key directly! + 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: " + mEnforcedKeyId); + Log.d(Constants.TAG, "masterKeyId: " + masterKeyId); + + if (mEnforcedKeyId != masterKeyId) { + throw new PgpGeneralException( + mContext.getString(R.string.error_no_secret_key_found)); + } + } + + encryptedDataAsymmetric = encData; + + // if no passphrase was explicitly set try to get it from the cache service + if (mPassphrase == null) { + // returns "" if key has no passphrase + mPassphrase = + PassphraseCacheService.getCachedPassphrase(mContext, encData.getKeyID()); + + // if passphrase was not cached, return here + // indicating that a passphrase is missing! + if (mPassphrase == null) { + returnData.setKeyIdPassphraseNeeded(encData.getKeyID()); + returnData.setStatus(PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED); + return returnData; + } + } + + // break out of while, only get first object here + // TODO???: There could be more pgp objects, which are not decrypted! break; } - } + } else if (mAllowSymmetricDecryption && obj instanceof PGPPBEEncryptedData) { + symmetricPacketFound = true; - if (pbe == null) { - throw new PgpGeneralException( - mContext.getString(R.string.error_no_symmetric_encryption_packet)); + encryptedDataSymmetric = (PGPPBEEncryptedData) obj; + + // if no passphrase is given, return here + // indicating that a passphrase is missing! + if (mPassphrase == null) { + returnData.setStatus(PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED); + return returnData; + } + + // break out of while, only get first object here + // TODO???: There could be more pgp objects, which are not decrypted! + break; } + } + if (symmetricPacketFound) { updateProgress(R.string.progress_preparing_streams, currentProgress, 100); PGPDigestCalculatorProvider digestCalcProvider = new JcaPGPDigestCalculatorProviderBuilder() @@ -248,65 +299,11 @@ public class PgpDecryptVerify { digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( mPassphrase.toCharArray()); - clear = pbe.getDataStream(decryptorFactory); + clear = encryptedDataSymmetric.getDataStream(decryptorFactory); - encryptedData = pbe; + encryptedData = encryptedDataSymmetric; currentProgress += 5; } else { - PGPPublicKeyEncryptedData pbe = null; - PGPSecretKey secretKey = null; - Iterator<?> it = enc.getEncryptedDataObjects(); - // find secret key - while (it.hasNext()) { - Object obj = it.next(); - if (obj instanceof PGPPublicKeyEncryptedData) { - updateProgress(R.string.progress_finding_key, currentProgress, 100); - - PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj; - secretKey = ProviderHelper.getPGPSecretKeyByKeyId(mContext, encData.getKeyID()); - if (secretKey != null) { - // secret key exists in database - - // allow only a specific key for decryption? - if (mEnforcedKeyId != 0) { - // TODO: improve this code! get master key directly! - 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: " + mEnforcedKeyId); - Log.d(Constants.TAG, "masterKeyId: " + masterKeyId); - - 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 (mPassphrase == null) { - // returns "" if key has no passphrase - mPassphrase = - PassphraseCacheService.getCachedPassphrase(mContext, encData.getKeyID()); - - // if passphrase was not cached, return here - // indicating that a passphrase is missing! - if (mPassphrase == null) { - returnData.setKeyIdPassphraseNeeded(encData.getKeyID()); - returnData.setStatus(PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED); - return returnData; - } - } - - break; - } - } else if (obj instanceof PGPPBEEncryptedData) { - - } - } - if (secretKey == null) { throw new PgpGeneralException(mContext.getString(R.string.error_no_secret_key_found)); } @@ -332,9 +329,9 @@ public class PgpDecryptVerify { PublicKeyDataDecryptorFactory decryptorFactory = new JcePublicKeyDataDecryptorFactoryBuilder() .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(privateKey); - clear = pbe.getDataStream(decryptorFactory); + clear = encryptedDataAsymmetric.getDataStream(decryptorFactory); - encryptedData = pbe; + encryptedData = encryptedDataAsymmetric; currentProgress += 5; } @@ -389,7 +386,7 @@ public class PgpDecryptVerify { if (signature != null) { JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); signature.init(contentVerifierBuilderProvider, signatureKey); } else { @@ -686,7 +683,7 @@ public class PgpDecryptVerify { } private static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector pkts, - PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) { + PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey) { boolean validPrimaryKeyBinding = false; JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider() diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 1d3bb88df..1cd5862e7 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -290,9 +290,8 @@ public class OpenPgpService extends RemoteService { InputData inputData = new InputData(is, inputLength); PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, os); - builder.assumeSymmetric(false) // no support for symmetric encryption - // allow only the private key for this app for decryption - .enforcedKeyId(accSettings.getKeyId()) + builder.allowSymmetricDecryption(false) // no support for symmetric encryption + .enforcedKeyId(accSettings.getKeyId()) // allow only the private key for this app for decryption .passphrase(passphrase); // TODO: currently does not support binary signed-only content diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 2ad7e348b..2060c6f61 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -98,7 +98,6 @@ public class KeychainIntentService extends IntentService // decrypt/verify public static final String DECRYPT_CIPHERTEXT_BYTES = "ciphertext_bytes"; - public static final String DECRYPT_ASSUME_SYMMETRIC = "assume_symmetric"; public static final String DECRYPT_PASSPHRASE = "passphrase"; // save keyring @@ -344,7 +343,6 @@ public class KeychainIntentService extends IntentService int target = data.getInt(TARGET); byte[] bytes = data.getByteArray(DECRYPT_CIPHERTEXT_BYTES); - boolean assumeSymmetricEncryption = data.getBoolean(DECRYPT_ASSUME_SYMMETRIC); String passphrase = data.getString(DECRYPT_PASSPHRASE); InputStream inStream; @@ -424,7 +422,7 @@ public class KeychainIntentService extends IntentService PgpDecryptVerify.Builder builder = new PgpDecryptVerify.Builder(this, inputData, outStream); builder.progressDialogUpdater(this); - builder.assumeSymmetric(assumeSymmetricEncryption) + builder.allowSymmetricDecryption(true) .passphrase(passphrase); PgpDecryptVerifyResult decryptVerifyResult = builder.build().execute(); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java index a929047b8..cec6d7a59 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java @@ -35,6 +35,7 @@ import com.devspark.appmsg.AppMsg; import org.openintents.openpgp.OpenPgpSignatureResult; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; @@ -202,6 +203,8 @@ public class DecryptFileFragment extends DecryptFragment { if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) { showPassphraseDialog(decryptVerifyResult.getKeyIdPassphraseNeeded()); + } else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) { + showPassphraseDialog(Id.key.symmetric); } else { if (mDeleteAfter.isChecked()) { // Create and show dialog to delete original file diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java index 94034b356..197a2af04 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java @@ -33,6 +33,7 @@ import com.devspark.appmsg.AppMsg; import org.openintents.openpgp.OpenPgpSignatureResult; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; @@ -149,6 +150,8 @@ public class DecryptMessageFragment extends DecryptFragment { if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) { showPassphraseDialog(decryptVerifyResult.getKeyIdPassphraseNeeded()); + } else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) { + showPassphraseDialog(Id.key.symmetric); } else { AppMsg.makeText(getActivity(), R.string.decryption_successful, AppMsg.STYLE_INFO).show(); |