Passphrase handling in encrypt

This commit is contained in:
Dominik Schürmann 2014-09-17 20:40:02 +02:00
parent 8724916866
commit 1abf167f80
6 changed files with 81 additions and 42 deletions

View File

@ -607,6 +607,7 @@
<activity <activity
android:name=".ui.ConsolidateDialogActivity" android:name=".ui.ConsolidateDialogActivity"
android:theme="@android:style/Theme.NoDisplay" /> android:theme="@android:style/Theme.NoDisplay" />
<!-- stateHidden -->
<activity <activity
android:name=".ui.PassphraseDialogActivity" android:name=".ui.PassphraseDialogActivity"
android:theme="@android:style/Theme.NoDisplay" /> android:theme="@android:style/Theme.NoDisplay" />

View File

@ -132,14 +132,13 @@ public class KeychainIntentService extends IntentService implements Progressable
// encrypt // encrypt
public static final String ENCRYPT_SIGNATURE_MASTER_ID = "secret_key_id"; public static final String ENCRYPT_SIGNATURE_MASTER_ID = "secret_key_id";
public static final String ENCRYPT_SIGNATURE_KEY_PASSPHRASE = "secret_key_passphrase";
public static final String ENCRYPT_USE_ASCII_ARMOR = "use_ascii_armor"; public static final String ENCRYPT_USE_ASCII_ARMOR = "use_ascii_armor";
public static final String ENCRYPT_ENCRYPTION_KEYS_IDS = "encryption_keys_ids"; public static final String ENCRYPT_ENCRYPTION_KEYS_IDS = "encryption_keys_ids";
public static final String ENCRYPT_COMPRESSION_ID = "compression_id"; public static final String ENCRYPT_COMPRESSION_ID = "compression_id";
public static final String ENCRYPT_MESSAGE_BYTES = "message_bytes"; public static final String ENCRYPT_MESSAGE_BYTES = "message_bytes";
public static final String ENCRYPT_INPUT_FILE = "input_file";
public static final String ENCRYPT_INPUT_URI = "input_uri"; public static final String ENCRYPT_INPUT_URI = "input_uri";
public static final String ENCRYPT_INPUT_URIS = "input_uris"; public static final String ENCRYPT_INPUT_URIS = "input_uris";
public static final String ENCRYPT_OUTPUT_FILE = "output_file";
public static final String ENCRYPT_OUTPUT_URI = "output_uri"; public static final String ENCRYPT_OUTPUT_URI = "output_uri";
public static final String ENCRYPT_OUTPUT_URIS = "output_uris"; public static final String ENCRYPT_OUTPUT_URIS = "output_uris";
public static final String ENCRYPT_SYMMETRIC_PASSPHRASE = "passphrase"; public static final String ENCRYPT_SYMMETRIC_PASSPHRASE = "passphrase";
@ -255,6 +254,7 @@ public class KeychainIntentService extends IntentService implements Progressable
Bundle resultData = new Bundle(); Bundle resultData = new Bundle();
long sigMasterKeyId = data.getLong(ENCRYPT_SIGNATURE_MASTER_ID); long sigMasterKeyId = data.getLong(ENCRYPT_SIGNATURE_MASTER_ID);
String sigKeyPassphrase = data.getString(ENCRYPT_SIGNATURE_KEY_PASSPHRASE);
String symmetricPassphrase = data.getString(ENCRYPT_SYMMETRIC_PASSPHRASE); String symmetricPassphrase = data.getString(ENCRYPT_SYMMETRIC_PASSPHRASE);
boolean useAsciiArmor = data.getBoolean(ENCRYPT_USE_ASCII_ARMOR); boolean useAsciiArmor = data.getBoolean(ENCRYPT_USE_ASCII_ARMOR);
@ -300,14 +300,10 @@ public class KeychainIntentService extends IntentService implements Progressable
new ProviderHelper(this).getCachedPublicKeyRing(sigMasterKeyId); new ProviderHelper(this).getCachedPublicKeyRing(sigMasterKeyId);
long sigSubKeyId = signingRing.getSignId(); long sigSubKeyId = signingRing.getSignId();
// Get its passphrase from cache. It is assumed that this passphrase was
// cached prior to the service call.
String passphrase = PassphraseCacheService.getCachedPassphrase(this, sigSubKeyId);
// Set signature settings // Set signature settings
builder.setSignatureMasterKeyId(sigMasterKeyId) builder.setSignatureMasterKeyId(sigMasterKeyId)
.setSignatureSubKeyId(sigSubKeyId) .setSignatureSubKeyId(sigSubKeyId)
.setSignaturePassphrase(passphrase) .setSignaturePassphrase(sigKeyPassphrase)
.setSignatureHashAlgorithm( .setSignatureHashAlgorithm(
Preferences.getPreferences(this).getDefaultHashAlgorithm()) Preferences.getPreferences(this).getDefaultHashAlgorithm())
.setAdditionalEncryptId(sigMasterKeyId); .setAdditionalEncryptId(sigMasterKeyId);

