fixes for empty passphrase

This commit is contained in:
Dominik 2012-06-09 19:12:19 +03:00
parent 404ba01424
commit 5576a847a6
3 changed files with 85 additions and 54 deletions

View File

@ -507,8 +507,9 @@ public class Apg {
PGPPublicKey tmpKey = masterKey.getPublicKey(); PGPPublicKey tmpKey = masterKey.getPublicKey();
PGPPublicKey masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(), PGPPublicKey masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(),
tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime()); tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime());
PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(oldPassPhrase.toCharArray(), PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
new BouncyCastleProvider()); .setProvider("SC").build(oldPassPhrase.toCharArray());
PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(keyDecryptor);
if (progress != null) if (progress != null)
progress.setProgress(R.string.progress_certifyingMasterKey, 20, 100); progress.setProgress(R.string.progress_certifyingMasterKey, 20, 100);
@ -572,8 +573,10 @@ public class Apg {
PGPSecretKey subKey = keys.get(i); PGPSecretKey subKey = keys.get(i);
// keyEditor = (KeyEditor) keyEditors.getChildAt(i); // keyEditor = (KeyEditor) keyEditors.getChildAt(i);
PGPPublicKey subPublicKey = subKey.getPublicKey(); PGPPublicKey subPublicKey = subKey.getPublicKey();
PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(oldPassPhrase.toCharArray(),
new BouncyCastleProvider()); PBESecretKeyDecryptor keyDecryptor2 = new JcePBESecretKeyDecryptorBuilder()
.setProvider("SC").build(oldPassPhrase.toCharArray());
PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(keyDecryptor2);
PGPKeyPair subKeyPair = new PGPKeyPair(subPublicKey.getAlgorithm(), PGPKeyPair subKeyPair = new PGPKeyPair(subPublicKey.getAlgorithm(),
subPublicKey.getKey(new BouncyCastleProvider()), subPrivateKey.getKey(), subPublicKey.getKey(new BouncyCastleProvider()), subPrivateKey.getKey(),
subPublicKey.getCreationTime()); subPublicKey.getCreationTime());
@ -642,8 +645,10 @@ public class Apg {
PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring; PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring;
boolean save = true; boolean save = true;
try { try {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
.setProvider("SC").build(new char[] {});
PGPPrivateKey testKey = secretKeyRing.getSecretKey().extractPrivateKey( PGPPrivateKey testKey = secretKeyRing.getSecretKey().extractPrivateKey(
new char[] {}, new BouncyCastleProvider()); keyDecryptor);
if (testKey == null) { if (testKey == null) {
// this is bad, something is very wrong... likely a --export-secret-subkeys // this is bad, something is very wrong... likely a --export-secret-subkeys
// export // export
@ -1311,8 +1316,9 @@ public class Apg {
} }
if (progress != null) if (progress != null)
progress.setProgress(R.string.progress_extractingSignatureKey, 0, 100); progress.setProgress(R.string.progress_extractingSignatureKey, 0, 100);
signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(), PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
new BouncyCastleProvider()); "SC").build(signaturePassPhrase.toCharArray());
signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
if (signaturePrivateKey == null) { if (signaturePrivateKey == null) {
throw new GeneralException( throw new GeneralException(
context.getString(R.string.error_couldNotExtractPrivateKey)); context.getString(R.string.error_couldNotExtractPrivateKey));
@ -1450,8 +1456,9 @@ public class Apg {
if (signaturePassPhrase == null) { if (signaturePassPhrase == null) {
throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase)); throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase));
} }
signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(), PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
new BouncyCastleProvider()); .setProvider("SC").build(signaturePassPhrase.toCharArray());
signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
if (signaturePrivateKey == null) { if (signaturePrivateKey == null) {
throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey)); throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey));
} }
@ -1562,8 +1569,9 @@ public class Apg {
if (signaturePassPhrase == null) { if (signaturePassPhrase == null) {
throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase)); throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase));
} }
signaturePrivateKey = signingKey.extractPrivateKey(signaturePassPhrase.toCharArray(), PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
new BouncyCastleProvider()); .setProvider("SC").build(signaturePassPhrase.toCharArray());
signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor);
if (signaturePrivateKey == null) { if (signaturePrivateKey == null) {
throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey)); throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey));
} }
@ -1804,8 +1812,9 @@ public class Apg {
progress.setProgress(R.string.progress_extractingKey, currentProgress, 100); progress.setProgress(R.string.progress_extractingKey, currentProgress, 100);
PGPPrivateKey privateKey = null; PGPPrivateKey privateKey = null;
try { try {
privateKey = secretKey.extractPrivateKey(passPhrase.toCharArray(), PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
new BouncyCastleProvider()); .setProvider("SC").build(passPhrase.toCharArray());
privateKey = secretKey.extractPrivateKey(keyDecryptor);
} catch (PGPException e) { } catch (PGPException e) {
throw new PGPException(context.getString(R.string.error_wrongPassPhrase)); throw new PGPException(context.getString(R.string.error_wrongPassPhrase));
} }

View File

@ -649,7 +649,6 @@ public class EncryptActivity extends SherlockFragmentActivity {
} }
if (getSecretKeyId() != 0 && Apg.getCachedPassPhrase(getSecretKeyId()) == null) { if (getSecretKeyId() != 0 && Apg.getCachedPassPhrase(getSecretKeyId()) == null) {
// showDialog(Id.dialog.pass_phrase);
showPassphraseDialog(); showPassphraseDialog();
return; return;
@ -672,7 +671,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
Handler returnHandler = new Handler() { Handler returnHandler = new Handler() {
@Override @Override
public void handleMessage(Message message) { public void handleMessage(Message message) {
if (message.arg1 == PassphraseDialogFragment.MESSAGE_OKAY) { if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
if (mEncryptTarget == Id.target.file) { if (mEncryptTarget == Id.target.file) {
askForOutputFilename(); askForOutputFilename();
} else { } else {
@ -685,12 +684,15 @@ public class EncryptActivity extends SherlockFragmentActivity {
// Create a new Messenger for the communication back // Create a new Messenger for the communication back
Messenger messenger = new Messenger(returnHandler); Messenger messenger = new Messenger(returnHandler);
try {
PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance( PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
mSecretKeyId, messenger); mSecretKeyId, messenger);
// no passphrase for this secret key -> passphraseDialog is null
if (passphraseDialog != null) {
passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
} catch (Apg.GeneralException e) {
Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
// send message to handler to start encryption directly
returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
} }
} }

View File

@ -16,11 +16,13 @@
package org.thialfihar.android.apg.ui.dialog; package org.thialfihar.android.apg.ui.dialog;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPPrivateKey; import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
import org.thialfihar.android.apg.Apg; import org.thialfihar.android.apg.Apg;
import org.thialfihar.android.apg.Apg.GeneralException;
import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R; import org.thialfihar.android.apg.R;
@ -59,17 +61,57 @@ public class PassphraseDialogFragment extends DialogFragment {
* @param messenger * @param messenger
* to communicate back after caching the passphrase * to communicate back after caching the passphrase
* @return * @return
* @throws GeneralException
*/ */
public static PassphraseDialogFragment newInstance(long secretKeyId, Messenger messenger) { public static PassphraseDialogFragment newInstance(long secretKeyId, Messenger messenger)
throws GeneralException {
// check if secret key has a passphrase
if (!(secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none)) {
if (!hasPassphrase(secretKeyId)) {
throw new Apg.GeneralException("No passphrase! No passphrase dialog needed!");
}
}
PassphraseDialogFragment frag = new PassphraseDialogFragment(); PassphraseDialogFragment frag = new PassphraseDialogFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putLong(ARG_SECRET_KEY_ID, secretKeyId); args.putLong(ARG_SECRET_KEY_ID, secretKeyId);
args.putParcelable(ARG_MESSENGER, messenger); args.putParcelable(ARG_MESSENGER, messenger);
frag.setArguments(args); frag.setArguments(args);
return frag; return frag;
} }
/**
* Checks if key has a passphrase
*
* @param secretKeyId
* @return true if it has a passphrase
*/
private static boolean hasPassphrase(long secretKeyId) {
// check if the key has no passphrase
try {
PGPSecretKey secretKey = Apg.getMasterKey(Apg.getSecretKeyRing(secretKeyId));
Log.d(Constants.TAG, "Check if key has no passphrase...");
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
"SC").build("".toCharArray());
PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
if (testKey != null) {
Log.d(Constants.TAG, "Key has no passphrase! Caches empty passphrase!");
// cache empty passphrase
Apg.setCachedPassPhrase(secretKey.getKeyID(), "");
return false;
}
} catch (PGPException e) {
// silently catch
}
return true;
}
/** /**
* Creates dialog * Creates dialog
*/ */
@ -119,17 +161,17 @@ public class PassphraseDialogFragment extends DialogFragment {
alert.setView(view); alert.setView(view);
// final PassPhraseCallbackInterface cb = callback;
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
// activity.removeDialog(Id.dialog.pass_phrase);
dismiss(); dismiss();
String passPhrase = input.getText().toString(); String passPhrase = input.getText().toString();
long keyId; long keyId;
if (secretKey != null) { if (secretKey != null) {
try { try {
PGPPrivateKey testKey = secretKey.extractPrivateKey( PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
passPhrase.toCharArray(), new BouncyCastleProvider()); .setProvider("SC").build(passPhrase.toCharArray());
PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
if (testKey == null) { if (testKey == null) {
Toast.makeText(activity, R.string.error_couldNotExtractPrivateKey, Toast.makeText(activity, R.string.error_couldNotExtractPrivateKey,
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
@ -145,54 +187,32 @@ public class PassphraseDialogFragment extends DialogFragment {
keyId = Id.key.symmetric; keyId = Id.key.symmetric;
} }
// cache again // cache the new passphrase
Log.d(Constants.TAG, "Everything okay! Caching entered passphrase");
Apg.setCachedPassPhrase(keyId, passPhrase); Apg.setCachedPassPhrase(keyId, passPhrase);
// return by callback
// cb.passPhraseCallback(keyId, passPhrase);
sendMessageToHandler(MESSAGE_OKAY); sendMessageToHandler(MESSAGE_OKAY);
} }
}); });
alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
// activity.removeDialog(Id.dialog.pass_phrase);
dismiss(); dismiss();
} }
}); });
// check if the key has no passphrase
if (secretKey != null) {
try {
Log.d(Constants.TAG, "Check if key has no passphrase...");
PGPPrivateKey testKey = secretKey.extractPrivateKey("".toCharArray(),
new BouncyCastleProvider());
if (testKey != null) {
Log.d(Constants.TAG, "Key has no passphrase!");
// cache null
Apg.setCachedPassPhrase(secretKey.getKeyID(), null);
// return by callback
// cb.passPhraseCallback(secretKey.getKeyID(), null);
sendMessageToHandler(MESSAGE_OKAY);
return null;
}
} catch (PGPException e) {
}
}
return alert.create(); return alert.create();
} }
/** /**
* Send message back to handler which is initialized in a activity * Send message back to handler which is initialized in a activity
* *
* @param arg1 * @param what
* Message you want to send * Message integer you want to send
*/ */
private void sendMessageToHandler(Integer arg1) { private void sendMessageToHandler(Integer what) {
Message msg = Message.obtain(); Message msg = Message.obtain();
msg.arg1 = arg1; msg.what = what;
try { try {
mMessenger.send(msg); mMessenger.send(msg);