diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java')
-rw-r--r-- | OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java | 134 |
1 files changed, 61 insertions, 73 deletions
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 12fd77141..5f47ee13c 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.WrappedSecretKey; +import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing; 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; @@ -106,8 +101,12 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor long secretKeyId) throws PgpGeneralException { // check if secret key has a passphrase if (!(secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none)) { - if (!PassphraseCacheService.hasPassphrase(context, secretKeyId)) { - throw new PgpGeneralException("No passphrase! No passphrase dialog needed!"); + try { + if (!new ProviderHelper(context).getWrappedSecretKeyRing(secretKeyId).hasPassphrase()) { + throw new PgpGeneralException("No passphrase! No passphrase dialog needed!"); + } + } catch(ProviderHelper.NotFoundException e) { + throw new PgpGeneralException("Error: Key not found!", e); } } @@ -139,18 +138,24 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor alert.setTitle(R.string.title_authentication); - final PGPSecretKey secretKey; - final String userId; + final WrappedSecretKeyRing secretRing; + String userId; if (secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none) { - secretKey = null; alert.setMessage(R.string.passphrase_for_symmetric_encryption); + secretRing = null; } 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.getWrappedSecretKeyRing(secretKeyId); + // yes the inner try/catch block is necessary, otherwise the final variable + // above can't be statically verified to have been set in all cases because + // the catch clause doesn't return. + try { + userId = secretRing.getPrimaryUserId(); + } catch (PgpGeneralException e) { + userId = null; + } } catch (ProviderHelper.NotFoundException e) { alert.setTitle(R.string.title_key_not_found); alert.setMessage(getString(R.string.key_not_found, secretKeyId)); @@ -179,76 +184,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 + + // 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; + } + + WrappedSecretKey unlockedSecretKey = null; + + for(WrappedSecretKey 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 } - keyId = secretKey.getKeyID(); - } else { - keyId = Constants.key.symmetric; } + // 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); } }); |