View File

@ -5,6 +5,23 @@ import android.content.Intent;
import org.sufficientlysecure.keychain.nfc.NfcActivity; import org.sufficientlysecure.keychain.nfc.NfcActivity;
public class EncryptActivity extends DrawerActivity { public class EncryptActivity extends DrawerActivity {
public static final int REQUEST_CODE_PASSPHRASE = 0x00008001;
public static final int REQUEST_CODE_NFC = 0x00008002;
protected void startPassphraseDialog(long subkeyId) {
Intent data = new Intent();
// build PendingIntent for Yubikey NFC operations
Intent intent = new Intent(this, PassphraseDialogActivity.class);
// pass params through to activity that it can be returned again later to repeat pgp operation
intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, subkeyId);
// intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
}
protected void startNfcSign(String pin, byte[] hashToSign, int hashAlgo) { protected void startNfcSign(String pin, byte[] hashToSign, int hashAlgo) {
Intent data = new Intent(); Intent data = new Intent();
@ -19,19 +36,8 @@ public class EncryptActivity extends DrawerActivity {
intent.putExtra(NfcActivity.EXTRA_NFC_HASH_ALGO, hashAlgo); intent.putExtra(NfcActivity.EXTRA_NFC_HASH_ALGO, hashAlgo);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(intent, 0); startActivityForResult(intent, REQUEST_CODE_NFC);
} }
protected void startPassphraseDialog(long subkeyId) {
Intent data = new Intent();
// build PendingIntent for Yubikey NFC operations
Intent intent = new Intent(this, PassphraseDialogActivity.class);
// pass params through to activity that it can be returned again later to repeat pgp operation
intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, subkeyId);
// intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(intent, 0);
}
} }

View File

@ -70,6 +70,7 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
private String mEncryptionUserIds[] = null; private String mEncryptionUserIds[] = null;
// TODO Constants.key.none? What's wrong with a null value? // TODO Constants.key.none? What's wrong with a null value?
private long mSigningKeyId = Constants.key.none; private long mSigningKeyId = Constants.key.none;
private String mSigningKeyPassphrase = null;
private String mPassphrase = ""; private String mPassphrase = "";
private boolean mShareAfterEncrypt = false; private boolean mShareAfterEncrypt = false;
private ArrayList<Uri> mInputUris; private ArrayList<Uri> mInputUris;
@ -219,6 +220,9 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
// Notify.showNotify(EncryptTextActivity.this, // Notify.showNotify(EncryptTextActivity.this,
// R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO); // R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO);
} }
// reset parameters, TODO: better state saving?
mSigningKeyPassphrase = null;
} else { } else {
pgpResult.createNotify(EncryptTextActivity.this).show(); pgpResult.createNotify(EncryptTextActivity.this).show();
} }
@ -236,6 +240,34 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
startService(intent); startService(intent);
} }
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_PASSPHRASE: {
if (resultCode == RESULT_OK && data != null) {
mSigningKeyPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
startEncrypt();
return;
}
break;
}
case REQUEST_CODE_NFC: {
if (resultCode == RESULT_OK && data != null) {
startEncrypt();
return;
}
break;
}
default: {
super.onActivityResult(requestCode, resultCode, data);
break;
}
}
}
private Bundle createEncryptBundle() { private Bundle createEncryptBundle() {
// fill values for this action // fill values for this action
Bundle data = new Bundle(); Bundle data = new Bundle();
@ -259,6 +291,8 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
} else { } else {
data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_MASTER_ID, mSigningKeyId); data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_MASTER_ID, mSigningKeyId);
data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, mEncryptionKeyIds); data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, mEncryptionKeyIds);
data.putString(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_PASSPHRASE, mSigningKeyPassphrase);
data.putLongArray(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_PASSPHRASE, mEncryptionKeyIds);
} }
return data; return data;
} }

