diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java index d0b18d757..948227819 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CachedSecretKey.java @@ -41,17 +41,18 @@ public class CachedSecretKey extends CachedPublicKey { return (CachedSecretKeyRing) mRing; } - public void unlock(String passphrase) throws PgpGeneralException { + public boolean unlock(String passphrase) throws PgpGeneralException { try { PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); mPrivateKey = mSecretKey.extractPrivateKey(keyDecryptor); } catch (PGPException e) { - throw new PgpGeneralException("error extracting key!", e); + return false; } if(mPrivateKey == null) { - throw new PgpGeneralException("error extracting key (bad passphrase?)"); + throw new PgpGeneralException("error extracting key"); } + return true; } public PGPSignatureGenerator getSignatureGenerator(int hashAlgo, boolean cleartext) 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 37dfee8b9..27e9e8ebd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -344,9 +344,11 @@ public class PgpDecryptVerify { currentProgress += 5; updateProgress(R.string.progress_extracting_key, currentProgress, 100); try { - secretEncryptionKey.unlock(mPassphrase); - } catch (PgpGeneralException e) { - throw new WrongPassphraseException(); + if (!secretEncryptionKey.unlock(mPassphrase)) { + throw new WrongPassphraseException(); + } + } catch(PgpGeneralException e) { + throw new KeyExtractionException(); } currentProgress += 5; updateProgress(R.string.progress_preparing_streams, currentProgress, 100); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 7251709e0..1dfbfaf3a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -338,8 +338,8 @@ public class PgpKeyOperation { } public UncachedKeyRing buildSecretKey(CachedSecretKeyRing wmKR, - CachedPublicKeyRing wpKR, - SaveKeyringParcel saveParcel) + CachedPublicKeyRing wpKR, + SaveKeyringParcel saveParcel) throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException { PGPSecretKeyRing mKR = wmKR.getRing(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index b135f8920..f2abd915e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -293,14 +293,6 @@ public class ProviderHelper { } } - @Deprecated - public PGPPublicKeyRing getPGPPublicKeyRingWithKeyId(long keyId) - throws NotFoundException { - Uri uri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId)); - long masterKeyId = getMasterKeyId(uri); - return getPGPPublicKeyRing(masterKeyId); - } - @Deprecated public PGPSecretKeyRing getPGPSecretKeyRingWithKeyId(long keyId) throws NotFoundException { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 972362f5f..af6e66937 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -801,7 +801,9 @@ public class KeychainIntentService extends IntentService CachedPublicKeyRing publicRing = providerHelper.getCachedPublicKeyRing(pubKeyId); CachedSecretKeyRing secretKeyRing = providerHelper.getCachedSecretKeyRing(masterKeyId); CachedSecretKey certificationKey = secretKeyRing.getSubKey(); - certificationKey.unlock(signaturePassphrase); + if(!certificationKey.unlock(signaturePassphrase)) { + throw new PgpGeneralException("Error extracting key (bad passphrase?)"); + } UncachedKeyRing newRing = certificationKey.certifyUserIds(publicRing, userIds); // store the signed key in our local cache diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java index 3cb1ce7b4..256d9d4b7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java @@ -41,17 +41,12 @@ import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import android.widget.Toast; -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPPrivateKey; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; -import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.pgp.CachedSecretKey; +import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.util.Log; @@ -139,18 +134,17 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor alert.setTitle(R.string.title_authentication); - final PGPSecretKey secretKey; + final CachedSecretKeyRing secretRing; final String userId; if (secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none) { - secretKey = null; + secretRing = null; alert.setMessage(R.string.passphrase_for_symmetric_encryption); } else { try { ProviderHelper helper = new ProviderHelper(activity); - secretKey = helper.getPGPSecretKeyRing(secretKeyId).getSecretKey(); - userId = (String) helper.getUnifiedData(secretKeyId, - KeychainContract.KeyRings.USER_ID, ProviderHelper.FIELD_TYPE_STRING); + secretRing = helper.getCachedSecretKeyRing(secretKeyId); + userId = secretRing.getPrimaryUserId(); } catch (ProviderHelper.NotFoundException e) { alert.setTitle(R.string.title_key_not_found); alert.setMessage(getString(R.string.key_not_found, secretKeyId)); @@ -179,76 +173,59 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor @Override public void onClick(DialogInterface dialog, int id) { dismiss(); - long curKeyIndex = 1; - boolean keyOK = true; + String passphrase = mPassphraseEditText.getText().toString(); - long keyId; - PGPSecretKey clickSecretKey = secretKey; - if (clickSecretKey != null) { - while (keyOK) { - if (clickSecretKey != null) { // check again for loop - try { - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( - passphrase.toCharArray()); - PGPPrivateKey testKey = clickSecretKey - .extractPrivateKey(keyDecryptor); - if (testKey == null) { - if (!clickSecretKey.isMasterKey()) { - Toast.makeText(activity, - R.string.error_could_not_extract_private_key, - Toast.LENGTH_SHORT).show(); - - sendMessageToHandler(MESSAGE_CANCEL); - return; - } else { - try { - clickSecretKey = PgpKeyHelper.getKeyNum(new ProviderHelper(activity) - .getPGPSecretKeyRingWithKeyId(secretKeyId), - curKeyIndex - ); - } catch (ProviderHelper.NotFoundException e) { - Log.e(Constants.TAG, "key not found!", e); - } - curKeyIndex++; // does post-increment work like C? - continue; - } - } else { - keyOK = false; - } - } catch (PGPException e) { - Toast.makeText(activity, R.string.wrong_passphrase, - Toast.LENGTH_SHORT).show(); - - sendMessageToHandler(MESSAGE_CANCEL); - return; - } - } else { - Toast.makeText(activity, R.string.error_could_not_extract_private_key, - Toast.LENGTH_SHORT).show(); - - sendMessageToHandler(MESSAGE_CANCEL); - return; // ran out of keys to try - } - } - keyId = secretKey.getKeyID(); - } else { - keyId = Constants.key.symmetric; + // Early breakout if we are dealing with a symmetric key + if (secretRing == null) { + PassphraseCacheService.addCachedPassphrase(activity, Constants.key.symmetric, passphrase); + // also return passphrase back to activity + Bundle data = new Bundle(); + data.putString(MESSAGE_DATA_PASSPHRASE, passphrase); + sendMessageToHandler(MESSAGE_OKAY, data); + return; } + CachedSecretKey unlockedSecretKey = null; + + for(CachedSecretKey clickSecretKey : secretRing.iterator()) { + try { + boolean unlocked = clickSecretKey.unlock(passphrase); + if (unlocked) { + unlockedSecretKey = clickSecretKey; + break; + } + } catch (PgpGeneralException e) { + Toast.makeText(activity, R.string.error_could_not_extract_private_key, + Toast.LENGTH_SHORT).show(); + + sendMessageToHandler(MESSAGE_CANCEL); + return; // ran out of keys to try + } + } + + // Means we got an exception every time + if (unlockedSecretKey == null) { + Toast.makeText(activity, R.string.wrong_passphrase, + Toast.LENGTH_SHORT).show(); + + sendMessageToHandler(MESSAGE_CANCEL); + return; + } + + long masterKeyId = secretRing.getMasterKeyId(); + // cache the new passphrase Log.d(Constants.TAG, "Everything okay! Caching entered passphrase"); - PassphraseCacheService.addCachedPassphrase(activity, keyId, passphrase); - if (!keyOK && clickSecretKey.getKeyID() != keyId) { - PassphraseCacheService.addCachedPassphrase(activity, clickSecretKey.getKeyID(), - passphrase); + PassphraseCacheService.addCachedPassphrase(activity, masterKeyId, passphrase); + if (unlockedSecretKey.getKeyId() != masterKeyId) { + PassphraseCacheService.addCachedPassphrase( + activity, unlockedSecretKey.getKeyId(), passphrase); } // also return passphrase back to activity Bundle data = new Bundle(); data.putString(MESSAGE_DATA_PASSPHRASE, passphrase); - sendMessageToHandler(MESSAGE_OKAY, data); } });