aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-03-20 11:32:15 +0100
committerVincent Breitmoser <valodim@mugenguild.com>2015-03-20 14:01:07 +0100
commitabce05d529bcc948654d7fcca425dfd544ef30be (patch)
treeaf2ea797cbb35894ed74a8949128bb91df0c5366 /OpenKeychain/src/main
parent3b04636f5daf3d171449296a5d9a67440abfbf75 (diff)
parent10510288f13a89b0f69994b9d2962c4d26b5f017 (diff)
downloadopen-keychain-abce05d529bcc948654d7fcca425dfd544ef30be.tar.gz
open-keychain-abce05d529bcc948654d7fcca425dfd544ef30be.tar.bz2
open-keychain-abce05d529bcc948654d7fcca425dfd544ef30be.zip
Merge remote-tracking branch 'origin/development' into development
Conflicts: OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
Diffstat (limited to 'OpenKeychain/src/main')
-rw-r--r--OpenKeychain/src/main/AndroidManifest.xml8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java15
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java25
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java25
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java36
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java20
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java91
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java62
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java61
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java55
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java56
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java157
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java110
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java252
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java21
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java35
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java15
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java218
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java163
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_nfc_grey_24dp.pngbin0 -> 1059 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_nfc_grey_24dp.pngbin0 -> 701 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_nfc_grey_24dp.pngbin0 -> 1359 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_nfc_grey_24dp.pngbin0 -> 2040 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_nfc_grey_24dp.pngbin0 -> 2756 bytes
-rw-r--r--OpenKeychain/src/main/res/layout/create_key_name_fragment.xml4
-rw-r--r--OpenKeychain/src/main/res/layout/create_key_start_fragment.xml104
-rw-r--r--OpenKeychain/src/main/res/layout/first_time_activity.xml137
-rw-r--r--OpenKeychain/src/main/res/layout/view_key_adv_share_fragment.xml25
-rw-r--r--OpenKeychain/src/main/res/menu/key_list.xml2
-rw-r--r--OpenKeychain/src/main/res/values-cs/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-de/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-es/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-eu/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-fi/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-fr/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-it/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-ja/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-nl/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-pl/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-ru/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-sl/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-sr/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-sv/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-tr/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-uk/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-zh-rTW/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-zh/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml8
77 files changed, 1149 insertions, 774 deletions
diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml
index c5317ae24..d983498cc 100644
--- a/OpenKeychain/src/main/AndroidManifest.xml
+++ b/OpenKeychain/src/main/AndroidManifest.xml
@@ -87,15 +87,9 @@
</intent-filter>
</activity>
<activity
- android:name=".ui.FirstTimeActivity"
- android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
- android:label="@string/app_name"
- android:windowSoftInputMode="stateAlwaysHidden" />
- <activity
android:name=".ui.CreateKeyActivity"
- android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:windowSoftInputMode="adjustResize"
- android:label="@string/title_create_key"
+ android:label="@string/title_manage_my_keys"
android:parentActivityName=".ui.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java
index 02cb502d0..03439228b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java
@@ -70,6 +70,8 @@ public class ImportKeysList extends ArrayList<ImportKeysListEntry> {
modified = true;
}
+ // keep track if this key result is from a HKP keyserver
+ boolean incomingFromHkpServer = true;
// we’re going to want to try to fetch the key from everywhere we found it, so remember
// all the origins
for (String origin : incoming.getOrigins()) {
@@ -78,13 +80,24 @@ public class ImportKeysList extends ArrayList<ImportKeysListEntry> {
// to work properly, Keybase-sourced entries need to pass along the extra
if (KeybaseKeyserver.ORIGIN.equals(origin)) {
existing.setExtraData(incoming.getExtraData());
+ // one of the origins is not a HKP keyserver
+ incomingFromHkpServer = false;
}
}
+
ArrayList<String> incomingIDs = incoming.getUserIds();
ArrayList<String> existingIDs = existing.getUserIds();
for (String incomingID : incomingIDs) {
if (!existingIDs.contains(incomingID)) {
- existingIDs.add(incomingID);
+ // prepend HKP server results to the start of the list,
+ // so that the UI (for cloud key search, which is picking the first list item)
+ // shows the right main email address, as mail addresses returned by HKP servers
+ // are preferred over keybase.io IDs
+ if (incomingFromHkpServer) {
+ existingIDs.add(0, incomingID);
+ } else {
+ existingIDs.add(incomingID);
+ }
modified = true;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java
index 40dcbd78d..a824e73d7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java
@@ -24,6 +24,7 @@ import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -101,7 +102,7 @@ public abstract class BaseOperation implements PassphraseCacheInterface {
}
@Override
- public String getCachedPassphrase(long subKeyId) throws NoSecretKeyException {
+ public Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException {
try {
long masterKeyId = mProviderHelper.getMasterKeyId(subKeyId);
return getCachedPassphrase(masterKeyId, subKeyId);
@@ -111,7 +112,7 @@ public abstract class BaseOperation implements PassphraseCacheInterface {
}
@Override
- public String getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException {
+ public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException {
try {
return PassphraseCacheService.getCachedPassphrase(
mContext, masterKeyId, subKeyId);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
index bcdbf5f67..ad2b297dd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
@@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -83,7 +84,7 @@ public class CertifyOperation extends BaseOperation {
}
// certification is always with the master key id, so use that one
- char[] passphrase = parcel.mCryptoInput.getPassphrase();
+ Passphrase passphrase = parcel.mCryptoInput.getPassphrase();
if (!certificationKey.unlock(passphrase)) {
log.add(LogType.MSG_CRT_ERROR_UNLOCK, 2);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java
index a03664091..28ef7582b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java
@@ -37,6 +37,7 @@ import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.util.concurrent.atomic.AtomicBoolean;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java
index 86b37fea6..7df37cd9b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java
@@ -22,6 +22,7 @@ import android.os.Parcel;
import org.openintents.openpgp.OpenPgpMetadata;
import org.openintents.openpgp.OpenPgpSignatureResult;
+import org.sufficientlysecure.keychain.util.Passphrase;
public class DecryptVerifyResult extends OperationResult {
@@ -37,7 +38,7 @@ public class DecryptVerifyResult extends OperationResult {
long mNfcSubKeyId;
byte[] mNfcSessionKey;
- String mNfcPassphrase;
+ Passphrase mNfcPassphrase;
OpenPgpSignatureResult mSignatureResult;
OpenPgpMetadata mDecryptMetadata;
@@ -53,7 +54,7 @@ public class DecryptVerifyResult extends OperationResult {
mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
}
- public void setNfcState(long subKeyId, byte[] sessionKey, String passphrase) {
+ public void setNfcState(long subKeyId, byte[] sessionKey, Passphrase passphrase) {
mNfcSubKeyId = subKeyId;
mNfcSessionKey = sessionKey;
mNfcPassphrase = passphrase;
@@ -67,7 +68,7 @@ public class DecryptVerifyResult extends OperationResult {
return mNfcSessionKey;
}
- public String getNfcPassphrase() {
+ public Passphrase getNfcPassphrase() {
return mNfcPassphrase;
}
@@ -109,7 +110,7 @@ public class DecryptVerifyResult extends OperationResult {
mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader());
mNfcSessionKey = source.readInt() != 0 ? source.createByteArray() : null;
- mNfcPassphrase = source.readString();
+ mNfcPassphrase = source.readParcelable(Passphrase.class.getClassLoader());
}
public int describeContents() {
@@ -127,7 +128,7 @@ public class DecryptVerifyResult extends OperationResult {
} else {
dest.writeInt(0);
}
- dest.writeString(mNfcPassphrase);
+ dest.writeParcelable(mNfcPassphrase, flags);
}
public static final Creator<DecryptVerifyResult> CREATOR = new Creator<DecryptVerifyResult>() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java
index a1204c0b5..bda9893dd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java
@@ -19,6 +19,8 @@ package org.sufficientlysecure.keychain.operations.results;
import android.os.Parcel;
+import org.sufficientlysecure.keychain.util.Passphrase;
+
import java.util.Date;
public class PgpSignEncryptResult extends OperationResult {
@@ -35,7 +37,7 @@ public class PgpSignEncryptResult extends OperationResult {
long mNfcKeyId;
byte[] mNfcHash;
int mNfcAlgo;
- String mNfcPassphrase;
+ Passphrase mNfcPassphrase;
byte[] mDetachedSignature;
public long getKeyIdPassphraseNeeded() {
@@ -46,7 +48,7 @@ public class PgpSignEncryptResult extends OperationResult {
mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
}
- public void setNfcData(long nfcKeyId, byte[] nfcHash, int nfcAlgo, String passphrase) {
+ public void setNfcData(long nfcKeyId, byte[] nfcHash, int nfcAlgo, Passphrase passphrase) {
mNfcKeyId = nfcKeyId;
mNfcHash = nfcHash;
mNfcAlgo = nfcAlgo;
@@ -69,7 +71,7 @@ public class PgpSignEncryptResult extends OperationResult {
return mNfcAlgo;
}
- public String getNfcPassphrase() {
+ public Passphrase getNfcPassphrase() {
return mNfcPassphrase;
}
@@ -123,4 +125,4 @@ public class PgpSignEncryptResult extends OperationResult {
}
};
-} \ No newline at end of file
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
index 36ab9dc1d..715d5af30 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
@@ -41,6 +41,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -149,14 +150,10 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
}
- public boolean unlock(String passphrase) throws PgpGeneralException {
- return unlock(passphrase.toCharArray());
- }
-
/**
* Returns true on right passphrase
*/
- public boolean unlock(char[] passphrase) throws PgpGeneralException {
+ public boolean unlock(Passphrase passphrase) throws PgpGeneralException {
// handle keys on OpenPGP cards like they were unlocked
if (mSecretKey.getS2K() != null
&& mSecretKey.getS2K().getType() == S2K.GNU_DUMMY_S2K
@@ -168,7 +165,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
// try to extract keys using the passphrase
try {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase);
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
mPrivateKey = mSecretKey.extractPrivateKey(keyDecryptor);
mPrivateKeyState = PRIVATE_KEY_STATE_UNLOCKED;
} catch (PGPException e) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java
index 0066bd23e..88ccccc6a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java
@@ -18,14 +18,16 @@
package org.sufficientlysecure.keychain.pgp;
+import org.sufficientlysecure.keychain.util.Passphrase;
+
public interface PassphraseCacheInterface {
public static class NoSecretKeyException extends Exception {
public NoSecretKeyException() {
}
}
- public String getCachedPassphrase(long subKeyId) throws NoSecretKeyException;
+ public Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException;
- public String getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException;
+ public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException;
}
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 14bc56538..364a1067d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
@@ -60,6 +60,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.io.BufferedInputStream;
@@ -83,7 +84,7 @@ public class PgpDecryptVerify extends BaseOperation {
private OutputStream mOutStream;
private boolean mAllowSymmetricDecryption;
- private String mPassphrase;
+ private Passphrase mPassphrase;
private Set<Long> mAllowedKeyIds;
private boolean mDecryptMetadataOnly;
private byte[] mDecryptedSessionKey;
@@ -118,7 +119,7 @@ public class PgpDecryptVerify extends BaseOperation {
private OutputStream mOutStream = null;
private Progressable mProgressable = null;
private boolean mAllowSymmetricDecryption = true;
- private String mPassphrase = null;
+ private Passphrase mPassphrase = null;
private Set<Long> mAllowedKeyIds = null;
private boolean mDecryptMetadataOnly = false;
private byte[] mDecryptedSessionKey = null;
@@ -159,7 +160,7 @@ public class PgpDecryptVerify extends BaseOperation {
return this;
}
- public Builder setPassphrase(String passphrase) {
+ public Builder setPassphrase(Passphrase passphrase) {
mPassphrase = passphrase;
return this;
}
@@ -572,7 +573,7 @@ public class PgpDecryptVerify extends BaseOperation {
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build();
PBEDataDecryptorFactory decryptorFactory = new JcePBEDataDecryptorFactoryBuilder(
digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
- mPassphrase.toCharArray());
+ mPassphrase.getCharArray());
clear = encryptedDataSymmetric.getDataStream(decryptorFactory);
encryptedData = encryptedDataSymmetric;
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 fb9edb1cd..092fd9d48 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
@@ -63,6 +63,7 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSign
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Primes;
import org.sufficientlysecure.keychain.util.ProgressScaler;
@@ -328,7 +329,7 @@ public class PgpKeyOperation {
masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator());
subProgressPush(50, 100);
- CryptoInputParcel cryptoInput = new CryptoInputParcel(new Date(), "");
+ mCryptoInput = new CryptoInputParcel(new Date(), new Passphrase(""));
return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, saveParcel, log);
} catch (PGPException e) {
@@ -444,7 +445,7 @@ public class PgpKeyOperation {
{
try {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(mCryptoInput.getPassphrase());
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(mCryptoInput.getPassphrase().getCharArray());
masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
} catch (PGPException e) {
log.add(LogType.MSG_MF_UNLOCK_ERROR, indent + 1);
@@ -815,7 +816,7 @@ public class PgpKeyOperation {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
- mCryptoInput.getPassphrase());
+ mCryptoInput.getPassphrase().getCharArray());
PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
PGPSignature sig = generateSubkeyBindingSignature(
getSignatureGenerator(masterSecretKey, mCryptoInput),
@@ -911,17 +912,14 @@ public class PgpKeyOperation {
}
PGPSecretKey sKey; {
- char[] passphrase = mCryptoInput.getPassphrase();
- if (passphrase == null) {
- passphrase = new char[] { };
- }
// Build key encrypter and decrypter based on passphrase
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder()
.build().get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase);
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ mCryptoInput.getPassphrase().getCharArray());
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
.build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
@@ -1055,7 +1053,7 @@ public class PgpKeyOperation {
PGPSecretKeyRing sKR,
PGPPublicKey masterPublicKey,
PGPPrivateKey masterPrivateKey,
- char[] passphrase,
+ Passphrase passphrase,
ChangeUnlockParcel newUnlock,
OperationLog log, int indent) throws PGPException {
@@ -1139,20 +1137,19 @@ public class PgpKeyOperation {
private static PGPSecretKeyRing applyNewPassphrase(
PGPSecretKeyRing sKR,
PGPPublicKey masterPublicKey,
- char[] passphrase,
- String newPassphrase,
+ Passphrase passphrase,
+ Passphrase newPassphrase,
OperationLog log, int indent) throws PGPException {
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder().build()
.get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase);
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
// Build key encryptor based on new passphrase
PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder(
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
- newPassphrase.toCharArray());
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
// noinspection unchecked
for (PGPSecretKey sKey : new IterableIterator<PGPSecretKey>(sKR.getSecretKeys())) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java
index 00ecc179e..022dc4d32 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java
@@ -21,6 +21,7 @@ package org.sufficientlysecure.keychain.pgp;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.nio.ByteBuffer;
import java.util.Date;
@@ -36,12 +37,12 @@ public class PgpSignEncryptInputParcel implements Parcelable {
protected boolean mEnableAsciiArmorOutput = false;
protected int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED;
protected long[] mEncryptionMasterKeyIds = null;
- protected String mSymmetricPassphrase = null;
+ protected Passphrase mSymmetricPassphrase = null;
protected int mSymmetricEncryptionAlgorithm = PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED;
protected long mSignatureMasterKeyId = Constants.key.none;
protected Long mSignatureSubKeyId = null;
protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED;
- protected String mSignaturePassphrase = null;
+ protected Passphrase mSignaturePassphrase = null;
protected long mAdditionalEncryptId = Constants.key.none;
protected boolean mFailOnMissingEncryptionKeyIds = false;
protected String mCharset;
@@ -56,17 +57,19 @@ public class PgpSignEncryptInputParcel implements Parcelable {
PgpSignEncryptInputParcel(Parcel source) {
+ ClassLoader loader = getClass().getClassLoader();
+
// we do all of those here, so the PgpSignEncryptInput class doesn't have to be parcelable
mVersionHeader = source.readString();
mEnableAsciiArmorOutput = source.readInt() == 1;
mCompressionId = source.readInt();
mEncryptionMasterKeyIds = source.createLongArray();
- mSymmetricPassphrase = source.readString();
+ mSymmetricPassphrase = source.readParcelable(loader);
mSymmetricEncryptionAlgorithm = source.readInt();
mSignatureMasterKeyId = source.readLong();
mSignatureSubKeyId = source.readInt() == 1 ? source.readLong() : null;
mSignatureHashAlgorithm = source.readInt();
- mSignaturePassphrase = source.readString();
+ mSignaturePassphrase = source.readParcelable(loader);
mAdditionalEncryptId = source.readLong();
mFailOnMissingEncryptionKeyIds = source.readInt() == 1;
mCharset = source.readString();
@@ -74,7 +77,7 @@ public class PgpSignEncryptInputParcel implements Parcelable {
mDetachedSignature = source.readInt() == 1;
mHiddenRecipients = source.readInt() == 1;
- mCryptoInput = source.readParcelable(PgpSignEncryptInputParcel.class.getClassLoader());
+ mCryptoInput = source.readParcelable(loader);
}
@Override
@@ -88,7 +91,7 @@ public class PgpSignEncryptInputParcel implements Parcelable {
dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
dest.writeInt(mCompressionId);
dest.writeLongArray(mEncryptionMasterKeyIds);
- dest.writeString(mSymmetricPassphrase);
+ dest.writeParcelable(mSymmetricPassphrase, 0);
dest.writeInt(mSymmetricEncryptionAlgorithm);
dest.writeLong(mSignatureMasterKeyId);
if (mSignatureSubKeyId != null) {
@@ -98,7 +101,7 @@ public class PgpSignEncryptInputParcel implements Parcelable {
dest.writeInt(0);
}
dest.writeInt(mSignatureHashAlgorithm);
- dest.writeString(mSignaturePassphrase);
+ dest.writeParcelable(mSignaturePassphrase, 0);
dest.writeLong(mAdditionalEncryptId);
dest.writeInt(mFailOnMissingEncryptionKeyIds ? 1 : 0);
dest.writeString(mCharset);
@@ -130,11 +133,11 @@ public class PgpSignEncryptInputParcel implements Parcelable {
return this;
}
- public String getSignaturePassphrase() {
+ public Passphrase getSignaturePassphrase() {
return mSignaturePassphrase;
}
- public PgpSignEncryptInputParcel setSignaturePassphrase(String signaturePassphrase) {
+ public PgpSignEncryptInputParcel setSignaturePassphrase(Passphrase signaturePassphrase) {
mSignaturePassphrase = signaturePassphrase;
return this;
}
@@ -175,11 +178,11 @@ public class PgpSignEncryptInputParcel implements Parcelable {
return this;
}
- public String getSymmetricPassphrase() {
+ public Passphrase getSymmetricPassphrase() {
return mSymmetricPassphrase;
}
- public PgpSignEncryptInputParcel setSymmetricPassphrase(String symmetricPassphrase) {
+ public PgpSignEncryptInputParcel setSymmetricPassphrase(Passphrase symmetricPassphrase) {
mSymmetricPassphrase = symmetricPassphrase;
return this;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
index 7253d9b18..7e70b4571 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
@@ -243,7 +243,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
log.add(LogType.MSG_PSE_SYMMETRIC, indent);
JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator =
- new JcePBEKeyEncryptionMethodGenerator(input.getSymmetricPassphrase().toCharArray());
+ new JcePBEKeyEncryptionMethodGenerator(input.getSymmetricPassphrase().getCharArray());
cPk.addMethod(symmetricEncryptionGenerator);
} else {
log.add(LogType.MSG_PSE_ASYMMETRIC, indent);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java
index 1b14e78fb..b178e9515 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java
@@ -21,6 +21,8 @@ package org.sufficientlysecure.keychain.pgp;
import android.net.Uri;
import android.os.Parcel;
+import org.sufficientlysecure.keychain.util.Passphrase;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
index f15bf7925..7d8aa993d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
@@ -55,6 +55,7 @@ import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
import org.sufficientlysecure.keychain.ui.ViewKeyActivity;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.io.IOException;
import java.io.InputStream;
@@ -180,7 +181,7 @@ public class OpenPgpService extends RemoteService {
return result;
}
- private PendingIntent getNfcSignPendingIntent(Intent data, long keyId, String pin, byte[] hashToSign, int hashAlgo) {
+ private PendingIntent getNfcSignPendingIntent(Intent data, long keyId, Passphrase pin, byte[] hashToSign, int hashAlgo) {
// build PendingIntent for Yubikey NFC operations
Intent intent = new Intent(getBaseContext(), NfcActivity.class);
intent.setAction(NfcActivity.ACTION_SIGN_HASH);
@@ -196,7 +197,7 @@ public class OpenPgpService extends RemoteService {
PendingIntent.FLAG_CANCEL_CURRENT);
}
- private PendingIntent getNfcDecryptPendingIntent(Intent data, long subKeyId, String pin, byte[] encryptedSessionKey) {
+ private PendingIntent getNfcDecryptPendingIntent(Intent data, long subKeyId, Passphrase pin, byte[] encryptedSessionKey) {
// build PendingIntent for Yubikey NFC operations
Intent intent = new Intent(getBaseContext(), NfcActivity.class);
intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY);
@@ -519,7 +520,7 @@ public class OpenPgpService extends RemoteService {
KeychainContract.ApiAllowedKeys.buildBaseUri(currentPkg));
}
- String passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE);
+ Passphrase passphrase = data.getParcelableExtra(OpenPgpApi.EXTRA_PASSPHRASE);
long inputLength = is.available();
InputData inputData = new InputData(is, inputLength);
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 6535cb404..cd3e06705 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -66,6 +66,7 @@ import org.sufficientlysecure.keychain.util.FileHelper;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ParcelableFileCache;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -283,7 +284,7 @@ public class KeychainIntentService extends IntentService implements Progressable
try {
/* Input */
- String passphrase = data.getString(DECRYPT_PASSPHRASE);
+ Passphrase passphrase = data.getParcelable(DECRYPT_PASSPHRASE);
byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
InputData inputData = createDecryptInputData(data);
@@ -413,7 +414,7 @@ public class KeychainIntentService extends IntentService implements Progressable
try {
/* Input */
- String passphrase = data.getString(DECRYPT_PASSPHRASE);
+ Passphrase passphrase = data.getParcelable(DECRYPT_PASSPHRASE);
byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
InputData inputData = createDecryptInputData(data);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
index 57881f8ee..ee481ad31 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
@@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
import java.util.Date;
@@ -121,7 +122,7 @@ public class PassphraseCacheService extends Service {
* new events to the alarm manager for new passphrases to let them timeout in the future.
*/
public static void addCachedPassphrase(Context context, long masterKeyId, long subKeyId,
- String passphrase,
+ Passphrase passphrase,
String primaryUserId) {
Log.d(Constants.TAG, "PassphraseCacheService.cacheNewPassphrase() for " + masterKeyId);
@@ -143,7 +144,7 @@ public class PassphraseCacheService extends Service {
* @return passphrase or null (if no passphrase is cached for this keyId)
*/
- public static String getCachedPassphrase(Context context, long masterKeyId, long subKeyId) throws KeyNotFoundException {
+ public static Passphrase getCachedPassphrase(Context context, long masterKeyId, long subKeyId) throws KeyNotFoundException {
Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphrase() for masterKeyId "
+ masterKeyId + ", subKeyId " + subKeyId);
@@ -190,7 +191,9 @@ public class PassphraseCacheService extends Service {
switch (returnMessage.what) {
case MSG_PASSPHRASE_CACHE_GET_OKAY:
- return returnMessage.getData().getString(EXTRA_PASSPHRASE);
+ Bundle returnData = returnMessage.getData();
+ returnData.setClassLoader(context.getClassLoader());
+ return returnData.getParcelable(EXTRA_PASSPHRASE);
case MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND:
throw new KeyNotFoundException();
default:
@@ -202,11 +205,11 @@ public class PassphraseCacheService extends Service {
/**
* Internal implementation to get cached passphrase.
*/
- private String getCachedPassphraseImpl(long masterKeyId, long subKeyId) throws ProviderHelper.NotFoundException {
+ private Passphrase getCachedPassphraseImpl(long masterKeyId, long subKeyId) throws ProviderHelper.NotFoundException {
// passphrase for symmetric encryption?
if (masterKeyId == Constants.key.symmetric) {
Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for symmetric encryption");
- String cachedPassphrase = mPassphraseCache.get(Constants.key.symmetric).getPassphrase();
+ Passphrase cachedPassphrase = mPassphraseCache.get(Constants.key.symmetric).getPassphrase();
if (cachedPassphrase == null) {
return null;
}
@@ -232,13 +235,13 @@ public class PassphraseCacheService extends Service {
case DIVERT_TO_CARD:
if (Preferences.getPreferences(this).useDefaultYubikeyPin()) {
Log.d(Constants.TAG, "PassphraseCacheService: Using default Yubikey PIN: 123456");
- return "123456"; // default Yubikey PIN, see http://www.yubico.com/2012/12/yubikey-neo-openpgp/
+ return new Passphrase("123456"); // default Yubikey PIN, see http://www.yubico.com/2012/12/yubikey-neo-openpgp/
} else {
Log.d(Constants.TAG, "PassphraseCacheService: NOT using default Yubikey PIN");
break;
}
case PASSPHRASE_EMPTY:
- return "";
+ return new Passphrase("");
case UNAVAILABLE:
throw new ProviderHelper.NotFoundException("secret key for this subkey is not available");
case GNU_DUMMY:
@@ -331,7 +334,7 @@ public class PassphraseCacheService extends Service {
long masterKeyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
long subKeyId = intent.getLongExtra(EXTRA_SUBKEY_ID, -1);
- String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE);
+ Passphrase passphrase = intent.getParcelableExtra(EXTRA_PASSPHRASE);
String primaryUserID = intent.getStringExtra(EXTRA_USER_ID);
Log.d(Constants.TAG,
@@ -373,10 +376,10 @@ public class PassphraseCacheService extends Service {
Log.e(Constants.TAG, "PassphraseCacheService: Bad request, missing masterKeyId or subKeyId!");
msg.what = MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND;
} else {
- String passphrase = getCachedPassphraseImpl(masterKeyId, subKeyId);
+ Passphrase passphrase = getCachedPassphraseImpl(masterKeyId, subKeyId);
msg.what = MSG_PASSPHRASE_CACHE_GET_OKAY;
Bundle bundle = new Bundle();
- bundle.putString(EXTRA_PASSPHRASE, passphrase);
+ bundle.putParcelable(EXTRA_PASSPHRASE, passphrase);
msg.setData(bundle);
}
} catch (ProviderHelper.NotFoundException e) {
@@ -412,7 +415,10 @@ public class PassphraseCacheService extends Service {
* Called when one specific passphrase for keyId timed out
*/
private void timeout(Context context, long keyId) {
- // remove passphrase corresponding to keyId from memory
+ CachedPassphrase cPass = mPassphraseCache.get(keyId);
+ // clean internal char[] from memory!
+ cPass.getPassphrase().removeFromMemory();
+ // remove passphrase object
mPassphraseCache.remove(keyId);
Log.d(Constants.TAG, "PassphraseCacheService Timeout of keyId " + keyId + ", removed from memory!");
@@ -517,9 +523,9 @@ public class PassphraseCacheService extends Service {
public class CachedPassphrase {
private String primaryUserID;
- private String passphrase;
+ private Passphrase passphrase;
- public CachedPassphrase(String passphrase, String primaryUserID) {
+ public CachedPassphrase(Passphrase passphrase, String primaryUserID) {
setPassphrase(passphrase);
setPrimaryUserID(primaryUserID);
}
@@ -528,7 +534,7 @@ public class PassphraseCacheService extends Service {
return primaryUserID;
}
- public String getPassphrase() {
+ public Passphrase getPassphrase() {
return passphrase;
}
@@ -536,7 +542,7 @@ public class PassphraseCacheService extends Service {
this.primaryUserID = primaryUserID;
}
- public void setPassphrase(String passphrase) {
+ public void setPassphrase(Passphrase passphrase) {
this.passphrase = passphrase;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
index e2d0c03c9..9fd278c13 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
@@ -22,6 +22,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.io.Serializable;
import java.util.ArrayList;
@@ -296,33 +297,30 @@ public class SaveKeyringParcel implements Parcelable {
public static class ChangeUnlockParcel implements Parcelable {
// The new passphrase to use
- public final String mNewPassphrase;
+ public final Passphrase mNewPassphrase;
// A new pin to use. Must only contain [0-9]+
- public final String mNewPin;
+ public final Passphrase mNewPin;
- public ChangeUnlockParcel(String newPassphrase) {
+ public ChangeUnlockParcel(Passphrase newPassphrase) {
this(newPassphrase, null);
}
- public ChangeUnlockParcel(String newPassphrase, String newPin) {
+ public ChangeUnlockParcel(Passphrase newPassphrase, Passphrase newPin) {
if (newPassphrase == null && newPin == null) {
throw new RuntimeException("Cannot set both passphrase and pin. THIS IS A BUG!");
}
- if (newPin != null && !newPin.matches("[0-9]+")) {
- throw new RuntimeException("Pin must be numeric digits only. THIS IS A BUG!");
- }
mNewPassphrase = newPassphrase;
mNewPin = newPin;
}
public ChangeUnlockParcel(Parcel source) {
- mNewPassphrase = source.readString();
- mNewPin = source.readString();
+ mNewPassphrase = source.readParcelable(Passphrase.class.getClassLoader());
+ mNewPin = source.readParcelable(Passphrase.class.getClassLoader());
}
@Override
public void writeToParcel(Parcel destination, int flags) {
- destination.writeString(mNewPassphrase);
- destination.writeString(mNewPin);
+ destination.writeParcelable(mNewPassphrase, flags);
+ destination.writeParcelable(mNewPin, flags);
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java
index 836568533..d77bbe7e2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java
@@ -9,6 +9,8 @@ import java.util.Map;
import android.os.Parcel;
import android.os.Parcelable;
+import org.sufficientlysecure.keychain.util.Passphrase;
+
/** This is a base class for the input of crypto operations.
*
@@ -16,13 +18,13 @@ import android.os.Parcelable;
public class CryptoInputParcel implements Parcelable {
final Date mSignatureTime;
- final String mPassphrase;
+ final Passphrase mPassphrase;
// this map contains both decrypted session keys and signed hashes to be
// used in the crypto operation described by this parcel.
private HashMap<ByteBuffer,byte[]> mCryptoData = new HashMap<>();
- public CryptoInputParcel(Date signatureTime, String passphrase) {
+ public CryptoInputParcel(Date signatureTime, Passphrase passphrase) {
mSignatureTime = signatureTime == null ? new Date() : signatureTime;
mPassphrase = passphrase;
}
@@ -34,7 +36,7 @@ public class CryptoInputParcel implements Parcelable {
protected CryptoInputParcel(Parcel source) {
mSignatureTime = new Date(source.readLong());
- mPassphrase = source.readString();
+ mPassphrase = source.readParcelable(getClass().getClassLoader());
{
int count = source.readInt();
@@ -56,7 +58,7 @@ public class CryptoInputParcel implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(mSignatureTime.getTime());
- dest.writeString(mPassphrase);
+ dest.writeParcelable(mPassphrase, 0);
dest.writeInt(mCryptoData.size());
for (HashMap.Entry<ByteBuffer,byte[]> entry : mCryptoData.entrySet()) {
@@ -81,8 +83,8 @@ public class CryptoInputParcel implements Parcelable {
return mPassphrase != null;
}
- public char[] getPassphrase() {
- return mPassphrase == null ? null : mPassphrase.toCharArray();
+ public Passphrase getPassphrase() {
+ return mPassphrase;
}
public static final Creator<CryptoInputParcel> CREATOR = new Creator<CryptoInputParcel>() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
index 711e2f2e7..a5f818734 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
@@ -62,6 +62,7 @@ import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
import org.sufficientlysecure.keychain.ui.widget.KeySpinner;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
import java.lang.reflect.Method;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
index 2da5511b8..ab76f693e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
@@ -20,31 +20,74 @@ package org.sufficientlysecure.keychain.ui;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
+import android.view.View;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.util.Passphrase;
+
+import java.util.ArrayList;
public class CreateKeyActivity extends BaseActivity {
public static final String EXTRA_NAME = "name";
public static final String EXTRA_EMAIL = "email";
+ public static final String EXTRA_FIRST_TIME = "first_time";
+ public static final String EXTRA_ADDITIONAL_EMAILS = "additional_emails";
+ public static final String EXTRA_PASSPHRASE = "passphrase";
- public static enum FragAction {
- START,
- TO_RIGHT,
- TO_LEFT
- }
+ public static final String FRAGMENT_TAG = "currentFragment";
+
+ String mName;
+ String mEmail;
+ ArrayList<String> mAdditionalEmails;
+ Passphrase mPassphrase;
+ boolean mFirstTime;
+
+ Fragment mCurrentFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // pass extras into fragment
- CreateKeyNameFragment frag =
- CreateKeyNameFragment.newInstance(
- getIntent().getStringExtra(EXTRA_NAME),
- getIntent().getStringExtra(EXTRA_EMAIL)
- );
- loadFragment(null, frag, FragAction.START);
+ // Check whether we're recreating a previously destroyed instance
+ if (savedInstanceState != null) {
+ // Restore value of members from saved state
+ mName = savedInstanceState.getString(EXTRA_NAME);
+ mEmail = savedInstanceState.getString(EXTRA_EMAIL);
+ mAdditionalEmails = savedInstanceState.getStringArrayList(EXTRA_ADDITIONAL_EMAILS);
+ mPassphrase = savedInstanceState.getParcelable(EXTRA_PASSPHRASE);
+ mFirstTime = savedInstanceState.getBoolean(EXTRA_FIRST_TIME);
+
+ mCurrentFragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
+ } else {
+ // Initialize members with default values for a new instance
+ mName = getIntent().getStringExtra(EXTRA_NAME);
+ mEmail = getIntent().getStringExtra(EXTRA_EMAIL);
+ mFirstTime = getIntent().getBooleanExtra(EXTRA_FIRST_TIME, false);
+
+ // Start with first fragment of wizard
+ CreateKeyStartFragment frag = CreateKeyStartFragment.newInstance();
+ loadFragment(frag, FragAction.START);
+ }
+
+ if (mFirstTime) {
+ setTitle(R.string.app_name);
+ setActionBarIcon(R.drawable.ic_launcher);
+ mToolbar.setNavigationOnClickListener(null);
+ } else {
+ setTitle(R.string.title_manage_my_keys);
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ outState.putString(EXTRA_NAME, mName);
+ outState.putString(EXTRA_EMAIL, mEmail);
+ outState.putStringArrayList(EXTRA_ADDITIONAL_EMAILS, mAdditionalEmails);
+ outState.putParcelable(EXTRA_PASSPHRASE, mPassphrase);
+ outState.putBoolean(EXTRA_FIRST_TIME, mFirstTime);
}
@Override
@@ -52,23 +95,23 @@ public class CreateKeyActivity extends BaseActivity {
setContentView(R.layout.create_key_activity);
}
- public void loadFragment(Bundle savedInstanceState, Fragment fragment, FragAction action) {
- // 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;
- }
+ public static enum FragAction {
+ START,
+ TO_RIGHT,
+ TO_LEFT
+ }
+
+ public void loadFragment(Fragment fragment, FragAction action) {
+ mCurrentFragment = fragment;
// Add the fragment to the 'fragment_container' FrameLayout
- // NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
switch (action) {
case START:
transaction.setCustomAnimations(0, 0);
- transaction.replace(R.id.create_key_fragment_container, fragment)
- .commitAllowingStateLoss();
+ transaction.replace(R.id.create_key_fragment_container, fragment, FRAGMENT_TAG)
+ .commit();
break;
case TO_LEFT:
getSupportFragmentManager().popBackStackImmediate();
@@ -77,8 +120,8 @@ public class CreateKeyActivity extends BaseActivity {
transaction.setCustomAnimations(R.anim.frag_slide_in_from_right, R.anim.frag_slide_out_to_left,
R.anim.frag_slide_in_from_left, R.anim.frag_slide_out_to_right);
transaction.addToBackStack(null);
- transaction.replace(R.id.create_key_fragment_container, fragment)
- .commitAllowingStateLoss();
+ transaction.replace(R.id.create_key_fragment_container, fragment, FRAGMENT_TAG)
+ .commit();
break;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java
index 66424e012..2e8a1f370 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java
@@ -46,16 +46,12 @@ import java.util.List;
public class CreateKeyEmailFragment extends Fragment {
- public static final String ARG_NAME = "name";
- public static final String ARG_EMAIL = "email";
-
CreateKeyActivity mCreateKeyActivity;
EmailEditText mEmailEdit;
RecyclerView mEmailsRecyclerView;
View mBackButton;
View mNextButton;
- String mName;
ArrayList<EmailAdapter.ViewModel> mAdditionalEmailModels;
EmailAdapter mEmailAdapter;
@@ -63,13 +59,10 @@ public class CreateKeyEmailFragment extends Fragment {
/**
* Creates new instance of this fragment
*/
- public static CreateKeyEmailFragment newInstance(String name, String email) {
+ public static CreateKeyEmailFragment newInstance() {
CreateKeyEmailFragment frag = new CreateKeyEmailFragment();
Bundle args = new Bundle();
- args.putString(ARG_NAME, name);
- args.putString(ARG_EMAIL, email);
-
frag.setArguments(args);
return frag;
@@ -85,7 +78,7 @@ public class CreateKeyEmailFragment extends Fragment {
*/
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
boolean output = true;
- if (editText.getText().toString().length() == 0) {
+ if (editText.getText().length() == 0) {
editText.setError(context.getString(R.string.create_key_empty));
editText.requestFocus();
output = false;
@@ -106,31 +99,33 @@ public class CreateKeyEmailFragment extends Fragment {
mEmailsRecyclerView = (RecyclerView) view.findViewById(R.id.create_key_emails);
// initial values
- mName = getArguments().getString(ARG_NAME);
- String email = getArguments().getString(ARG_EMAIL);
- mEmailEdit.setText(email);
+ mEmailEdit.setText(mCreateKeyActivity.mEmail);
// focus empty edit fields
- if (email == null) {
+ if (mCreateKeyActivity.mEmail == null) {
mEmailEdit.requestFocus();
}
mBackButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- mCreateKeyActivity.loadFragment(null, null, FragAction.TO_LEFT);
+ mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
}
});
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- createKeyCheck();
+ nextClicked();
}
});
mEmailsRecyclerView.setHasFixedSize(true);
mEmailsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mEmailsRecyclerView.setItemAnimator(new DefaultItemAnimator());
+ // initial values
mAdditionalEmailModels = new ArrayList<>();
+ if (mCreateKeyActivity.mAdditionalEmails != null) {
+ setAdditionalEmails(mCreateKeyActivity.mAdditionalEmails);
+ }
mEmailAdapter = new EmailAdapter(mAdditionalEmailModels, new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -171,25 +166,38 @@ public class CreateKeyEmailFragment extends Fragment {
mCreateKeyActivity = (CreateKeyActivity) getActivity();
}
- private void createKeyCheck() {
+ private void nextClicked() {
if (isEditTextNotEmpty(getActivity(), mEmailEdit)) {
+ // save state
+ mCreateKeyActivity.mEmail = mEmailEdit.getText().toString();
+ mCreateKeyActivity.mAdditionalEmails = getAdditionalEmails();
- ArrayList<String> emails = new ArrayList<>();
- for (EmailAdapter.ViewModel holder : mAdditionalEmailModels) {
- emails.add(holder.toString());
- }
+ CreateKeyPassphraseFragment frag = CreateKeyPassphraseFragment.newInstance();
+ mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
+ }
+ }
- CreateKeyPassphraseFragment frag =
- CreateKeyPassphraseFragment.newInstance(
- mName,
- mEmailEdit.getText().toString(),
- emails
- );
+ private ArrayList<String> getAdditionalEmails() {
+ ArrayList<String> emails = new ArrayList<>();
+ for (EmailAdapter.ViewModel holder : mAdditionalEmailModels) {
+ emails.add(holder.toString());
+ }
+ return emails;
+ }
- mCreateKeyActivity.loadFragment(null, frag, FragAction.TO_RIGHT);
+ private void setAdditionalEmails(ArrayList<String> emails) {
+ for (String email : emails) {
+ mAdditionalEmailModels.add(new EmailAdapter.ViewModel(email));
}
}
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ // save state in activity
+ mCreateKeyActivity.mAdditionalEmails = getAdditionalEmails();
+ }
+
public static class EmailAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<ViewModel> mDataset;
private View.OnClickListener mFooterOnClickListener;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
index 4871b5ae2..75f49a426 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
@@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
import java.util.ArrayList;
@@ -64,32 +65,15 @@ public class CreateKeyFinalFragment extends Fragment {
TextView mEditText;
View mEditButton;
- public static final String ARG_NAME = "name";
- public static final String ARG_EMAIL = "email";
- public static final String ARG_ADDITIONAL_EMAILS = "emails";
- public static final String ARG_PASSPHRASE = "passphrase";
-
- String mName;
- String mEmail;
- ArrayList<String> mAdditionalEmails;
- String mPassphrase;
-
SaveKeyringParcel mSaveKeyringParcel;
/**
* Creates new instance of this fragment
*/
- public static CreateKeyFinalFragment newInstance(String name, String email,
- ArrayList<String> additionalEmails,
- String passphrase) {
+ public static CreateKeyFinalFragment newInstance() {
CreateKeyFinalFragment frag = new CreateKeyFinalFragment();
Bundle args = new Bundle();
- args.putString(ARG_NAME, name);
- args.putString(ARG_EMAIL, email);
- args.putStringArrayList(ARG_ADDITIONAL_EMAILS, additionalEmails);
- args.putString(ARG_PASSPHRASE, passphrase);
-
frag.setArguments(args);
return frag;
@@ -107,17 +91,11 @@ public class CreateKeyFinalFragment extends Fragment {
mEditText = (TextView) view.findViewById(R.id.create_key_edit_text);
mEditButton = view.findViewById(R.id.create_key_edit_button);
- // get args
- mName = getArguments().getString(ARG_NAME);
- mEmail = getArguments().getString(ARG_EMAIL);
- mAdditionalEmails = getArguments().getStringArrayList(ARG_ADDITIONAL_EMAILS);
- mPassphrase = getArguments().getString(ARG_PASSPHRASE);
-
// set values
- mNameEdit.setText(mName);
- if (mAdditionalEmails != null && mAdditionalEmails.size() > 0) {
- String emailText = mEmail + ", ";
- Iterator<?> it = mAdditionalEmails.iterator();
+ mNameEdit.setText(mCreateKeyActivity.mName);
+ if (mCreateKeyActivity.mAdditionalEmails != null && mCreateKeyActivity.mAdditionalEmails.size() > 0) {
+ String emailText = mCreateKeyActivity.mEmail + ", ";
+ Iterator<?> it = mCreateKeyActivity.mAdditionalEmails.iterator();
while (it.hasNext()) {
Object next = it.next();
emailText += next;
@@ -127,7 +105,7 @@ public class CreateKeyFinalFragment extends Fragment {
}
mEmailEdit.setText(emailText);
} else {
- mEmailEdit.setText(mEmail);
+ mEmailEdit.setText(mCreateKeyActivity.mEmail);
}
mCreateButton.setOnClickListener(new View.OnClickListener() {
@@ -140,7 +118,7 @@ public class CreateKeyFinalFragment extends Fragment {
mBackButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- mCreateKeyActivity.loadFragment(null, null, FragAction.TO_LEFT);
+ mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
}
});
@@ -157,6 +135,12 @@ public class CreateKeyFinalFragment extends Fragment {
}
@Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mCreateKeyActivity = (CreateKeyActivity) getActivity();
+ }
+
+ @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_EDIT_KEY: {
@@ -186,17 +170,22 @@ public class CreateKeyFinalFragment extends Fragment {
Algorithm.RSA, 4096, null, KeyFlags.SIGN_DATA, 0L));
mSaveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
Algorithm.RSA, 4096, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L));
- String userId = KeyRing.createUserId(new KeyRing.UserId(mName, mEmail, null));
+ String userId = KeyRing.createUserId(
+ new KeyRing.UserId(mCreateKeyActivity.mName, mCreateKeyActivity.mEmail, null)
+ );
mSaveKeyringParcel.mAddUserIds.add(userId);
mSaveKeyringParcel.mChangePrimaryUserId = userId;
- if (mAdditionalEmails != null && mAdditionalEmails.size() > 0) {
- for (String email : mAdditionalEmails) {
- String thisUserId = KeyRing.createUserId(new KeyRing.UserId(mName, email, null));
+ if (mCreateKeyActivity.mAdditionalEmails != null
+ && mCreateKeyActivity.mAdditionalEmails.size() > 0) {
+ for (String email : mCreateKeyActivity.mAdditionalEmails) {
+ String thisUserId = KeyRing.createUserId(
+ new KeyRing.UserId(mCreateKeyActivity.mName, email, null)
+ );
mSaveKeyringParcel.mAddUserIds.add(thisUserId);
}
}
- mSaveKeyringParcel.mNewUnlock = mPassphrase != null
- ? new ChangeUnlockParcel(mPassphrase, null)
+ mSaveKeyringParcel.mNewUnlock = mCreateKeyActivity.mPassphrase != null
+ ? new ChangeUnlockParcel(mCreateKeyActivity.mPassphrase, null)
: null;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java
index 50a3bd655..7480367bb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java
@@ -24,34 +24,26 @@ import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
-import org.sufficientlysecure.keychain.ui.widget.EmailEditText;
import org.sufficientlysecure.keychain.ui.widget.NameEditText;
public class CreateKeyNameFragment extends Fragment {
- public static final String ARG_NAME = "name";
- public static final String ARG_EMAIL = "email";
-
CreateKeyActivity mCreateKeyActivity;
NameEditText mNameEdit;
+ View mBackButton;
View mNextButton;
- String mEmail;
-
/**
* Creates new instance of this fragment
*/
- public static CreateKeyNameFragment newInstance(String name, String email) {
+ public static CreateKeyNameFragment newInstance() {
CreateKeyNameFragment frag = new CreateKeyNameFragment();
Bundle args = new Bundle();
- args.putString(ARG_NAME, name);
- args.putString(ARG_EMAIL, email);
frag.setArguments(args);
@@ -68,7 +60,7 @@ public class CreateKeyNameFragment extends Fragment {
*/
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
boolean output = true;
- if (editText.getText().toString().length() == 0) {
+ if (editText.getText().length() == 0) {
editText.setError(context.getString(R.string.create_key_empty));
editText.requestFocus();
output = false;
@@ -79,39 +71,31 @@ public class CreateKeyNameFragment extends Fragment {
return output;
}
- private static boolean areEditTextsEqual(Context context, EditText editText1, EditText editText2) {
- boolean output = true;
- if (!editText1.getText().toString().equals(editText2.getText().toString())) {
- editText2.setError(context.getString(R.string.create_key_passphrases_not_equal));
- editText2.requestFocus();
- output = false;
- } else {
- editText2.setError(null);
- }
-
- return output;
- }
-
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.create_key_name_fragment, container, false);
mNameEdit = (NameEditText) view.findViewById(R.id.create_key_name);
+ mBackButton = view.findViewById(R.id.create_key_back_button);
mNextButton = view.findViewById(R.id.create_key_next_button);
// initial values
- String name = getArguments().getString(ARG_NAME);
- mEmail = getArguments().getString(ARG_EMAIL);
- mNameEdit.setText(name);
+ mNameEdit.setText(mCreateKeyActivity.mName);
// focus empty edit fields
- if (name == null) {
+ if (mCreateKeyActivity.mName == null) {
mNameEdit.requestFocus();
}
+ mBackButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
+ }
+ });
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- createKeyCheck();
+ nextClicked();
}
});
@@ -124,16 +108,13 @@ public class CreateKeyNameFragment extends Fragment {
mCreateKeyActivity = (CreateKeyActivity) getActivity();
}
- private void createKeyCheck() {
+ private void nextClicked() {
if (isEditTextNotEmpty(getActivity(), mNameEdit)) {
+ // save state
+ mCreateKeyActivity.mName = mNameEdit.getText().toString();
- CreateKeyEmailFragment frag =
- CreateKeyEmailFragment.newInstance(
- mNameEdit.getText().toString(),
- mEmail
- );
-
- mCreateKeyActivity.loadFragment(null, frag, FragAction.TO_RIGHT);
+ CreateKeyEmailFragment frag = CreateKeyEmailFragment.newInstance();
+ mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java
index 055ea608b..32173edf7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java
@@ -21,6 +21,7 @@ import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
+import android.text.Editable;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.view.LayoutInflater;
@@ -34,20 +35,13 @@ import android.widget.EditText;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
import org.sufficientlysecure.keychain.ui.widget.PassphraseEditText;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.util.ArrayList;
+import java.util.Arrays;
public class CreateKeyPassphraseFragment extends Fragment {
- public static final String ARG_NAME = "name";
- public static final String ARG_EMAIL = "email";
- public static final String ARG_ADDITIONAL_EMAILS = "emails";
-
- // model
- String mName;
- String mEmail;
- ArrayList<String> mAdditionalEmails;
-
// view
CreateKeyActivity mCreateKeyActivity;
PassphraseEditText mPassphraseEdit;
@@ -59,15 +53,10 @@ public class CreateKeyPassphraseFragment extends Fragment {
/**
* Creates new instance of this fragment
*/
- public static CreateKeyPassphraseFragment newInstance(String name, String email,
- ArrayList<String> additionalEmails) {
+ public static CreateKeyPassphraseFragment newInstance() {
CreateKeyPassphraseFragment frag = new CreateKeyPassphraseFragment();
Bundle args = new Bundle();
- args.putString(ARG_NAME, name);
- args.putString(ARG_EMAIL, email);
- args.putStringArrayList(ARG_ADDITIONAL_EMAILS, additionalEmails);
-
frag.setArguments(args);
return frag;
@@ -83,7 +72,7 @@ public class CreateKeyPassphraseFragment extends Fragment {
*/
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
boolean output = true;
- if (editText.getText().toString().length() == 0) {
+ if (editText.getText().length() == 0) {
editText.setError(context.getString(R.string.create_key_empty));
editText.requestFocus();
output = false;
@@ -95,11 +84,13 @@ public class CreateKeyPassphraseFragment extends Fragment {
}
private static boolean areEditTextsEqual(Context context, EditText editText1, EditText editText2) {
- boolean output = true;
- if (!editText1.getText().toString().equals(editText2.getText().toString())) {
+ Passphrase p1 = new Passphrase(editText1);
+ Passphrase p2 = new Passphrase(editText2);
+ boolean output = (p1.equals(p2));
+
+ if (!output) {
editText2.setError(context.getString(R.string.create_key_passphrases_not_equal));
editText2.requestFocus();
- output = false;
} else {
editText2.setError(null);
}
@@ -118,9 +109,12 @@ public class CreateKeyPassphraseFragment extends Fragment {
mNextButton = view.findViewById(R.id.create_key_next_button);
// initial values
- mName = getArguments().getString(ARG_NAME);
- mEmail = getArguments().getString(ARG_EMAIL);
- mAdditionalEmails = getArguments().getStringArrayList(ARG_ADDITIONAL_EMAILS);
+ // TODO: using String here is unsafe...
+ if (mCreateKeyActivity.mPassphrase != null) {
+ mPassphraseEdit.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray()));
+ mPassphraseEditAgain.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray()));
+ }
+
mPassphraseEdit.requestFocus();
mBackButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -131,7 +125,7 @@ public class CreateKeyPassphraseFragment extends Fragment {
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- createKeyCheck();
+ nextClicked();
}
});
mShowPassphrase.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@@ -159,23 +153,19 @@ public class CreateKeyPassphraseFragment extends Fragment {
private void back() {
hideKeyboard();
- mCreateKeyActivity.loadFragment(null, null, FragAction.TO_LEFT);
+ mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
}
- private void createKeyCheck() {
+ private void nextClicked() {
if (isEditTextNotEmpty(getActivity(), mPassphraseEdit)
&& areEditTextsEqual(getActivity(), mPassphraseEdit, mPassphraseEditAgain)) {
- CreateKeyFinalFragment frag =
- CreateKeyFinalFragment.newInstance(
- mName,
- mEmail,
- mAdditionalEmails,
- mPassphraseEdit.getText().toString()
- );
+ // save state
+ mCreateKeyActivity.mPassphrase = new Passphrase(mPassphraseEdit);
+ CreateKeyFinalFragment frag = CreateKeyFinalFragment.newInstance();
hideKeyboard();
- mCreateKeyActivity.loadFragment(null, frag, FragAction.TO_RIGHT);
+ mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java
new file mode 100644
index 000000000..180a52a1c
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.support.v4.app.Fragment;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
+import org.sufficientlysecure.keychain.ui.dialog.AddEmailDialogFragment;
+import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
+import org.sufficientlysecure.keychain.ui.widget.EmailEditText;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CreateKeyStartFragment extends Fragment {
+
+ CreateKeyActivity mCreateKeyActivity;
+
+ View mCreateKey;
+ View mImportKey;
+ View mYubiKey;
+ TextView mCancel;
+ public static final int REQUEST_CODE_CREATE_OR_IMPORT_KEY = 0x00007012;
+
+ /**
+ * Creates new instance of this fragment
+ */
+ public static CreateKeyStartFragment newInstance() {
+ CreateKeyStartFragment frag = new CreateKeyStartFragment();
+
+ Bundle args = new Bundle();
+
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.create_key_start_fragment, container, false);
+
+ mCreateKey = view.findViewById(R.id.create_key_create_key_button);
+ mImportKey = view.findViewById(R.id.create_key_import_button);
+// mYubiKey = view.findViewById(R.id.create_key_yubikey_button);
+ mCancel = (TextView) view.findViewById(R.id.create_key_cancel);
+
+ if (mCreateKeyActivity.mFirstTime) {
+ mCancel.setText(R.string.first_time_skip);
+ } else {
+ mCancel.setText(R.string.btn_do_not_save);
+ }
+
+ mCreateKey.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ CreateKeyNameFragment frag = CreateKeyNameFragment.newInstance();
+ mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
+ }
+ });
+
+ mImportKey.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(mCreateKeyActivity, ImportKeysActivity.class);
+ intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN);
+ startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY);
+ }
+ });
+
+ mCancel.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finishSetup(null);
+ }
+ });
+
+ return view;
+ }
+
+
+ private void finishSetup(Intent srcData) {
+ if (mCreateKeyActivity.mFirstTime) {
+ Preferences prefs = Preferences.getPreferences(mCreateKeyActivity);
+ prefs.setFirstTime(false);
+ }
+ Intent intent = new Intent(mCreateKeyActivity, MainActivity.class);
+ // give intent through to display notify
+ if (srcData != null) {
+ intent.putExtras(srcData);
+ }
+ startActivity(intent);
+ mCreateKeyActivity.finish();
+ }
+
+ // workaround for https://code.google.com/p/android/issues/detail?id=61394
+// @Override
+// public boolean onKeyDown(int keyCode, KeyEvent event) {
+// return keyCode == KeyEvent.KEYCODE_MENU || super.onKeyDown(keyCode, event);
+// }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == REQUEST_CODE_CREATE_OR_IMPORT_KEY) {
+ if (resultCode == Activity.RESULT_OK) {
+ finishSetup(data);
+ }
+ } else {
+ Log.e(Constants.TAG, "No valid request code!");
+ }
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mCreateKeyActivity = (CreateKeyActivity) getActivity();
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
index 7e33843ea..71832daa5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
@@ -191,7 +191,7 @@ public class DecryptFilesFragment extends DecryptFragment {
data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal());
data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri);
- data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
+ data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@@ -265,7 +265,7 @@ public class DecryptFilesFragment extends DecryptFragment {
data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal());
data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri);
- data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
+ data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@@ -341,7 +341,7 @@ public class DecryptFilesFragment extends DecryptFragment {
switch (requestCode) {
case REQUEST_CODE_PASSPHRASE: {
if (resultCode == Activity.RESULT_OK && data != null) {
- mPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
+ mPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
decryptOriginalFilename();
}
return;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
index 513300cc5..63508e530 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
@@ -32,6 +32,7 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
+import org.sufficientlysecure.keychain.util.Passphrase;
public abstract class DecryptFragment extends Fragment {
private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006;
@@ -57,7 +58,7 @@ public abstract class DecryptFragment extends Fragment {
// State
- protected String mPassphrase;
+ protected Passphrase mPassphrase;
protected byte[] mNfcDecryptedSessionKey;
@Override
@@ -100,7 +101,7 @@ public abstract class DecryptFragment extends Fragment {
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
}
- protected void startNfcDecrypt(long subKeyId, String pin, byte[] encryptedSessionKey) {
+ protected void startNfcDecrypt(long subKeyId, Passphrase pin, byte[] encryptedSessionKey) {
// build PendingIntent for Yubikey NFC operations
Intent intent = new Intent(getActivity(), NfcActivity.class);
intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
index 1b34f6bf0..30cf739fc 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
@@ -161,7 +161,7 @@ public class DecryptTextFragment extends DecryptFragment {
// data
data.putInt(KeychainIntentService.TARGET, IOType.BYTES.ordinal());
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, mCiphertext.getBytes());
- data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
+ data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@@ -247,7 +247,7 @@ public class DecryptTextFragment extends DecryptFragment {
case REQUEST_CODE_PASSPHRASE: {
if (resultCode == Activity.RESULT_OK && data != null) {
- mPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
+ mPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
decryptStart();
} else {
getActivity().finish();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
index 9f2fa54f8..45d681308 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
@@ -69,6 +69,8 @@ import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
+
public class EditKeyFragment extends CryptoOperationFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
@@ -337,7 +339,7 @@ public class EditKeyFragment extends CryptoOperationFragment implements
// cache new returned passphrase!
mSaveKeyringParcel.mNewUnlock = new ChangeUnlockParcel(
- data.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
+ (Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
null
);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
index 66d1ad5a6..b87dec8fc 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
@@ -33,6 +33,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
+import org.sufficientlysecure.keychain.util.Passphrase;
public abstract class EncryptActivity extends BaseActivity {
@@ -41,7 +42,7 @@ public abstract class EncryptActivity extends BaseActivity {
public static final int REQUEST_CODE_NFC = 0x00008002;
// For NFC data
- protected String mSigningKeyPassphrase = null;
+ protected Passphrase mSigningKeyPassphrase = null;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -76,7 +77,7 @@ public abstract class EncryptActivity extends BaseActivity {
switch (requestCode) {
case REQUEST_CODE_PASSPHRASE: {
if (resultCode == RESULT_OK && data != null) {
- mSigningKeyPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
+ mSigningKeyPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
startEncrypt();
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java
index c89707c34..2a102c6c4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java
@@ -19,6 +19,8 @@ package org.sufficientlysecure.keychain.ui;
import android.net.Uri;
+import org.sufficientlysecure.keychain.util.Passphrase;
+
import java.util.ArrayList;
public interface EncryptActivityInterface {
@@ -39,7 +41,7 @@ public interface EncryptActivityInterface {
public void setEncryptionKeys(long[] encryptionKeys);
public void setEncryptionUsers(String[] encryptionUsers);
- public void setPassphrase(String passphrase);
+ public void setPassphrase(Passphrase passphrase);
// ArrayList on purpose as only those are parcelable
public ArrayList<Uri> getInputUris();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
index 49a0f5016..eef11b855 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
@@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ShareHelper;
import java.util.ArrayList;
@@ -72,7 +73,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
private long mEncryptionKeyIds[] = null;
private String mEncryptionUserIds[] = null;
private long mSigningKeyId = Constants.key.none;
- private String mPassphrase = "";
+ private Passphrase mPassphrase = new Passphrase();
private ArrayList<Uri> mInputUris;
private ArrayList<Uri> mOutputUris;
@@ -136,7 +137,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
}
@Override
- public void setPassphrase(String passphrase) {
+ public void setPassphrase(Passphrase passphrase) {
mPassphrase = passphrase;
}
@@ -243,8 +244,8 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
if (isModeSymmetric()) {
Log.d(Constants.TAG, "Symmetric encryption enabled!");
- String passphrase = mPassphrase;
- if (passphrase.length() == 0) {
+ Passphrase passphrase = mPassphrase;
+ if (passphrase.isEmpty()) {
passphrase = null;
}
data.setSymmetricPassphrase(passphrase);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java
index 86731b162..36b3c08f9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java
@@ -28,6 +28,7 @@ import android.view.ViewGroup;
import android.widget.EditText;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.util.Passphrase;
public class EncryptSymmetricFragment extends Fragment implements EncryptActivityInterface.UpdateListener {
@@ -67,8 +68,13 @@ public class EncryptSymmetricFragment extends Fragment implements EncryptActivit
@Override
public void afterTextChanged(Editable s) {
// update passphrase in EncryptActivity
- if (mPassphrase.getText().toString().equals(mPassphraseAgain.getText().toString())) {
- mEncryptInterface.setPassphrase(s.toString());
+ Passphrase p1 = new Passphrase(mPassphrase.getText());
+ Passphrase p2 = new Passphrase(mPassphraseAgain.getText());
+ boolean passesEquals = (p1.equals(p2));
+ p1.removeFromMemory();
+ p2.removeFromMemory();
+ if (passesEquals) {
+ mEncryptInterface.setPassphrase(new Passphrase(mPassphrase.getText()));
} else {
mEncryptInterface.setPassphrase(null);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
index 894c1202d..3047661ad 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
@@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.pgp.PgpConstants;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ShareHelper;
import java.util.ArrayList;
@@ -70,7 +71,7 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
private String mEncryptionUserIds[] = null;
// TODO Constants.key.none? What's wrong with a null value?
private long mSigningKeyId = Constants.key.none;
- private String mPassphrase = "";
+ private Passphrase mPassphrase = new Passphrase();
private ArrayList<Uri> mInputUris;
private ArrayList<Uri> mOutputUris;
@@ -134,7 +135,8 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
}
@Override
- public void setPassphrase(String passphrase) {
+ public void setPassphrase(Passphrase passphrase) {
+ mPassphrase.removeFromMemory();
mPassphrase = passphrase;
}
@@ -223,8 +225,8 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
if (isModeSymmetric()) {
Log.d(Constants.TAG, "Symmetric encryption enabled!");
- String passphrase = mPassphrase;
- if (passphrase.length() == 0) {
+ Passphrase passphrase = mPassphrase;
+ if (passphrase.isEmpty()) {
passphrase = null;
}
data.setSymmetricPassphrase(passphrase);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java
deleted file mode 100644
index 393e15cfa..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.Window;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.util.Preferences;
-
-public class FirstTimeActivity extends BaseActivity {
-
- View mCreateKey;
- View mImportKey;
- View mSkipSetup;
-
- public static final int REQUEST_CODE_CREATE_OR_IMPORT_KEY = 0x00007012;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
-
- super.onCreate(savedInstanceState);
-
- mCreateKey = findViewById(R.id.first_time_create_key);
- mImportKey = findViewById(R.id.first_time_import_key);
- mSkipSetup = findViewById(R.id.first_time_cancel);
-
- mSkipSetup.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- finishSetup(null);
- }
- });
-
- mImportKey.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(FirstTimeActivity.this, ImportKeysActivity.class);
- intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN);
- startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY);
- }
- });
-
- mCreateKey.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(FirstTimeActivity.this, CreateKeyActivity.class);
- startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY);
- }
- });
- }
-
- @Override
- protected void initLayout() {
- setContentView(R.layout.first_time_activity);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
-
- if (requestCode == REQUEST_CODE_CREATE_OR_IMPORT_KEY) {
- if (resultCode == RESULT_OK) {
- finishSetup(data);
- }
- } else {
- Log.e(Constants.TAG, "No valid request code!");
- }
- }
-
- private void finishSetup(Intent srcData) {
- Preferences prefs = Preferences.getPreferences(this);
- prefs.setFirstTime(false);
- Intent intent = new Intent(this, MainActivity.class);
- // give intent through to display notify
- if (srcData != null) {
- intent.putExtras(srcData);
- }
- startActivity(intent);
- finish();
- }
-
- // workaround for https://code.google.com/p/android/issues/detail?id=61394
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- return keyCode == KeyEvent.KEYCODE_MENU || super.onKeyDown(keyCode, event);
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
index 4b604add8..f8939f3d1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -489,7 +489,8 @@ public class KeyListFragment extends LoaderFragment
case R.id.menu_key_list_debug_first_time:
Preferences prefs = Preferences.getPreferences(getActivity());
prefs.setFirstTime(true);
- Intent intent = new Intent(getActivity(), FirstTimeActivity.class);
+ Intent intent = new Intent(getActivity(), CreateKeyActivity.class);
+ intent.putExtra(CreateKeyActivity.EXTRA_FIRST_TIME, true);
startActivity(intent);
getActivity().finish();
return true;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
index b6b2fcb8a..5fa3edba4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
@@ -54,7 +54,9 @@ public class MainActivity extends MaterialNavigationDrawer implements FabContain
// if this is the first time show first time activity
Preferences prefs = Preferences.getPreferences(this);
if (prefs.isFirstTime()) {
- startActivity(new Intent(this, FirstTimeActivity.class));
+ Intent intent = new Intent(this, CreateKeyActivity.class);
+ intent.putExtra(CreateKeyActivity.EXTRA_FIRST_TIME, true);
+ startActivity(intent);
finish();
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
index ca65f47cd..9e04426eb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
@@ -59,6 +59,7 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType;
import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
/**
@@ -333,7 +334,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
positive.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- final String passphrase = mPassphraseEditText.getText().toString();
+ final Passphrase passphrase = new Passphrase(mPassphraseEditText);
// Early breakout if we are dealing with a symmetric key
if (mSecretRing == null) {
@@ -410,7 +411,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
});
}
- private void finishCaching(String passphrase) {
+ private void finishCaching(Passphrase passphrase) {
// any indication this isn't needed anymore, don't do it.
if (mIsCancelled || getActivity() == null) {
return;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index 13a5ac269..45ad944c4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -21,18 +21,12 @@ package org.sufficientlysecure.keychain.ui;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
-import android.nfc.NdefMessage;
-import android.nfc.NdefRecord;
-import android.nfc.NfcAdapter;
-import android.nfc.NfcEvent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
@@ -40,7 +34,6 @@ import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.provider.ContactsContract;
-import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
@@ -58,9 +51,7 @@ import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
-
import com.getbase.floatingactionbutton.FloatingActionButton;
-
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
@@ -74,6 +65,8 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler.MessageStatus;
+import org.sufficientlysecure.keychain.service.PassphraseCacheService;
+import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
@@ -82,6 +75,7 @@ import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.ExportHelper;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.NfcHelper;
import org.sufficientlysecure.keychain.util.Preferences;
import java.util.ArrayList;
@@ -91,8 +85,8 @@ public class ViewKeyActivity extends BaseActivity implements
LoaderManager.LoaderCallbacks<Cursor> {
static final int REQUEST_QR_FINGERPRINT = 1;
- static final int REQUEST_DELETE= 2;
- static final int REQUEST_EXPORT= 3;
+ static final int REQUEST_DELETE = 2;
+ static final int REQUEST_EXPORT = 3;
ExportHelper mExportHelper;
ProviderHelper mProviderHelper;
@@ -113,11 +107,7 @@ public class ViewKeyActivity extends BaseActivity implements
private CardView mQrCodeLayout;
// NFC
- private NfcAdapter mNfcAdapter;
- private NfcAdapter.CreateNdefMessageCallback mNdefCallback;
- private NfcAdapter.OnNdefPushCompleteCallback mNdefCompleteCallback;
- private byte[] mNfcKeyringBytes;
- private static final int NFC_SENT = 1;
+ private NfcHelper mNfcHelper;
private static final int LOADER_ID_UNIFIED = 0;
@@ -254,7 +244,7 @@ public class ViewKeyActivity extends BaseActivity implements
mActionNfc.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- invokeNfcBeam();
+ mNfcHelper.invokeNfcBeam();
}
});
@@ -262,7 +252,8 @@ public class ViewKeyActivity extends BaseActivity implements
// or start new ones.
getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
- initNfc(mDataUri);
+ mNfcHelper = new NfcHelper(this, mProviderHelper);
+ mNfcHelper.initNfc(mDataUri);
startFragment(savedInstanceState, mDataUri);
}
@@ -310,31 +301,31 @@ public class ViewKeyActivity extends BaseActivity implements
return true;
}
case R.id.menu_key_view_export_file: {
- Intent mIntent = new Intent(this,PassphraseDialogActivity.class);
- long keyId=0;
try {
- keyId = new ProviderHelper(this)
- .getCachedPublicKeyRing(mDataUri)
- .extractOrGetMasterKeyId();
- } catch (PgpKeyNotFoundException e) {
- e.printStackTrace();
+ if (PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId, mMasterKeyId) != null) {
+ exportToFile(mDataUri, mExportHelper, mProviderHelper);
+ return true;
+ }
+
+ startPassphraseActivity(REQUEST_EXPORT);
+ } catch (PassphraseCacheService.KeyNotFoundException e) {
+ // This happens when the master key is stripped
+ exportToFile(mDataUri, mExportHelper, mProviderHelper);
}
- mIntent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID,keyId);
- startActivityForResult(mIntent,REQUEST_EXPORT);
return true;
}
case R.id.menu_key_view_delete: {
- Intent mIntent = new Intent(this,PassphraseDialogActivity.class);
- long keyId=0;
try {
- keyId = new ProviderHelper(this)
- .getCachedPublicKeyRing(mDataUri)
- .extractOrGetMasterKeyId();
- } catch (PgpKeyNotFoundException e) {
- e.printStackTrace();
+ if (PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId, mMasterKeyId) != null) {
+ deleteKey();
+ return true;
+ }
+
+ startPassphraseActivity(REQUEST_DELETE);
+ } catch (PassphraseCacheService.KeyNotFoundException e) {
+ // This happens when the master key is stripped
+ deleteKey();
}
- mIntent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID,keyId);
- startActivityForResult(mIntent,REQUEST_DELETE);
return true;
}
case R.id.menu_key_view_advanced: {
@@ -373,41 +364,6 @@ public class ViewKeyActivity extends BaseActivity implements
return true;
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- private void invokeNfcBeam() {
- // Check if device supports NFC
- if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) {
- Notify.createNotify(this, R.string.no_nfc_support, Notify.LENGTH_LONG, Notify.Style.ERROR).show();
- return;
- }
- // Check for available NFC Adapter
- mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
- if (mNfcAdapter == null || !mNfcAdapter.isEnabled()) {
- Notify.createNotify(this, R.string.error_nfc_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
- @Override
- public void onAction() {
- Intent intentSettings = new Intent(Settings.ACTION_NFC_SETTINGS);
- startActivity(intentSettings);
- }
- }, R.string.menu_nfc_preferences).show();
-
- return;
- }
-
- if (!mNfcAdapter.isNdefPushEnabled()) {
- Notify.createNotify(this, R.string.error_beam_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
- @Override
- public void onAction() {
- Intent intentSettings = new Intent(Settings.ACTION_NFCSHARING_SETTINGS);
- startActivity(intentSettings);
- }
- }, R.string.menu_beam_preferences).show();
-
- return;
- }
-
- mNfcAdapter.invokeBeam(this);
- }
private void scanQrCode() {
Intent scanQrCode = new Intent(this, ImportKeysProxyActivity.class);
@@ -424,7 +380,7 @@ public class ViewKeyActivity extends BaseActivity implements
private void certifyImmediate() {
Intent intent = new Intent(this, CertifyKeyActivity.class);
- intent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[]{mMasterKeyId});
+ intent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[] {mMasterKeyId});
startCertifyIntent(intent);
}
@@ -473,22 +429,32 @@ public class ViewKeyActivity extends BaseActivity implements
ActivityCompat.startActivity(this, qrCodeIntent, opts);
}
- private void exportToFile(Uri dataUri, ExportHelper exportHelper, ProviderHelper providerHelper)
- throws ProviderHelper.NotFoundException {
- Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri);
-
- HashMap<String, Object> data = providerHelper.getGenericData(
- baseUri,
- new String[]{KeychainContract.Keys.MASTER_KEY_ID, KeychainContract.KeyRings.HAS_SECRET},
- new int[]{ProviderHelper.FIELD_TYPE_INTEGER, ProviderHelper.FIELD_TYPE_INTEGER});
+ private void startPassphraseActivity(int requestCode) {
+ Intent intent = new Intent(this, PassphraseDialogActivity.class);
+ intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, mMasterKeyId);
+ startActivityForResult(intent, requestCode);
+ }
- exportHelper.showExportKeysDialog(
- new long[]{(Long) data.get(KeychainContract.KeyRings.MASTER_KEY_ID)},
- Constants.Path.APP_DIR_FILE, ((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) != 0)
- );
+ private void exportToFile(Uri dataUri, ExportHelper exportHelper, ProviderHelper providerHelper) {
+ try {
+ Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri);
+
+ HashMap<String, Object> data = providerHelper.getGenericData(
+ baseUri,
+ new String[] {KeychainContract.Keys.MASTER_KEY_ID, KeychainContract.KeyRings.HAS_SECRET},
+ new int[] {ProviderHelper.FIELD_TYPE_INTEGER, ProviderHelper.FIELD_TYPE_INTEGER});
+
+ exportHelper.showExportKeysDialog(
+ new long[] {(Long) data.get(KeychainContract.KeyRings.MASTER_KEY_ID)},
+ Constants.Path.APP_DIR_FILE, ((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) != 0)
+ );
+ } catch (ProviderHelper.NotFoundException e) {
+ Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR);
+ Log.e(Constants.TAG, "Key not found", e);
+ }
}
- private void deleteKey(Uri dataUri, ExportHelper exportHelper) {
+ private void deleteKey() {
// Message is received after key is deleted
Handler returnHandler = new Handler() {
@Override
@@ -500,7 +466,11 @@ public class ViewKeyActivity extends BaseActivity implements
}
};
- exportHelper.deleteKey(dataUri, returnHandler);
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(returnHandler);
+ DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
+ new long[] {mMasterKeyId});
+ deleteKeyDialog.show(getSupportFragmentManager(), "deleteKeyDialog");
}
@Override
@@ -530,18 +500,13 @@ public class ViewKeyActivity extends BaseActivity implements
return;
}
- if (requestCode == REQUEST_DELETE && resultCode == Activity.RESULT_OK){
- deleteKey(mDataUri, mExportHelper);
- }
- if (requestCode == REQUEST_EXPORT && resultCode == Activity.RESULT_OK){
- try {
- exportToFile(mDataUri, mExportHelper, mProviderHelper);
- } catch (ProviderHelper.NotFoundException e) {
- Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR);
- Log.e(Constants.TAG, "Key not found", e);
- }
+ if (requestCode == REQUEST_DELETE && resultCode == Activity.RESULT_OK) {
+ deleteKey();
}
+ if (requestCode == REQUEST_EXPORT && resultCode == Activity.RESULT_OK) {
+ exportToFile(mDataUri, mExportHelper, mProviderHelper);
+ }
if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) {
OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
@@ -561,7 +526,7 @@ public class ViewKeyActivity extends BaseActivity implements
long keyId = new ProviderHelper(this)
.getCachedPublicKeyRing(dataUri)
.extractOrGetMasterKeyId();
- long[] encryptionKeyIds = new long[]{keyId};
+ long[] encryptionKeyIds = new long[] {keyId};
Intent intent;
if (text) {
intent = new Intent(this, EncryptTextActivity.class);
@@ -699,98 +664,9 @@ public class ViewKeyActivity extends BaseActivity implements
loadTask.execute();
}
- /**
- * NFC: Initialize NFC sharing if OS and device supports it
- */
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- private void initNfc(final Uri dataUri) {
- // check if NFC Beam is supported (>= Android 4.1)
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-
- // Implementation for the CreateNdefMessageCallback interface
- mNdefCallback = new NfcAdapter.CreateNdefMessageCallback() {
- @Override
- public NdefMessage createNdefMessage(NfcEvent event) {
- /*
- * When a device receives a push with an AAR in it, the application specified in the AAR is
- * guaranteed to run. The AAR overrides the tag dispatch system. You can add it back in to
- * guarantee that this activity starts when receiving a beamed message. For now, this code
- * uses the tag dispatch system.
- */
- return new NdefMessage(NdefRecord.createMime(Constants.NFC_MIME,
- mNfcKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME));
- }
- };
-
- // Implementation for the OnNdefPushCompleteCallback interface
- mNdefCompleteCallback = new NfcAdapter.OnNdefPushCompleteCallback() {
- @Override
- public void onNdefPushComplete(NfcEvent event) {
- // A handler is needed to send messages to the activity when this
- // callback occurs, because it happens from a binder thread
- mNfcHandler.obtainMessage(NFC_SENT).sendToTarget();
- }
- };
-
- // Check for available NFC Adapter
- mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
- if (mNfcAdapter != null) {
- /*
- * Retrieve mNfcKeyringBytes here asynchronously (to not block the UI)
- * and init nfc adapter afterwards.
- * mNfcKeyringBytes can not be retrieved in createNdefMessage, because this process
- * has no permissions to query the Uri.
- */
- AsyncTask<Void, Void, Void> initTask =
- new AsyncTask<Void, Void, Void>() {
- protected Void doInBackground(Void... unused) {
- try {
- Uri blobUri =
- KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri);
- mNfcKeyringBytes = (byte[]) mProviderHelper.getGenericData(
- blobUri,
- KeychainContract.KeyRingData.KEY_RING_DATA,
- ProviderHelper.FIELD_TYPE_BLOB);
- } catch (ProviderHelper.NotFoundException e) {
- Log.e(Constants.TAG, "key not found!", e);
- }
-
- // no AsyncTask return (Void)
- return null;
- }
-
- protected void onPostExecute(Void unused) {
- // Register callback to set NDEF message
- mNfcAdapter.setNdefPushMessageCallback(mNdefCallback,
- ViewKeyActivity.this);
- // Register callback to listen for message-sent success
- mNfcAdapter.setOnNdefPushCompleteCallback(mNdefCompleteCallback,
- ViewKeyActivity.this);
- }
- };
-
- initTask.execute();
- }
- }
- }
-
- /**
- * NFC: This handler receives a message from onNdefPushComplete
- */
- private final Handler mNfcHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case NFC_SENT:
- Notify.showNotify(
- ViewKeyActivity.this, R.string.nfc_successful, Notify.Style.INFO);
- break;
- }
- }
- };
// These are the rows that we will retrieve.
- static final String[] PROJECTION = new String[]{
+ static final String[] PROJECTION = new String[] {
KeychainContract.KeyRings._ID,
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.KeyRings.USER_ID,
@@ -1007,4 +883,4 @@ public class ViewKeyActivity extends BaseActivity implements
public void onLoaderReset(Loader<Cursor> loader) {
}
-}
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
index 95a6faea9..29586ae9f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
@@ -52,6 +52,7 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.NfcHelper;
import java.io.IOException;
@@ -68,10 +69,12 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
private View mFingerprintClipboardButton;
private View mKeyShareButton;
private View mKeyClipboardButton;
+ private View mKeyNfcButton;
private ImageButton mKeySafeSlingerButton;
private View mKeyUploadButton;
ProviderHelper mProviderHelper;
+ NfcHelper mNfcHelper;
private static final int LOADER_ID_UNIFIED = 0;
@@ -83,6 +86,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
View view = inflater.inflate(R.layout.view_key_adv_share_fragment, getContainer());
mProviderHelper = new ProviderHelper(ViewKeyAdvShareFragment.this.getActivity());
+ mNfcHelper = new NfcHelper(getActivity(), mProviderHelper);
mFingerprint = (TextView) view.findViewById(R.id.view_key_fingerprint);
mQrCode = (ImageView) view.findViewById(R.id.view_key_qr_code);
@@ -90,6 +94,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
mFingerprintShareButton = view.findViewById(R.id.view_key_action_fingerprint_share);
mFingerprintClipboardButton = view.findViewById(R.id.view_key_action_fingerprint_clipboard);
mKeyShareButton = view.findViewById(R.id.view_key_action_key_share);
+ mKeyNfcButton = view.findViewById(R.id.view_key_action_key_nfc);
mKeyClipboardButton = view.findViewById(R.id.view_key_action_key_clipboard);
mKeySafeSlingerButton = (ImageButton) view.findViewById(R.id.view_key_action_key_safeslinger);
mKeyUploadButton = view.findViewById(R.id.view_key_action_upload);
@@ -128,6 +133,14 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
share(mDataUri, mProviderHelper, false, true);
}
});
+
+ mKeyNfcButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNfcHelper.invokeNfcBeam();
+ }
+ });
+
mKeySafeSlingerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -255,9 +268,12 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
// Prepare the loaders. Either re-connect with an existing ones,
// or start new ones.
getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
+
+ // Prepare the NfcHelper
+ mNfcHelper.initNfc(mDataUri);
}
- static final String[] UNIFIED_PROJECTION = new String[]{
+ static final String[] UNIFIED_PROJECTION = new String[] {
KeyRings._ID, KeyRings.MASTER_KEY_ID, KeyRings.HAS_ANY_SECRET,
KeyRings.USER_ID, KeyRings.FINGERPRINT,
KeyRings.ALGORITHM, KeyRings.KEY_SIZE, KeyRings.CREATION, KeyRings.IS_EXPIRED,
@@ -362,4 +378,5 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
startActivityForResult(uploadIntent, 0);
}
-}
+
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
index dc8d8f303..4eb253825 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
@@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.widget.PassphraseEditText;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
private static final String ARG_MESSENGER = "messenger";
@@ -113,12 +114,12 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
public void onClick(DialogInterface dialog, int id) {
dismiss();
- String passphrase1;
+ Passphrase passphrase1 = new Passphrase();
if (mNoPassphraseCheckBox.isChecked()) {
- passphrase1 = "";
+ passphrase1.setEmpty();
} else {
- passphrase1 = mPassphraseEditText.getText().toString();
- String passphrase2 = mPassphraseAgainEditText.getText().toString();
+ passphrase1 = new Passphrase(mPassphraseEditText);
+ Passphrase passphrase2 = new Passphrase(mPassphraseAgainEditText);
if (!passphrase1.equals(passphrase2)) {
Toast.makeText(
activity,
@@ -129,7 +130,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
return;
}
- if (passphrase1.equals("")) {
+ if (passphrase1.isEmpty()) {
Toast.makeText(
activity,
getString(R.string.error_message,
@@ -142,7 +143,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
// return resulting data back to activity
Bundle data = new Bundle();
- data.putString(MESSAGE_NEW_PASSPHRASE, passphrase1);
+ data.putParcelable(MESSAGE_NEW_PASSPHRASE, passphrase1);
sendMessageToHandler(MESSAGE_OKAY, data);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java
index 3bc29edb6..9736b5765 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java
@@ -19,6 +19,11 @@ package org.sufficientlysecure.keychain.ui.util;
import android.app.Activity;
import android.content.res.Resources;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.view.View;
+import android.view.ViewGroup;
import com.nispok.snackbar.Snackbar;
import com.nispok.snackbar.Snackbar.SnackbarDuration;
@@ -61,11 +66,11 @@ public class Notify {
break;
}
- SnackbarManager.show(bar);
+ showSnackbar(activity, bar);
}
- public static Showable createNotify (Activity activity, int resId, int duration, Style style) {
+ public static Showable createNotify (final Activity activity, int resId, int duration, Style style) {
final Snackbar bar = getSnackbar(activity)
.text(resId);
@@ -90,7 +95,7 @@ public class Notify {
return new Showable () {
@Override
public void show() {
- SnackbarManager.show(bar);
+ showSnackbar(activity, bar);
}
};
}
@@ -104,7 +109,7 @@ public class Notify {
return createNotify(activity, msg, duration, style, null, 0);
}
- public static Showable createNotify(Activity activity, String msg, int duration, Style style,
+ public static Showable createNotify(final Activity activity, String msg, int duration, Style style,
final ActionListener listener, int resIdAction) {
final Snackbar bar = getSnackbar(activity)
@@ -141,7 +146,7 @@ public class Notify {
return new Showable () {
@Override
public void show() {
- SnackbarManager.show(bar);
+ showSnackbar(activity, bar);
}
};
@@ -178,6 +183,26 @@ public class Notify {
return bar;
}
+ private static void showSnackbar(Activity activity, Snackbar snackbar) {
+ if (activity instanceof FragmentActivity) {
+ FragmentManager fragmentManager = ((FragmentActivity) activity).getSupportFragmentManager();
+
+ int count = fragmentManager.getBackStackEntryCount();
+ Fragment fragment = fragmentManager.getFragments().get(count > 0 ? count - 1 : 0);
+
+ if (fragment != null) {
+ View view = fragment.getView();
+
+ if (view != null) {
+ SnackbarManager.show(snackbar, (ViewGroup) view);
+ return;
+ }
+ }
+ }
+
+ SnackbarManager.show(snackbar);
+ }
+
public interface Showable {
public void show();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java
index 1bdec7b84..e21c5d510 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java
@@ -58,9 +58,10 @@ public class EmailEditText extends AutoCompleteTextView {
}
private void init() {
- this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
- this.addTextChangedListener(textWatcher);
- removeFlag();
+ setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ reenableKeyboardSuggestions();
+
+ addTextChangedListener(textWatcher);
initAdapter();
}
@@ -104,7 +105,7 @@ public class EmailEditText extends AutoCompleteTextView {
* Hack to re-enable keyboard auto correction in AutoCompleteTextView.
* From http://stackoverflow.com/a/22512858
*/
- private void removeFlag() {
+ private void reenableKeyboardSuggestions() {
int inputType = getInputType();
inputType &= ~EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE;
setRawInputType(inputType);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java
index f086c5696..153bf2ff2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java
@@ -50,7 +50,7 @@ public class NameEditText extends AutoCompleteTextView {
}
private void init() {
- removeFlag();
+ reenableKeyboardSuggestions();
initAdapter();
}
@@ -62,10 +62,10 @@ public class NameEditText extends AutoCompleteTextView {
}
/**
- * Hack to re-enable keyboard auto correction in AutoCompleteTextView.
+ * Hack to re-enable keyboard suggestions in AutoCompleteTextView.
* From http://stackoverflow.com/a/22512858
*/
- private void removeFlag() {
+ private void reenableKeyboardSuggestions() {
int inputType = getInputType();
inputType &= ~EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE;
setRawInputType(inputType);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
index cda5892fe..7b164f2b2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
@@ -47,21 +47,6 @@ public class ExportHelper {
this.mActivity = activity;
}
- public void deleteKey(Uri dataUri, Handler deleteHandler) {
- try {
- long masterKeyId = new ProviderHelper(mActivity).getCachedPublicKeyRing(dataUri)
- .extractOrGetMasterKeyId();
-
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(deleteHandler);
- DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
- new long[]{ masterKeyId });
- deleteKeyDialog.show(mActivity.getSupportFragmentManager(), "deleteKeyDialog");
- } catch (PgpKeyNotFoundException e) {
- Log.e(Constants.TAG, "key not found!", e);
- }
- }
-
/**
* Show dialog where to export keys
*/
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java
new file mode 100644
index 000000000..c010ac151
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Kent Nguyen <kentnguyen@moneylover.me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.util;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.nfc.NdefMessage;
+import android.nfc.NdefRecord;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcEvent;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Settings;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.ui.util.Notify;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * This class contains NFC functionality that can be shared across Fragments or Activities.
+ */
+
+public class NfcHelper {
+
+ private Activity mActivity;
+ private ProviderHelper mProviderHelper;
+
+ /**
+ * NFC: This handler receives a message from onNdefPushComplete
+ */
+ private static NfcHandler mNfcHandler;
+
+ private NfcAdapter mNfcAdapter;
+ private NfcAdapter.CreateNdefMessageCallback mNdefCallback;
+ private NfcAdapter.OnNdefPushCompleteCallback mNdefCompleteCallback;
+ private byte[] mNfcKeyringBytes;
+ private static final int NFC_SENT = 1;
+
+ /**
+ * Initializes the NfcHelper.
+ */
+ public NfcHelper(final Activity activity, final ProviderHelper providerHelper) {
+ mActivity = activity;
+ mProviderHelper = providerHelper;
+
+ mNfcHandler = new NfcHandler(mActivity);
+ }
+
+ /**
+ * Return true if the NFC Adapter of this Helper has any features enabled.
+ *
+ * @return true if this NFC Adapter has any features enabled
+ */
+ public boolean isEnabled() {
+ return mNfcAdapter.isEnabled();
+ }
+
+ /**
+ * NFC: Initialize NFC sharing if OS and device supports it
+ */
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+ public void initNfc(final Uri dataUri) {
+ // check if NFC Beam is supported (>= Android 4.1)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+
+ // Implementation for the CreateNdefMessageCallback interface
+ mNdefCallback = new NfcAdapter.CreateNdefMessageCallback() {
+ @Override
+ public NdefMessage createNdefMessage(NfcEvent event) {
+ /*
+ * When a device receives a push with an AAR in it, the application specified in the AAR is
+ * guaranteed to run. The AAR overrides the tag dispatch system. You can add it back in to
+ * guarantee that this activity starts when receiving a beamed message. For now, this code
+ * uses the tag dispatch system.
+ */
+ return new NdefMessage(NdefRecord.createMime(Constants.NFC_MIME,
+ mNfcKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME));
+ }
+ };
+
+ // Implementation for the OnNdefPushCompleteCallback interface
+ mNdefCompleteCallback = new NfcAdapter.OnNdefPushCompleteCallback() {
+ @Override
+ public void onNdefPushComplete(NfcEvent event) {
+ // A handler is needed to send messages to the activity when this
+ // callback occurs, because it happens from a binder thread
+ mNfcHandler.obtainMessage(NFC_SENT).sendToTarget();
+ }
+ };
+
+ // Check for available NFC Adapter
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity);
+ if (mNfcAdapter != null) {
+ /*
+ * Retrieve mNfcKeyringBytes here asynchronously (to not block the UI)
+ * and init nfc adapter afterwards.
+ * mNfcKeyringBytes can not be retrieved in createNdefMessage, because this process
+ * has no permissions to query the Uri.
+ */
+ AsyncTask<Void, Void, Void> initTask =
+ new AsyncTask<Void, Void, Void>() {
+ protected Void doInBackground(Void... unused) {
+ try {
+ Uri blobUri =
+ KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri);
+ mNfcKeyringBytes = (byte[]) mProviderHelper.getGenericData(
+ blobUri,
+ KeychainContract.KeyRingData.KEY_RING_DATA,
+ ProviderHelper.FIELD_TYPE_BLOB);
+ } catch (ProviderHelper.NotFoundException e) {
+ Log.e(Constants.TAG, "key not found!", e);
+ }
+
+ // no AsyncTask return (Void)
+ return null;
+ }
+
+ protected void onPostExecute(Void unused) {
+ // Register callback to set NDEF message
+ mNfcAdapter.setNdefPushMessageCallback(mNdefCallback,
+ mActivity);
+ // Register callback to listen for message-sent success
+ mNfcAdapter.setOnNdefPushCompleteCallback(mNdefCompleteCallback,
+ mActivity);
+ }
+ };
+
+ initTask.execute();
+ }
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public void invokeNfcBeam() {
+ // Check if device supports NFC
+ if (!mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) {
+ Notify.createNotify(mActivity, R.string.no_nfc_support, Notify.LENGTH_LONG, Notify.Style.ERROR).show();
+ return;
+ }
+ // Check for available NFC Adapter
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity);
+ if (mNfcAdapter == null || !mNfcAdapter.isEnabled()) {
+ Notify.createNotify(mActivity, R.string.error_nfc_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
+ @Override
+ public void onAction() {
+ Intent intentSettings = new Intent(Settings.ACTION_NFC_SETTINGS);
+ mActivity.startActivity(intentSettings);
+ }
+ }, R.string.menu_nfc_preferences).show();
+
+ return;
+ }
+
+ if (!mNfcAdapter.isNdefPushEnabled()) {
+ Notify.createNotify(mActivity, R.string.error_beam_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
+ @Override
+ public void onAction() {
+ Intent intentSettings = new Intent(Settings.ACTION_NFCSHARING_SETTINGS);
+ mActivity.startActivity(intentSettings);
+ }
+ }, R.string.menu_beam_preferences).show();
+
+ return;
+ }
+
+ mNfcAdapter.invokeBeam(mActivity);
+ }
+
+ /**
+ * A static subclass of {@link Handler} with a {@link WeakReference} to an {@link Activity} to avoid memory leaks.
+ */
+ private static class NfcHandler extends Handler {
+ private final WeakReference<Activity> mActivityReference;
+
+ public NfcHandler(Activity activity) {
+ mActivityReference = new WeakReference<>(activity);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ Activity activity = mActivityReference.get();
+
+ if (activity != null) {
+ switch (msg.what) {
+ case NFC_SENT:
+ Notify.showNotify(
+ activity, R.string.nfc_successful, Notify.Style.INFO);
+ break;
+ }
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java
new file mode 100644
index 000000000..06efdde4d
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.util;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.Editable;
+import android.widget.EditText;
+
+import org.sufficientlysecure.keychain.Constants;
+
+import java.util.Arrays;
+
+/**
+ * Passwords should not be stored as Strings in memory.
+ * This class wraps a char[] that can be erased after it is no longer used.
+ * See also:
+ * <p/>
+ * http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#PBEEx
+ * https://github.com/c-a-m/passfault/blob/master/core/src/main/java/org/owasp/passfault/SecureString.java
+ * http://stackoverflow.com/q/8881291
+ * http://stackoverflow.com/a/15844273
+ */
+public class Passphrase implements Parcelable {
+ private char[] mPassphrase;
+
+ /**
+ * According to http://stackoverflow.com/a/15844273 EditText is not using String internally
+ * but char[]. Thus, we can get the char[] directly from it.
+ */
+ public Passphrase(Editable editable) {
+ int pl = editable.length();
+ mPassphrase = new char[pl];
+ editable.getChars(0, pl, mPassphrase, 0);
+ // TODO: clean up internal char[] of EditText after getting the passphrase?
+// editText.getText().replace()
+ }
+
+ public Passphrase(EditText editText) {
+ this(editText.getText());
+ }
+
+ public Passphrase(char[] passphrase) {
+ mPassphrase = passphrase;
+ }
+
+ public Passphrase(String passphrase) {
+ mPassphrase = passphrase.toCharArray();
+ }
+
+ /**
+ * Creates a passphrase object with an empty ("") passphrase
+ */
+ public Passphrase() {
+ setEmpty();
+ }
+
+ public char[] getCharArray() {
+ return mPassphrase;
+ }
+
+ public void setEmpty() {
+ removeFromMemory();
+ mPassphrase = new char[0];
+ }
+
+ public boolean isEmpty() {
+ return (length() == 0);
+ }
+
+ public int length() {
+ return mPassphrase.length;
+ }
+
+ public char charAt(int index) {
+ return mPassphrase[index];
+ }
+
+ /**
+ * Manually clear the underlying array holding the characters
+ */
+ public void removeFromMemory() {
+ if (mPassphrase != null) {
+ Arrays.fill(mPassphrase, ' ');
+ }
+ }
+
+ @Override
+ public void finalize() throws Throwable {
+ removeFromMemory();
+ super.finalize();
+ }
+
+ @Override
+ public String toString() {
+ if (Constants.DEBUG) {
+ return "Passphrase{" +
+ "mPassphrase=" + Arrays.toString(mPassphrase) +
+ '}';
+ } else {
+ return "Passphrase: hidden";
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Passphrase that = (Passphrase) o;
+ if (!Arrays.equals(mPassphrase, that.mPassphrase)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return mPassphrase != null ? Arrays.hashCode(mPassphrase) : 0;
+ }
+
+ private Passphrase(Parcel source) {
+ mPassphrase = source.createCharArray();
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeCharArray(mPassphrase);
+ }
+
+ public static final Creator<Passphrase> CREATOR = new Creator<Passphrase>() {
+ public Passphrase createFromParcel(final Parcel source) {
+ return new Passphrase(source);
+ }
+
+ public Passphrase[] newArray(final int size) {
+ return new Passphrase[size];
+ }
+ };
+
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_nfc_grey_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_nfc_grey_24dp.png
new file mode 100644
index 000000000..fedf39013
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_nfc_grey_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_nfc_grey_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_nfc_grey_24dp.png
new file mode 100644
index 000000000..f8f6c3812
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_nfc_grey_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_nfc_grey_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_nfc_grey_24dp.png
new file mode 100644
index 000000000..04e0bf781
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_nfc_grey_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_nfc_grey_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_nfc_grey_24dp.png
new file mode 100644
index 000000000..7e8fa6ba2
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_nfc_grey_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_nfc_grey_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_nfc_grey_24dp.png
new file mode 100644
index 000000000..ee00975dc
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_nfc_grey_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/layout/create_key_name_fragment.xml b/OpenKeychain/src/main/res/layout/create_key_name_fragment.xml
index ea064b00c..a2f81f74c 100644
--- a/OpenKeychain/src/main/res/layout/create_key_name_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/create_key_name_fragment.xml
@@ -56,11 +56,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
+ android:text="@string/btn_back"
android:textAllCaps="true"
android:minHeight="?android:attr/listPreferredItemHeight"
+ android:drawableLeft="@drawable/ic_chevron_left_grey_24dp"
android:drawablePadding="8dp"
android:gravity="left|center_vertical"
- android:clickable="false"
+ android:clickable="true"
style="?android:attr/borderlessButtonStyle" />
<TextView
diff --git a/OpenKeychain/src/main/res/layout/create_key_start_fragment.xml b/OpenKeychain/src/main/res/layout/create_key_start_fragment.xml
new file mode 100644
index 000000000..79ffe58b1
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/create_key_start_fragment.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:layout_above="@+id/create_key_buttons">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="0dp"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:layout_marginTop="16dp"
+ android:layout_marginBottom="16dp"
+ android:adjustViewBounds="true"
+ android:src="@drawable/first_time_1"
+ android:layout_gravity="center_horizontal"
+ android:layout_weight="1" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:background="@color/holo_gray_bright"
+ android:id="@+id/create_key_buttons">
+
+ <TextView
+ android:id="@+id/create_key_create_key_button"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/first_time_create_key"
+ android:textAllCaps="true"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:drawableRight="@drawable/ic_chevron_right_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="right|center_vertical"
+ android:clickable="true"
+ style="?android:attr/borderlessButtonStyle" />
+
+ <!--<TextView-->
+ <!--android:id="@+id/create_key_yubikey_button"-->
+ <!--android:paddingLeft="16dp"-->
+ <!--android:paddingRight="16dp"-->
+ <!--android:textAppearance="?android:attr/textAppearanceMedium"-->
+ <!--android:layout_width="match_parent"-->
+ <!--android:layout_height="wrap_content"-->
+ <!--android:layout_weight="1"-->
+ <!--android:text="@string/first_time_yubikey"-->
+ <!--android:textAllCaps="true"-->
+ <!--android:minHeight="?android:attr/listPreferredItemHeight"-->
+ <!--android:drawableRight="@drawable/ic_chevron_right_grey_24dp"-->
+ <!--android:drawablePadding="8dp"-->
+ <!--android:gravity="right|center_vertical"-->
+ <!--android:clickable="true"-->
+ <!--style="?android:attr/borderlessButtonStyle" />-->
+
+ <TextView
+ android:id="@+id/create_key_import_button"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/first_time_import_key"
+ android:textAllCaps="true"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:drawableRight="@drawable/ic_chevron_right_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="right|center_vertical"
+ android:clickable="true"
+ style="?android:attr/borderlessButtonStyle" />
+
+ <TextView
+ android:id="@+id/create_key_cancel"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_do_not_save"
+ android:textAllCaps="true"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:drawableRight="@drawable/ic_close_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="right|center_vertical"
+ android:clickable="true"
+ style="?android:attr/borderlessButtonStyle" />
+ </LinearLayout>
+</RelativeLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/first_time_activity.xml b/OpenKeychain/src/main/res/layout/first_time_activity.xml
deleted file mode 100644
index 9b37766e9..000000000
--- a/OpenKeychain/src/main/res/layout/first_time_activity.xml
+++ /dev/null
@@ -1,137 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingTop="16dp">
-
- <ImageView
- android:id="@+id/status_bar"
- android:layout_width="match_parent"
- android:layout_height="@dimen/statusbar_height" />
-
- <LinearLayout
- android:id="@+id/first_time_buttons"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
- android:layout_alignParentBottom="true"
- android:orientation="vertical">
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="?android:attr/listDivider" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <TextView
- android:id="@+id/first_time_import_key"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/first_time_import_key"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:drawableRight="@drawable/ic_folder_grey_24dp"
- android:drawablePadding="8dp"
- android:gravity="center_vertical"
- android:layout_gravity="center_vertical"
- android:clickable="true"
- android:background="?android:selectableItemBackground" />
-
- <View
- android:layout_width="1dp"
- android:layout_height="match_parent"
- android:layout_marginTop="8dp"
- android:layout_marginBottom="8dp"
- android:background="?android:attr/listDivider" />
-
- <TextView
- android:id="@+id/first_time_create_key"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/first_time_create_key"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:drawableRight="@drawable/ic_key_plus_grey600_24dp"
- android:drawablePadding="8dp"
- android:gravity="center_vertical"
- android:layout_gravity="center_vertical"
- android:clickable="true"
- android:background="?android:selectableItemBackground" />
-
- </LinearLayout>
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="?android:attr/listDivider" />
-
- <TextView
- android:id="@+id/first_time_cancel"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/first_time_skip"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:gravity="center"
- android:clickable="true"
- android:background="?android:selectableItemBackground"
- android:layout_gravity="center_horizontal" />
-
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:layout_below="@+id/status_bar"
- android:layout_above="@+id/first_time_buttons">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:text="@string/app_name"
- android:drawableLeft="@drawable/ic_launcher"
- android:drawablePadding="8dp"
- android:gravity="center"
- android:layout_gravity="center_horizontal" />
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="0dp"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- android:layout_marginTop="16dp"
- android:layout_marginBottom="16dp"
- android:adjustViewBounds="true"
- android:src="@drawable/first_time_1"
- android:layout_gravity="center_horizontal"
- android:layout_weight="1" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="64dp"
- android:layout_marginRight="64dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:text="@string/first_time_text1"
- android:layout_gravity="center_horizontal"
- android:gravity="center_horizontal"
- android:layout_marginBottom="16dp" />
-
- </LinearLayout>
-
-</RelativeLayout>
diff --git a/OpenKeychain/src/main/res/layout/view_key_adv_share_fragment.xml b/OpenKeychain/src/main/res/layout/view_key_adv_share_fragment.xml
index 6a21e0dc1..c08d66cc1 100644
--- a/OpenKeychain/src/main/res/layout/view_key_adv_share_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/view_key_adv_share_fragment.xml
@@ -99,14 +99,12 @@
android:layout_weight="1" />
<LinearLayout
- android:id="@+id/view_key_action_key_share"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
- android:clickable="true"
- android:background="?android:selectableItemBackground"
android:orientation="horizontal">
<TextView
+ android:id="@+id/view_key_action_key_share"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:textAppearance="?android:attr/textAppearanceMedium"
@@ -116,7 +114,25 @@
android:layout_weight="1"
android:drawableRight="@drawable/ic_share_grey_24dp"
android:drawablePadding="8dp"
- android:gravity="center_vertical" />
+ android:gravity="center_vertical"
+ android:background="?android:selectableItemBackground"/>
+
+ <View
+ android:layout_width="1dip"
+ android:layout_height="match_parent"
+ android:gravity="right"
+ android:layout_marginBottom="8dp"
+ android:layout_marginTop="8dp"
+ android:background="?android:attr/listDivider" />
+
+ <ImageButton
+ android:id="@+id/view_key_action_key_nfc"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:padding="8dp"
+ android:src="@drawable/ic_nfc_grey_24dp"
+ android:layout_gravity="center_vertical"
+ android:background="?android:selectableItemBackground" />
<View
android:layout_width="1dip"
@@ -154,6 +170,7 @@
</LinearLayout>
+
<View
android:layout_width="match_parent"
android:layout_height="1dip"
diff --git a/OpenKeychain/src/main/res/menu/key_list.xml b/OpenKeychain/src/main/res/menu/key_list.xml
index 386a9d46e..15e098138 100644
--- a/OpenKeychain/src/main/res/menu/key_list.xml
+++ b/OpenKeychain/src/main/res/menu/key_list.xml
@@ -16,7 +16,7 @@
<item
android:id="@+id/menu_key_list_create"
- android:title="@string/menu_create_key"
+ android:title="@string/menu_manage_keys"
app:showAsAction="never" />
<item
diff --git a/OpenKeychain/src/main/res/values-cs/strings.xml b/OpenKeychain/src/main/res/values-cs/strings.xml
index 9c16fa413..ab8b00eca 100644
--- a/OpenKeychain/src/main/res/values-cs/strings.xml
+++ b/OpenKeychain/src/main/res/values-cs/strings.xml
@@ -71,7 +71,7 @@
<string name="menu_help">Nápověda</string>
<string name="menu_export_key">Exportovat do souboru</string>
<string name="menu_delete_key">Smazat klíč</string>
- <string name="menu_create_key">Vytvořit moje klíče</string>
+ <string name="menu_manage_keys">Vytvořit moje klíče</string>
<string name="menu_import_existing_key">Importovat ze souboru</string>
<string name="menu_search">Hledat</string>
<string name="menu_beam_preferences">Beam settings</string>
diff --git a/OpenKeychain/src/main/res/values-de/strings.xml b/OpenKeychain/src/main/res/values-de/strings.xml
index fbae159a3..20c8d933d 100644
--- a/OpenKeychain/src/main/res/values-de/strings.xml
+++ b/OpenKeychain/src/main/res/values-de/strings.xml
@@ -88,7 +88,7 @@
<string name="menu_help">Hilfe</string>
<string name="menu_export_key">In Datei exportieren</string>
<string name="menu_delete_key">Schlüssel löschen</string>
- <string name="menu_create_key">Erzeuge meinen Schlüssel</string>
+ <string name="menu_manage_keys">Erzeuge meinen Schlüssel</string>
<string name="menu_import_existing_key">Von Datei importieren</string>
<string name="menu_search">Suchen</string>
<string name="menu_nfc_preferences">NFC-Einstellungen</string>
diff --git a/OpenKeychain/src/main/res/values-es/strings.xml b/OpenKeychain/src/main/res/values-es/strings.xml
index d7557074a..6ba096420 100644
--- a/OpenKeychain/src/main/res/values-es/strings.xml
+++ b/OpenKeychain/src/main/res/values-es/strings.xml
@@ -89,7 +89,7 @@
<string name="menu_help">Ayuda</string>
<string name="menu_export_key">Exportar hacia archivo</string>
<string name="menu_delete_key">Borrar clave</string>
- <string name="menu_create_key">Crear mi clave</string>
+ <string name="menu_manage_keys">Crear mi clave</string>
<string name="menu_import_existing_key">Importar desde fichero</string>
<string name="menu_search">Buscar</string>
<string name="menu_nfc_preferences">Configuraciones NFC</string>
diff --git a/OpenKeychain/src/main/res/values-eu/strings.xml b/OpenKeychain/src/main/res/values-eu/strings.xml
index 32fdfc4cb..73ac12403 100644
--- a/OpenKeychain/src/main/res/values-eu/strings.xml
+++ b/OpenKeychain/src/main/res/values-eu/strings.xml
@@ -76,7 +76,7 @@
<string name="menu_help">Laguntza</string>
<string name="menu_export_key">Esportatu agirira</string>
<string name="menu_delete_key">Ezabatu giltza</string>
- <string name="menu_create_key">Sortu nire giltza</string>
+ <string name="menu_manage_keys">Sortu nire giltza</string>
<string name="menu_import_existing_key">inportatu agiritik</string>
<string name="menu_search">Bilatu</string>
<string name="menu_nfc_preferences">NFC ezarpenak</string>
diff --git a/OpenKeychain/src/main/res/values-fi/strings.xml b/OpenKeychain/src/main/res/values-fi/strings.xml
index 4b75d203d..508b17d0a 100644
--- a/OpenKeychain/src/main/res/values-fi/strings.xml
+++ b/OpenKeychain/src/main/res/values-fi/strings.xml
@@ -70,7 +70,7 @@
<string name="menu_help">Apua</string>
<string name="menu_export_key">Vie tiedostoon</string>
<string name="menu_delete_key">Poista avain</string>
- <string name="menu_create_key">Luo minun avaimeni</string>
+ <string name="menu_manage_keys">Luo minun avaimeni</string>
<string name="menu_import_existing_key">Tuo tiedostosta</string>
<string name="menu_search">Etsi</string>
<string name="menu_beam_preferences">Beam asetukset</string>
diff --git a/OpenKeychain/src/main/res/values-fr/strings.xml b/OpenKeychain/src/main/res/values-fr/strings.xml
index ba6f2e2af..3b3add86a 100644
--- a/OpenKeychain/src/main/res/values-fr/strings.xml
+++ b/OpenKeychain/src/main/res/values-fr/strings.xml
@@ -89,7 +89,7 @@
<string name="menu_help">Aide</string>
<string name="menu_export_key">Exporter vers un fichier</string>
<string name="menu_delete_key">Supprimer la clef</string>
- <string name="menu_create_key">Créer ma clef</string>
+ <string name="menu_manage_keys">Créer ma clef</string>
<string name="menu_import_existing_key">Importer depuis un fichier</string>
<string name="menu_search">Rechercher</string>
<string name="menu_nfc_preferences">Paramètres NFC</string>
diff --git a/OpenKeychain/src/main/res/values-it/strings.xml b/OpenKeychain/src/main/res/values-it/strings.xml
index 5de5a1579..4b88aa494 100644
--- a/OpenKeychain/src/main/res/values-it/strings.xml
+++ b/OpenKeychain/src/main/res/values-it/strings.xml
@@ -69,7 +69,7 @@
<string name="menu_help">Aiuto</string>
<string name="menu_export_key">Esporta su un file</string>
<string name="menu_delete_key">Cancella chiave</string>
- <string name="menu_create_key">Crea mia chiave</string>
+ <string name="menu_manage_keys">Crea mia chiave</string>
<string name="menu_import_existing_key">Importa da file</string>
<string name="menu_search">Cerca</string>
<string name="menu_beam_preferences">Impostazioni Beam</string>
diff --git a/OpenKeychain/src/main/res/values-ja/strings.xml b/OpenKeychain/src/main/res/values-ja/strings.xml
index 183938811..16b9c3cc4 100644
--- a/OpenKeychain/src/main/res/values-ja/strings.xml
+++ b/OpenKeychain/src/main/res/values-ja/strings.xml
@@ -89,7 +89,7 @@
<string name="menu_help">ヘルプ</string>
<string name="menu_export_key">ファイルへのエクスポート</string>
<string name="menu_delete_key">鍵の削除</string>
- <string name="menu_create_key">自分の鍵の生成</string>
+ <string name="menu_manage_keys">自分の鍵の生成</string>
<string name="menu_import_existing_key">ファイルからインポート</string>
<string name="menu_search">検索</string>
<string name="menu_nfc_preferences">NFC設定</string>
diff --git a/OpenKeychain/src/main/res/values-nl/strings.xml b/OpenKeychain/src/main/res/values-nl/strings.xml
index 0d3cb0094..d77d4e331 100644
--- a/OpenKeychain/src/main/res/values-nl/strings.xml
+++ b/OpenKeychain/src/main/res/values-nl/strings.xml
@@ -96,7 +96,7 @@
<string name="menu_help">Help</string>
<string name="menu_export_key">Exporteren naar bestand</string>
<string name="menu_delete_key">Sleutel verwijderen</string>
- <string name="menu_create_key">Mijn sleutel aanmaken</string>
+ <string name="menu_manage_keys">Mijn sleutel aanmaken</string>
<string name="menu_import_existing_key">Importeren van bestand</string>
<string name="menu_search">Zoeken</string>
<string name="menu_nfc_preferences">NFC-instellingen</string>
diff --git a/OpenKeychain/src/main/res/values-pl/strings.xml b/OpenKeychain/src/main/res/values-pl/strings.xml
index 1ee5a86e7..e4fce6bcc 100644
--- a/OpenKeychain/src/main/res/values-pl/strings.xml
+++ b/OpenKeychain/src/main/res/values-pl/strings.xml
@@ -78,7 +78,7 @@
<string name="menu_help">Pomoc</string>
<string name="menu_export_key">Eksportuj do pliku</string>
<string name="menu_delete_key">Usuń klucz</string>
- <string name="menu_create_key">Utwórz mój klucz</string>
+ <string name="menu_manage_keys">Utwórz mój klucz</string>
<string name="menu_import_existing_key">Importuj z pliku</string>
<string name="menu_search">Szukaj</string>
<string name="menu_beam_preferences">Ustawienia Beam</string>
diff --git a/OpenKeychain/src/main/res/values-ru/strings.xml b/OpenKeychain/src/main/res/values-ru/strings.xml
index 9559ecf51..7cd0cec9b 100644
--- a/OpenKeychain/src/main/res/values-ru/strings.xml
+++ b/OpenKeychain/src/main/res/values-ru/strings.xml
@@ -85,7 +85,7 @@
<string name="menu_help">Помощь</string>
<string name="menu_export_key">Экспорт в файл</string>
<string name="menu_delete_key">Удалить ключ</string>
- <string name="menu_create_key">Создать свой ключ</string>
+ <string name="menu_manage_keys">Создать свой ключ</string>
<string name="menu_import_existing_key">Импорт из файла</string>
<string name="menu_search">Поиск</string>
<string name="menu_nfc_preferences">Настройки NFC</string>
diff --git a/OpenKeychain/src/main/res/values-sl/strings.xml b/OpenKeychain/src/main/res/values-sl/strings.xml
index 3eb8eeba8..3f0def752 100644
--- a/OpenKeychain/src/main/res/values-sl/strings.xml
+++ b/OpenKeychain/src/main/res/values-sl/strings.xml
@@ -75,7 +75,7 @@
<string name="menu_help">Pomoč</string>
<string name="menu_export_key">Izvozi v datoteko</string>
<string name="menu_delete_key">Izbriši ključ</string>
- <string name="menu_create_key">Ustvari zasebni ključ</string>
+ <string name="menu_manage_keys">Ustvari zasebni ključ</string>
<string name="menu_import_existing_key">Uvozi iz datoteke</string>
<string name="menu_search">Išči</string>
<string name="menu_beam_preferences">Nastavitve Beam</string>
diff --git a/OpenKeychain/src/main/res/values-sr/strings.xml b/OpenKeychain/src/main/res/values-sr/strings.xml
index b5ba0b361..c4c92dce5 100644
--- a/OpenKeychain/src/main/res/values-sr/strings.xml
+++ b/OpenKeychain/src/main/res/values-sr/strings.xml
@@ -89,7 +89,7 @@
<string name="menu_help">Помоћ</string>
<string name="menu_export_key">Извези у фајл</string>
<string name="menu_delete_key">Обриши кључ</string>
- <string name="menu_create_key">Направи ми кључ</string>
+ <string name="menu_manage_keys">Направи ми кључ</string>
<string name="menu_import_existing_key">Увези из фајла</string>
<string name="menu_search">Претрага</string>
<string name="menu_nfc_preferences">НФЦ поставке</string>
diff --git a/OpenKeychain/src/main/res/values-sv/strings.xml b/OpenKeychain/src/main/res/values-sv/strings.xml
index 93b833590..605e14695 100644
--- a/OpenKeychain/src/main/res/values-sv/strings.xml
+++ b/OpenKeychain/src/main/res/values-sv/strings.xml
@@ -78,7 +78,7 @@
<string name="menu_help">Hjälp</string>
<string name="menu_export_key">Exportera till fil</string>
<string name="menu_delete_key">Radera nyckel</string>
- <string name="menu_create_key">Skapa min nyckel</string>
+ <string name="menu_manage_keys">Skapa min nyckel</string>
<string name="menu_import_existing_key">Importera från fil</string>
<string name="menu_search">Sök</string>
<string name="menu_beam_preferences">Beam-inställningar</string>
diff --git a/OpenKeychain/src/main/res/values-tr/strings.xml b/OpenKeychain/src/main/res/values-tr/strings.xml
index 2b60c9758..b939faf0d 100644
--- a/OpenKeychain/src/main/res/values-tr/strings.xml
+++ b/OpenKeychain/src/main/res/values-tr/strings.xml
@@ -69,7 +69,7 @@
<string name="menu_help">Yardım</string>
<string name="menu_export_key">Dosyaya ver</string>
<string name="menu_delete_key">Anahtar sil</string>
- <string name="menu_create_key">Anahtarımı oluştur</string>
+ <string name="menu_manage_keys">Anahtarımı oluştur</string>
<string name="menu_import_existing_key">Dosyadan al</string>
<string name="menu_search">Ara</string>
<string name="menu_beam_preferences">NFC ayarları</string>
diff --git a/OpenKeychain/src/main/res/values-uk/strings.xml b/OpenKeychain/src/main/res/values-uk/strings.xml
index b3a161758..f192cb07a 100644
--- a/OpenKeychain/src/main/res/values-uk/strings.xml
+++ b/OpenKeychain/src/main/res/values-uk/strings.xml
@@ -69,7 +69,7 @@
<string name="menu_help">Довідка</string>
<string name="menu_export_key">Експорт до файлу</string>
<string name="menu_delete_key">Вилучити ключ</string>
- <string name="menu_create_key">Створити мій ключ</string>
+ <string name="menu_manage_keys">Створити мій ключ</string>
<string name="menu_import_existing_key">Імпорт з файлу</string>
<string name="menu_search">Пошук</string>
<string name="menu_beam_preferences">Налаштування променя</string>
diff --git a/OpenKeychain/src/main/res/values-zh-rTW/strings.xml b/OpenKeychain/src/main/res/values-zh-rTW/strings.xml
index 286e98b79..bb8462bf3 100644
--- a/OpenKeychain/src/main/res/values-zh-rTW/strings.xml
+++ b/OpenKeychain/src/main/res/values-zh-rTW/strings.xml
@@ -65,7 +65,7 @@
<string name="menu_help">說明</string>
<string name="menu_export_key">匯出到檔案</string>
<string name="menu_delete_key">刪除金鑰</string>
- <string name="menu_create_key">建立金鑰</string>
+ <string name="menu_manage_keys">建立金鑰</string>
<string name="menu_import_existing_key">從檔案匯入</string>
<string name="menu_search">搜尋</string>
<string name="menu_beam_preferences">Beam 設定</string>
diff --git a/OpenKeychain/src/main/res/values-zh/strings.xml b/OpenKeychain/src/main/res/values-zh/strings.xml
index d59b2a2e0..31df7e587 100644
--- a/OpenKeychain/src/main/res/values-zh/strings.xml
+++ b/OpenKeychain/src/main/res/values-zh/strings.xml
@@ -57,7 +57,7 @@
<string name="menu_help">帮助</string>
<string name="menu_export_key">导出密钥</string>
<string name="menu_delete_key">删除密钥</string>
- <string name="menu_create_key">创建密钥</string>
+ <string name="menu_manage_keys">创建密钥</string>
<string name="menu_search">搜索</string>
<string name="menu_beam_preferences">参数</string>
<string name="menu_key_edit_cancel">取消</string>
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index e8bcbcc31..a7e9cdf7e 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -44,6 +44,7 @@
<string name="title_keys">"Keys"</string>
<string name="title_delete_secret_key">"Delete YOUR key '%s'?"</string>
<string name="title_export_log">"Export Log"</string>
+ <string name="title_manage_my_keys">"Manage my keys"</string>
<!-- section -->
<string name="section_user_ids">"Identities"</string>
@@ -106,7 +107,7 @@
<string name="menu_help">"Help"</string>
<string name="menu_export_key">"Export to file"</string>
<string name="menu_delete_key">"Delete key"</string>
- <string name="menu_create_key">"Create my key"</string>
+ <string name="menu_manage_keys">"Manage my keys"</string>
<string name="menu_import_existing_key">"Import from file"</string>
<string name="menu_search">"Search"</string>
<string name="menu_nfc_preferences">"NFC settings"</string>
@@ -1198,8 +1199,9 @@
<!-- First Time -->
<string name="first_time_text1">"Take back your privacy with OpenKeychain!"</string>
- <string name="first_time_create_key">"Create my key"</string>
- <string name="first_time_import_key">"Import from file"</string>
+ <string name="first_time_create_key">"Create my key (recommended)"</string>
+ <string name="first_time_import_key">"Import key from file"</string>
+ <string name="first_time_yubikey">"Use YubiKey NEO"</string>
<string name="first_time_skip">"Skip Setup"</string>
<!-- unsorted -->