View File

@ -25,9 +25,9 @@ import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Messenger;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentActivity;
import android.view.ContextThemeWrapper;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -102,7 +102,6 @@ public class PassphraseDialogActivity extends FragmentActivity {
} }
public static class PassphraseDialogFragment extends DialogFragment implements TextView.OnEditorActionListener { public static class PassphraseDialogFragment extends DialogFragment implements TextView.OnEditorActionListener {
private Messenger mMessenger;
private EditText mPassphraseEditText; private EditText mPassphraseEditText;
private View mInput, mProgress; private View mInput, mProgress;
@ -116,9 +115,15 @@ public class PassphraseDialogActivity extends FragmentActivity {
@Override @Override
public Dialog onCreateDialog(Bundle savedInstanceState) { public Dialog onCreateDialog(Bundle savedInstanceState) {
final Activity activity = getActivity(); final Activity activity = getActivity();
// if the dialog is displayed from the application class, design is missing
// hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay
ContextThemeWrapper theme = new ContextThemeWrapper(activity,
R.style.Theme_AppCompat_Light);
mSubKeyId = getArguments().getLong(EXTRA_SUBKEY_ID); mSubKeyId = getArguments().getLong(EXTRA_SUBKEY_ID);
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity); CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(theme);
alert.setTitle(R.string.title_authentication); alert.setTitle(R.string.title_authentication);
@ -174,7 +179,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
alert.setMessage(message); alert.setMessage(message);
} }
LayoutInflater inflater = activity.getLayoutInflater(); LayoutInflater inflater = LayoutInflater.from(theme);
View view = inflater.inflate(R.layout.passphrase_dialog, null); View view = inflater.inflate(R.layout.passphrase_dialog, null);
alert.setView(view); alert.setView(view);
@ -201,6 +206,9 @@ public class PassphraseDialogActivity extends FragmentActivity {
mPassphraseEditText.post(new Runnable() { mPassphraseEditText.post(new Runnable() {
@Override @Override
public void run() { public void run() {
if (getActivity() == null || mPassphraseEditText == null) {
return;
}
InputMethodManager imm = (InputMethodManager) getActivity() InputMethodManager imm = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE); .getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(mPassphraseEditText, InputMethodManager.SHOW_IMPLICIT); imm.showSoftInput(mPassphraseEditText, InputMethodManager.SHOW_IMPLICIT);
@ -320,32 +328,27 @@ public class PassphraseDialogActivity extends FragmentActivity {
// note we need no synchronization here, this variable is only accessed in the ui thread // note we need no synchronization here, this variable is only accessed in the ui thread
mIsCancelled = true; mIsCancelled = true;
// dismiss the dialogue
getActivity().setResult(RESULT_CANCELED);
dismiss();
getActivity().finish();
} }
@Override @Override
public void onDismiss(DialogInterface dialog) { public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog); super.onDismiss(dialog);
Log.d(Constants.TAG, "onDismiss");
// hide keyboard on dismiss
hideKeyboard(); hideKeyboard();
getActivity().setResult(RESULT_CANCELED);
getActivity().finish();
} }
private void hideKeyboard() { private void hideKeyboard() {
if (getActivity() == null) {
return;
}
InputMethodManager inputManager = (InputMethodManager) getActivity() InputMethodManager inputManager = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE); .getSystemService(Context.INPUT_METHOD_SERVICE);
//check if no view has focus: inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
View v = getActivity().getCurrentFocus();
if (v == null)
return;
inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
} }
/** /**
@ -364,4 +367,6 @@ public class PassphraseDialogActivity extends FragmentActivity {
} }
} }
} }

View File

@ -1,8 +1,7 @@
package org.sufficientlysecure.keychain.ui.dialog; package org.sufficientlysecure.keychain.ui.dialog;
import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.view.ContextThemeWrapper; import android.content.Context;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
@ -16,10 +15,8 @@ import org.sufficientlysecure.keychain.R;
*/ */
public class CustomAlertDialogBuilder extends AlertDialog.Builder { public class CustomAlertDialogBuilder extends AlertDialog.Builder {
public CustomAlertDialogBuilder(Activity activity) { public CustomAlertDialogBuilder(Context context) {
// if the progress dialog is displayed from the application class, design is missing super(context);
// hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay
super(new ContextThemeWrapper(activity, R.style.Theme_AppCompat_Light));
} }
@Override @Override