Merge remote-tracking branch 'origin/master' into development

Conflicts:
	OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
	OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
	OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java
	OpenKeychain/src/main/res/values/strings.xml
This commit is contained in:
Vincent Breitmoser 2015-05-28 23:05:41 +02:00
commit 38d8f4be52
14 changed files with 122 additions and 80 deletions

View File

@ -72,9 +72,9 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
private PGPPrivateKey mPrivateKey = null; private PGPPrivateKey mPrivateKey = null;
private int mPrivateKeyState = PRIVATE_KEY_STATE_LOCKED; private int mPrivateKeyState = PRIVATE_KEY_STATE_LOCKED;
private static int PRIVATE_KEY_STATE_LOCKED = 0; final private static int PRIVATE_KEY_STATE_LOCKED = 0;
private static int PRIVATE_KEY_STATE_UNLOCKED = 1; final private static int PRIVATE_KEY_STATE_UNLOCKED = 1;
private static int PRIVATE_KEY_STATE_DIVERT_TO_CARD = 2; final private static int PRIVATE_KEY_STATE_DIVERT_TO_CARD = 2;
CanonicalizedSecretKey(CanonicalizedSecretKeyRing ring, PGPSecretKey key) { CanonicalizedSecretKey(CanonicalizedSecretKeyRing ring, PGPSecretKey key) {
super(ring, key.getPublicKey()); super(ring, key.getPublicKey());
@ -126,9 +126,10 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
} }
public SecretKeyType getSecretKeyType() { public SecretKeyType getSecretKeyType() {
if (mSecretKey.getS2K() != null && mSecretKey.getS2K().getType() == S2K.GNU_DUMMY_S2K) { S2K s2k = mSecretKey.getS2K();
if (s2k != null && s2k.getType() == S2K.GNU_DUMMY_S2K) {
// divert to card is special // divert to card is special
if (mSecretKey.getS2K().getProtectionMode() == S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD) { if (s2k.getProtectionMode() == S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD) {
return SecretKeyType.DIVERT_TO_CARD; return SecretKeyType.DIVERT_TO_CARD;
} }
// no matter the exact protection mode, it's some kind of dummy key // no matter the exact protection mode, it's some kind of dummy key
@ -159,9 +160,10 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
*/ */
public boolean unlock(Passphrase passphrase) throws PgpGeneralException { public boolean unlock(Passphrase passphrase) throws PgpGeneralException {
// handle keys on OpenPGP cards like they were unlocked // handle keys on OpenPGP cards like they were unlocked
if (mSecretKey.getS2K() != null S2K s2k = mSecretKey.getS2K();
&& mSecretKey.getS2K().getType() == S2K.GNU_DUMMY_S2K if (s2k != null
&& mSecretKey.getS2K().getProtectionMode() == S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD) { && s2k.getType() == S2K.GNU_DUMMY_S2K
&& s2k.getProtectionMode() == S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD) {
mPrivateKeyState = PRIVATE_KEY_STATE_DIVERT_TO_CARD; mPrivateKeyState = PRIVATE_KEY_STATE_DIVERT_TO_CARD;
return true; return true;
} }

View File

@ -602,7 +602,8 @@ public class PgpDecryptVerify extends BaseOperation {
} catch (NfcSyncPublicKeyDataDecryptorFactoryBuilder.NfcInteractionNeeded e) { } catch (NfcSyncPublicKeyDataDecryptorFactoryBuilder.NfcInteractionNeeded e) {
log.add(LogType.MSG_DC_PENDING_NFC, indent + 1); log.add(LogType.MSG_DC_PENDING_NFC, indent + 1);
return new DecryptVerifyResult(log, RequiredInputParcel.createNfcDecryptOperation( return new DecryptVerifyResult(log, RequiredInputParcel.createNfcDecryptOperation(
e.encryptedSessionKey, secretEncryptionKey.getKeyId() secretEncryptionKey.getRing().getMasterKeyId(),
secretEncryptionKey.getKeyId(), e.encryptedSessionKey
)); ));
} }
encryptedData = encryptedDataAsymmetric; encryptedData = encryptedDataAsymmetric;

View File

@ -1568,13 +1568,13 @@ public class PgpKeyOperation {
private static boolean isDummy(PGPSecretKey secretKey) { private static boolean isDummy(PGPSecretKey secretKey) {
S2K s2k = secretKey.getS2K(); S2K s2k = secretKey.getS2K();
return s2k.getType() == S2K.GNU_DUMMY_S2K return s2k != null && s2k.getType() == S2K.GNU_DUMMY_S2K
&& s2k.getProtectionMode() == S2K.GNU_PROTECTION_MODE_NO_PRIVATE_KEY; && s2k.getProtectionMode() != S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD;
} }
private static boolean isDivertToCard(PGPSecretKey secretKey) { private static boolean isDivertToCard(PGPSecretKey secretKey) {
S2K s2k = secretKey.getS2K(); S2K s2k = secretKey.getS2K();
return s2k.getType() == S2K.GNU_DUMMY_S2K return s2k != null && s2k.getType() == S2K.GNU_DUMMY_S2K
&& s2k.getProtectionMode() == S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD; && s2k.getProtectionMode() == S2K.GNU_PROTECTION_MODE_DIVERT_TO_CARD;
} }

View File

@ -497,6 +497,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
// this secret key diverts to a OpenPGP card, throw exception with hash that will be signed // this secret key diverts to a OpenPGP card, throw exception with hash that will be signed
log.add(LogType.MSG_PSE_PENDING_NFC, indent); log.add(LogType.MSG_PSE_PENDING_NFC, indent);
return new PgpSignEncryptResult(log, RequiredInputParcel.createNfcSignOperation( return new PgpSignEncryptResult(log, RequiredInputParcel.createNfcSignOperation(
signingKey.getRing().getMasterKeyId(), signingKey.getKeyId(),
e.hashToSign, e.hashAlgo, cryptoInput.getSignatureTime())); e.hashToSign, e.hashAlgo, cryptoInput.getSignatureTime()));
} }
} }

View File

@ -648,10 +648,6 @@ public class ProviderHelper {
UserPacketItem item = uids.get(userIdRank); UserPacketItem item = uids.get(userIdRank);
operations.add(buildUserIdOperations(masterKeyId, item, userIdRank)); operations.add(buildUserIdOperations(masterKeyId, item, userIdRank));
if (item.selfCert == null) {
throw new AssertionError("User ids MUST be self-certified at this point!!");
}
if (item.selfRevocation != null) { if (item.selfRevocation != null) {
operations.add(buildCertOperations(masterKeyId, userIdRank, item.selfRevocation, operations.add(buildCertOperations(masterKeyId, userIdRank, item.selfRevocation,
Certs.VERIFIED_SELF)); Certs.VERIFIED_SELF));
@ -659,6 +655,10 @@ public class ProviderHelper {
continue; continue;
} }
if (item.selfCert == null) {
throw new AssertionError("User ids MUST be self-certified at this point!!");
}
operations.add(buildCertOperations(masterKeyId, userIdRank, item.selfCert, operations.add(buildCertOperations(masterKeyId, userIdRank, item.selfCert,
selfCertsAreTrusted ? Certs.VERIFIED_SECRET : Certs.VERIFIED_SELF)); selfCertsAreTrusted ? Certs.VERIFIED_SECRET : Certs.VERIFIED_SELF));
@ -782,7 +782,7 @@ public class ProviderHelper {
// first, mark all keys as not available // first, mark all keys as not available
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(Keys.HAS_SECRET, SecretKeyType.UNAVAILABLE.getNum()); values.put(Keys.HAS_SECRET, SecretKeyType.GNU_DUMMY.getNum());
mContentResolver.update(uri, values, null, null); mContentResolver.update(uri, values, null, null);
// then, mark exactly the keys we have available // then, mark exactly the keys we have available
@ -831,7 +831,7 @@ public class ProviderHelper {
mIndent -= 1; mIndent -= 1;
// this implicitly leaves all keys which were not in the secret key ring // this implicitly leaves all keys which were not in the secret key ring
// with has_secret = 0 // with has_secret = 1
} }
log(LogType.MSG_IS_SUCCESS); log(LogType.MSG_IS_SUCCESS);

View File

@ -22,8 +22,8 @@ public class RequiredInputParcel implements Parcelable {
public final byte[][] mInputHashes; public final byte[][] mInputHashes;
public final int[] mSignAlgos; public final int[] mSignAlgos;
private Long mMasterKeyId; private long mMasterKeyId;
private Long mSubKeyId; private long mSubKeyId;
private RequiredInputParcel(RequiredInputType type, byte[][] inputHashes, private RequiredInputParcel(RequiredInputType type, byte[][] inputHashes,
int[] signAlgos, Date signatureTime, Long masterKeyId, Long subKeyId) { int[] signAlgos, Date signatureTime, Long masterKeyId, Long subKeyId) {
@ -61,8 +61,8 @@ public class RequiredInputParcel implements Parcelable {
} }
mSignatureTime = source.readInt() != 0 ? new Date(source.readLong()) : null; mSignatureTime = source.readInt() != 0 ? new Date(source.readLong()) : null;
mMasterKeyId = source.readInt() != 0 ? source.readLong() : null; mMasterKeyId = source.readLong();
mSubKeyId = source.readInt() != 0 ? source.readLong() : null; mSubKeyId = source.readLong();
} }
@ -75,15 +75,17 @@ public class RequiredInputParcel implements Parcelable {
} }
public static RequiredInputParcel createNfcSignOperation( public static RequiredInputParcel createNfcSignOperation(
long masterKeyId, long subKeyId,
byte[] inputHash, int signAlgo, Date signatureTime) { byte[] inputHash, int signAlgo, Date signatureTime) {
return new RequiredInputParcel(RequiredInputType.NFC_SIGN, return new RequiredInputParcel(RequiredInputType.NFC_SIGN,
new byte[][] { inputHash }, new int[] { signAlgo }, new byte[][] { inputHash }, new int[] { signAlgo },
signatureTime, null, null); signatureTime, masterKeyId, subKeyId);
} }
public static RequiredInputParcel createNfcDecryptOperation(byte[] inputHash, long subKeyId) { public static RequiredInputParcel createNfcDecryptOperation(
long masterKeyId, long subKeyId, byte[] inputHash) {
return new RequiredInputParcel(RequiredInputType.NFC_DECRYPT, return new RequiredInputParcel(RequiredInputType.NFC_DECRYPT,
new byte[][] { inputHash }, null, null, null, subKeyId); new byte[][] { inputHash }, null, null, masterKeyId, subKeyId);
} }
public static RequiredInputParcel createRequiredSignPassphrase( public static RequiredInputParcel createRequiredSignPassphrase(
@ -135,18 +137,8 @@ public class RequiredInputParcel implements Parcelable {
} else { } else {
dest.writeInt(0); dest.writeInt(0);
} }
if (mMasterKeyId != null) { dest.writeLong(mMasterKeyId);
dest.writeInt(1); dest.writeLong(mSubKeyId);
dest.writeLong(mMasterKeyId);
} else {
dest.writeInt(0);
}
if (mSubKeyId != null) {
dest.writeInt(1);
dest.writeLong(mSubKeyId);
} else {
dest.writeInt(0);
}
} }
@ -164,10 +156,10 @@ public class RequiredInputParcel implements Parcelable {
Date mSignatureTime; Date mSignatureTime;
ArrayList<Integer> mSignAlgos = new ArrayList<>(); ArrayList<Integer> mSignAlgos = new ArrayList<>();
ArrayList<byte[]> mInputHashes = new ArrayList<>(); ArrayList<byte[]> mInputHashes = new ArrayList<>();
Long mMasterKeyId; long mMasterKeyId;
Long mSubKeyId; long mSubKeyId;
public NfcSignOperationsBuilder(Date signatureTime, Long masterKeyId, Long subKeyId) { public NfcSignOperationsBuilder(Date signatureTime, long masterKeyId, long subKeyId) {
mSignatureTime = signatureTime; mSignatureTime = signatureTime;
mMasterKeyId = masterKeyId; mMasterKeyId = masterKeyId;
mSubKeyId = subKeyId; mSubKeyId = subKeyId;

View File

@ -18,6 +18,7 @@
package org.sufficientlysecure.keychain.ui; package org.sufficientlysecure.keychain.ui;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import android.app.Activity; import android.app.Activity;
@ -57,7 +58,6 @@ public class CreateKeyYubiKeyImportFragment extends Fragment implements NfcListe
CreateKeyActivity mCreateKeyActivity; CreateKeyActivity mCreateKeyActivity;
private byte[] mNfcFingerprints; private byte[] mNfcFingerprints;
private long mNfcMasterKeyId;
private byte[] mNfcAid; private byte[] mNfcAid;
private String mNfcUserId; private String mNfcUserId;
private String mNfcFingerprint; private String mNfcFingerprint;
@ -88,8 +88,9 @@ public class CreateKeyYubiKeyImportFragment extends Fragment implements NfcListe
mNfcAid = args.getByteArray(ARG_AID); mNfcAid = args.getByteArray(ARG_AID);
mNfcUserId = args.getString(ARG_USER_ID); mNfcUserId = args.getString(ARG_USER_ID);
mNfcMasterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mNfcFingerprints); byte[] fp = new byte[20];
mNfcFingerprint = KeyFormattingUtils.convertFingerprintToHex(mNfcFingerprints); ByteBuffer.wrap(fp).put(mNfcFingerprints, 0, 20);
mNfcFingerprint = KeyFormattingUtils.convertFingerprintToHex(fp);
} }
@ -226,9 +227,8 @@ public class CreateKeyYubiKeyImportFragment extends Fragment implements NfcListe
intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING); intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING);
String hexFp = KeyFormattingUtils.convertFingerprintToHex(mNfcFingerprints);
ArrayList<ParcelableKeyRing> keyList = new ArrayList<>(); ArrayList<ParcelableKeyRing> keyList = new ArrayList<>();
keyList.add(new ParcelableKeyRing(hexFp, null, null)); keyList.add(new ParcelableKeyRing(mNfcFingerprint, null, null));
data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, keyList); data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, keyList);
{ {
@ -258,8 +258,9 @@ public class CreateKeyYubiKeyImportFragment extends Fragment implements NfcListe
mNfcAid = mCreateKeyActivity.nfcGetAid(); mNfcAid = mCreateKeyActivity.nfcGetAid();
mNfcUserId = mCreateKeyActivity.nfcGetUserId(); mNfcUserId = mCreateKeyActivity.nfcGetUserId();
mNfcMasterKeyId = KeyFormattingUtils.getKeyIdFromFingerprint(mNfcFingerprints); byte[] fp = new byte[20];
mNfcFingerprint = KeyFormattingUtils.convertFingerprintToHex(mNfcFingerprints); ByteBuffer.wrap(fp).put(mNfcFingerprints, 0, 20);
mNfcFingerprint = KeyFormattingUtils.convertFingerprintToHex(fp);
setData(); setData();
refreshSearch(); refreshSearch();

View File

@ -60,6 +60,7 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
LoaderManager.LoaderCallbacks<Cursor> { LoaderManager.LoaderCallbacks<Cursor> {
public static final int LOADER_ID_UNIFIED = 0; public static final int LOADER_ID_UNIFIED = 0;
public static final String ARG_DECRYPT_VERIFY_RESULT = "decrypt_verify_result";
protected LinearLayout mResultLayout; protected LinearLayout mResultLayout;
protected ImageView mEncryptionIcon; protected ImageView mEncryptionIcon;
@ -75,6 +76,7 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
private LinearLayout mErrorOverlayLayout; private LinearLayout mErrorOverlayLayout;
private OpenPgpSignatureResult mSignatureResult; private OpenPgpSignatureResult mSignatureResult;
private DecryptVerifyResult mDecryptVerifyResult;
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState) { public void onViewCreated(View view, Bundle savedInstanceState) {
@ -105,6 +107,27 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
}); });
} }
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(ARG_DECRYPT_VERIFY_RESULT, mDecryptVerifyResult);
}
@Override
public void onViewStateRestored(Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
if (savedInstanceState == null) {
return;
}
DecryptVerifyResult result = savedInstanceState.getParcelable(ARG_DECRYPT_VERIFY_RESULT);
if (result != null) {
loadVerifyResult(result);
}
}
private void lookupUnknownKey(long unknownKeyId) { private void lookupUnknownKey(long unknownKeyId) {
// Message is received after importing is done in KeychainIntentService // Message is received after importing is done in KeychainIntentService
@ -183,7 +206,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements
*/ */
protected void loadVerifyResult(DecryptVerifyResult decryptVerifyResult) { protected void loadVerifyResult(DecryptVerifyResult decryptVerifyResult) {
mDecryptVerifyResult = decryptVerifyResult;
mSignatureResult = decryptVerifyResult.getSignatureResult(); mSignatureResult = decryptVerifyResult.getSignatureResult();
mResultLayout.setVisibility(View.VISIBLE); mResultLayout.setVisibility(View.VISIBLE);
// unsigned data // unsigned data

View File

@ -21,6 +21,7 @@ package org.sufficientlysecure.keychain.ui;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.Toast;
@ -46,8 +47,6 @@ public class DecryptTextActivity extends BaseActivity {
// intern // intern
public static final String ACTION_DECRYPT_FROM_CLIPBOARD = Constants.INTENT_PREFIX + "DECRYPT_TEXT_FROM_CLIPBOARD"; public static final String ACTION_DECRYPT_FROM_CLIPBOARD = Constants.INTENT_PREFIX + "DECRYPT_TEXT_FROM_CLIPBOARD";
DecryptTextFragment mFragment;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -148,6 +147,10 @@ public class DecryptTextActivity extends BaseActivity {
extras = new Bundle(); extras = new Bundle();
} }
if (savedInstanceState != null) {
return;
}
if (Intent.ACTION_SEND.equals(action) && type != null) { if (Intent.ACTION_SEND.equals(action) && type != null) {
Log.d(Constants.TAG, "ACTION_SEND"); Log.d(Constants.TAG, "ACTION_SEND");
Log.logDebugBundle(extras, "SEND extras"); Log.logDebugBundle(extras, "SEND extras");
@ -158,7 +161,7 @@ public class DecryptTextActivity extends BaseActivity {
sharedText = getPgpContent(sharedText); sharedText = getPgpContent(sharedText);
if (sharedText != null) { if (sharedText != null) {
loadFragment(savedInstanceState, sharedText); loadFragment(sharedText);
} else { } else {
Log.e(Constants.TAG, "EXTRA_TEXT does not contain PGP content!"); Log.e(Constants.TAG, "EXTRA_TEXT does not contain PGP content!");
Toast.makeText(this, R.string.error_invalid_data, Toast.LENGTH_LONG).show(); Toast.makeText(this, R.string.error_invalid_data, Toast.LENGTH_LONG).show();
@ -176,7 +179,7 @@ public class DecryptTextActivity extends BaseActivity {
extraText = getPgpContent(extraText); extraText = getPgpContent(extraText);
if (extraText != null) { if (extraText != null) {
loadFragment(savedInstanceState, extraText); loadFragment(extraText);
} else { } else {
Log.e(Constants.TAG, "EXTRA_TEXT does not contain PGP content!"); Log.e(Constants.TAG, "EXTRA_TEXT does not contain PGP content!");
Toast.makeText(this, R.string.error_invalid_data, Toast.LENGTH_LONG).show(); Toast.makeText(this, R.string.error_invalid_data, Toast.LENGTH_LONG).show();
@ -189,7 +192,7 @@ public class DecryptTextActivity extends BaseActivity {
String text = getPgpContent(clipboardText); String text = getPgpContent(clipboardText);
if (text != null) { if (text != null) {
loadFragment(savedInstanceState, text); loadFragment(text);
} else { } else {
returnInvalidResult(); returnInvalidResult();
} }
@ -209,21 +212,14 @@ public class DecryptTextActivity extends BaseActivity {
finish(); finish();
} }
private void loadFragment(Bundle savedInstanceState, String ciphertext) { private void loadFragment(String ciphertext) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
// Create an instance of the fragment // Create an instance of the fragment
mFragment = DecryptTextFragment.newInstance(ciphertext); Fragment frag = DecryptTextFragment.newInstance(ciphertext);
// Add the fragment to the 'fragment_container' FrameLayout // Add the fragment to the 'fragment_container' FrameLayout
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes! // NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
getSupportFragmentManager().beginTransaction() getSupportFragmentManager().beginTransaction()
.replace(R.id.decrypt_text_fragment_container, mFragment) .replace(R.id.decrypt_text_fragment_container, frag)
.commitAllowingStateLoss(); .commitAllowingStateLoss();
// do it immediately! // do it immediately!
getSupportFragmentManager().executePendingTransactions(); getSupportFragmentManager().executePendingTransactions();

View File

@ -28,8 +28,6 @@ import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
@ -48,17 +46,15 @@ import java.io.UnsupportedEncodingException;
public class DecryptTextFragment extends DecryptFragment { public class DecryptTextFragment extends DecryptFragment {
public static final String ARG_CIPHERTEXT = "ciphertext"; public static final String ARG_CIPHERTEXT = "ciphertext";
public static final String ARG_SHOW_MENU = "show_menu";
// view // view
private TextView mText; private TextView mText;
// model // model
private String mCiphertext; private String mCiphertext;
private boolean mShowMenuOptions = false; private boolean mShowMenuOptions;
/**
* Creates new instance of this fragment
*/
public static DecryptTextFragment newInstance(String ciphertext) { public static DecryptTextFragment newInstance(String ciphertext) {
DecryptTextFragment frag = new DecryptTextFragment(); DecryptTextFragment frag = new DecryptTextFragment();
@ -115,11 +111,24 @@ public class DecryptTextFragment extends DecryptFragment {
setHasOptionsMenu(true); setHasOptionsMenu(true);
String ciphertext = getArguments().getString(ARG_CIPHERTEXT); Bundle args = savedInstanceState == null ? getArguments() : savedInstanceState;
if (ciphertext != null) { mCiphertext = args.getString(ARG_CIPHERTEXT);
mCiphertext = ciphertext; mShowMenuOptions = args.getBoolean(ARG_SHOW_MENU, false);
if (savedInstanceState == null) {
cryptoOperation(new CryptoInputParcel()); cryptoOperation(new CryptoInputParcel());
} }
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(ARG_CIPHERTEXT, mCiphertext);
outState.putBoolean(ARG_SHOW_MENU, mShowMenuOptions);
// no need to save the decrypted text, it's in the textview
} }
@Override @Override

View File

@ -60,8 +60,9 @@ public class NfcOperationActivity extends BaseNfcActivity {
mRequiredInput = data.getParcelable(EXTRA_REQUIRED_INPUT); mRequiredInput = data.getParcelable(EXTRA_REQUIRED_INPUT);
mServiceIntent = data.getParcelable(EXTRA_SERVICE_INTENT); mServiceIntent = data.getParcelable(EXTRA_SERVICE_INTENT);
// obtain passphrase for this subkey
if (mRequiredInput.mType != RequiredInputParcel.RequiredInputType.NFC_KEYTOCARD) { if (mRequiredInput.mType != RequiredInputParcel.RequiredInputType.NFC_KEYTOCARD) {
obtainYubiKeyPin(RequiredInputParcel.createRequiredPassphrase(mRequiredInput)); obtainYubiKeyPin(mRequiredInput);
} }
} }
@ -173,7 +174,7 @@ public class NfcOperationActivity extends BaseNfcActivity {
PassphraseCacheService.clearCachedPassphrase( PassphraseCacheService.clearCachedPassphrase(
this, mRequiredInput.getMasterKeyId(), mRequiredInput.getSubKeyId()); this, mRequiredInput.getMasterKeyId(), mRequiredInput.getSubKeyId());
obtainYubiKeyPin(RequiredInputParcel.createRequiredPassphrase(mRequiredInput)); obtainYubiKeyPin(mRequiredInput);
} }
} }

View File

@ -44,6 +44,8 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.PassphraseCacheService.KeyNotFoundException;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity; import org.sufficientlysecure.keychain.ui.CreateKeyActivity;
@ -136,16 +138,29 @@ public abstract class BaseNfcActivity extends BaseActivity {
protected void obtainYubiKeyPin(RequiredInputParcel requiredInput) { protected void obtainYubiKeyPin(RequiredInputParcel requiredInput) {
// shortcut if we only use the default yubikey pin
Preferences prefs = Preferences.getPreferences(this); Preferences prefs = Preferences.getPreferences(this);
if (prefs.useDefaultYubiKeyPin()) { if (prefs.useDefaultYubiKeyPin()) {
mPin = new Passphrase("123456"); mPin = new Passphrase("123456");
return; return;
} }
Intent intent = new Intent(this, PassphraseDialogActivity.class); try {
intent.putExtra(PassphraseDialogActivity.EXTRA_REQUIRED_INPUT, Passphrase phrase = PassphraseCacheService.getCachedPassphrase(this,
RequiredInputParcel.createRequiredPassphrase(requiredInput)); requiredInput.getMasterKeyId(), requiredInput.getSubKeyId());
startActivityForResult(intent, REQUEST_CODE_PIN); if (phrase != null) {
mPin = phrase;
return;
}
Intent intent = new Intent(this, PassphraseDialogActivity.class);
intent.putExtra(PassphraseDialogActivity.EXTRA_REQUIRED_INPUT,
RequiredInputParcel.createRequiredPassphrase(requiredInput));
startActivityForResult(intent, REQUEST_CODE_PIN);
} catch (KeyNotFoundException e) {
throw new AssertionError(
"tried to find passphrase for non-existing key. this is a programming error!");
}
} }

View File

@ -219,7 +219,7 @@ public class KeyFormattingUtils {
// NOTE: Even though v3 keys are not imported we need to support both fingerprints for // NOTE: Even though v3 keys are not imported we need to support both fingerprints for
// display/comparison before import // display/comparison before import
if (fingerprint.length != 16 && fingerprint.length != 20) { if (fingerprint.length != 16 && fingerprint.length != 20) {
throw new AssertionError("No valid v3 or v4 fingerprint!"); throw new IllegalArgumentException("No valid v3 or v4 fingerprint!");
} }
return Hex.toHexString(fingerprint).toLowerCase(Locale.ENGLISH); return Hex.toHexString(fingerprint).toLowerCase(Locale.ENGLISH);

View File

@ -26,8 +26,7 @@
android:paddingLeft="16dp" android:paddingLeft="16dp"
android:paddingRight="16dp" android:paddingRight="16dp"
android:paddingTop="4dp" android:paddingTop="4dp"
android:paddingBottom="4dp" android:paddingBottom="4dp">
android:animateLayoutChanges="true">
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"