mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-30 12:32:17 -05:00
New Passphrase class for safer passphrase handling in memory
This commit is contained in:
parent
dbcb7a9e10
commit
9c9f95c7ac
@ -24,6 +24,7 @@ import org.sufficientlysecure.keychain.pgp.Progressable;
|
|||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
|
||||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
@ -101,7 +102,7 @@ public abstract class BaseOperation implements PassphraseCacheInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCachedPassphrase(long subKeyId) throws NoSecretKeyException {
|
public Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException {
|
||||||
try {
|
try {
|
||||||
long masterKeyId = mProviderHelper.getMasterKeyId(subKeyId);
|
long masterKeyId = mProviderHelper.getMasterKeyId(subKeyId);
|
||||||
return getCachedPassphrase(masterKeyId, subKeyId);
|
return getCachedPassphrase(masterKeyId, subKeyId);
|
||||||
@ -111,7 +112,7 @@ public abstract class BaseOperation implements PassphraseCacheInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException {
|
public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException {
|
||||||
try {
|
try {
|
||||||
return PassphraseCacheService.getCachedPassphrase(
|
return PassphraseCacheService.getCachedPassphrase(
|
||||||
mContext, masterKeyId, subKeyId);
|
mContext, masterKeyId, subKeyId);
|
||||||
|
@ -40,6 +40,7 @@ import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyActio
|
|||||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
@ -79,7 +80,7 @@ public class CertifyOperation extends BaseOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// certification is always with the master key id, so use that one
|
// certification is always with the master key id, so use that one
|
||||||
String passphrase = getCachedPassphrase(parcel.mMasterKeyId, parcel.mMasterKeyId);
|
Passphrase passphrase = getCachedPassphrase(parcel.mMasterKeyId, parcel.mMasterKeyId);
|
||||||
|
|
||||||
if (!certificationKey.unlock(passphrase)) {
|
if (!certificationKey.unlock(passphrase)) {
|
||||||
log.add(LogType.MSG_CRT_ERROR_UNLOCK, 2);
|
log.add(LogType.MSG_CRT_ERROR_UNLOCK, 2);
|
||||||
|
@ -35,6 +35,7 @@ import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
|||||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
@ -55,7 +56,7 @@ public class EditKeyOperation extends BaseOperation {
|
|||||||
super(context, providerHelper, progressable, cancelled);
|
super(context, providerHelper, progressable, cancelled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EditKeyResult execute(SaveKeyringParcel saveParcel, String passphrase) {
|
public EditKeyResult execute(SaveKeyringParcel saveParcel, Passphrase passphrase) {
|
||||||
|
|
||||||
OperationLog log = new OperationLog();
|
OperationLog log = new OperationLog();
|
||||||
log.add(LogType.MSG_ED, 0);
|
log.add(LogType.MSG_ED, 0);
|
||||||
|
@ -22,6 +22,7 @@ import android.os.Parcel;
|
|||||||
|
|
||||||
import org.openintents.openpgp.OpenPgpMetadata;
|
import org.openintents.openpgp.OpenPgpMetadata;
|
||||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
public class DecryptVerifyResult extends OperationResult {
|
public class DecryptVerifyResult extends OperationResult {
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ public class DecryptVerifyResult extends OperationResult {
|
|||||||
|
|
||||||
long mNfcSubKeyId;
|
long mNfcSubKeyId;
|
||||||
byte[] mNfcSessionKey;
|
byte[] mNfcSessionKey;
|
||||||
String mNfcPassphrase;
|
Passphrase mNfcPassphrase;
|
||||||
|
|
||||||
OpenPgpSignatureResult mSignatureResult;
|
OpenPgpSignatureResult mSignatureResult;
|
||||||
OpenPgpMetadata mDecryptMetadata;
|
OpenPgpMetadata mDecryptMetadata;
|
||||||
@ -53,7 +54,7 @@ public class DecryptVerifyResult extends OperationResult {
|
|||||||
mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
|
mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNfcState(long subKeyId, byte[] sessionKey, String passphrase) {
|
public void setNfcState(long subKeyId, byte[] sessionKey, Passphrase passphrase) {
|
||||||
mNfcSubKeyId = subKeyId;
|
mNfcSubKeyId = subKeyId;
|
||||||
mNfcSessionKey = sessionKey;
|
mNfcSessionKey = sessionKey;
|
||||||
mNfcPassphrase = passphrase;
|
mNfcPassphrase = passphrase;
|
||||||
@ -67,7 +68,7 @@ public class DecryptVerifyResult extends OperationResult {
|
|||||||
return mNfcSessionKey;
|
return mNfcSessionKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNfcPassphrase() {
|
public Passphrase getNfcPassphrase() {
|
||||||
return mNfcPassphrase;
|
return mNfcPassphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +110,7 @@ public class DecryptVerifyResult extends OperationResult {
|
|||||||
mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
|
mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
|
||||||
mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader());
|
mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader());
|
||||||
mNfcSessionKey = source.readInt() != 0 ? source.createByteArray() : null;
|
mNfcSessionKey = source.readInt() != 0 ? source.createByteArray() : null;
|
||||||
mNfcPassphrase = source.readString();
|
mNfcPassphrase = source.readParcelable(Passphrase.class.getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
@ -127,7 +128,7 @@ public class DecryptVerifyResult extends OperationResult {
|
|||||||
} else {
|
} else {
|
||||||
dest.writeInt(0);
|
dest.writeInt(0);
|
||||||
}
|
}
|
||||||
dest.writeString(mNfcPassphrase);
|
dest.writeParcelable(mNfcPassphrase, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Creator<DecryptVerifyResult> CREATOR = new Creator<DecryptVerifyResult>() {
|
public static final Creator<DecryptVerifyResult> CREATOR = new Creator<DecryptVerifyResult>() {
|
||||||
|
@ -19,6 +19,8 @@ package org.sufficientlysecure.keychain.operations.results;
|
|||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
|
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
public class PgpSignEncryptResult extends OperationResult {
|
public class PgpSignEncryptResult extends OperationResult {
|
||||||
@ -36,7 +38,7 @@ public class PgpSignEncryptResult extends OperationResult {
|
|||||||
byte[] mNfcHash;
|
byte[] mNfcHash;
|
||||||
int mNfcAlgo;
|
int mNfcAlgo;
|
||||||
Date mNfcTimestamp;
|
Date mNfcTimestamp;
|
||||||
String mNfcPassphrase;
|
Passphrase mNfcPassphrase;
|
||||||
byte[] mDetachedSignature;
|
byte[] mDetachedSignature;
|
||||||
|
|
||||||
public long getKeyIdPassphraseNeeded() {
|
public long getKeyIdPassphraseNeeded() {
|
||||||
@ -47,7 +49,7 @@ public class PgpSignEncryptResult extends OperationResult {
|
|||||||
mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
|
mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNfcData(long nfcKeyId, byte[] nfcHash, int nfcAlgo, Date nfcTimestamp, String passphrase) {
|
public void setNfcData(long nfcKeyId, byte[] nfcHash, int nfcAlgo, Date nfcTimestamp, Passphrase passphrase) {
|
||||||
mNfcKeyId = nfcKeyId;
|
mNfcKeyId = nfcKeyId;
|
||||||
mNfcHash = nfcHash;
|
mNfcHash = nfcHash;
|
||||||
mNfcAlgo = nfcAlgo;
|
mNfcAlgo = nfcAlgo;
|
||||||
@ -75,7 +77,7 @@ public class PgpSignEncryptResult extends OperationResult {
|
|||||||
return mNfcTimestamp;
|
return mNfcTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNfcPassphrase() {
|
public Passphrase getNfcPassphrase() {
|
||||||
return mNfcPassphrase;
|
return mNfcPassphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ import org.sufficientlysecure.keychain.Constants;
|
|||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -149,7 +150,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
|||||||
/**
|
/**
|
||||||
* Returns true on right passphrase
|
* Returns true on right passphrase
|
||||||
*/
|
*/
|
||||||
public boolean unlock(String passphrase) throws PgpGeneralException {
|
public boolean unlock(Passphrase passphrase) throws PgpGeneralException {
|
||||||
// handle keys on OpenPGP cards like they were unlocked
|
// handle keys on OpenPGP cards like they were unlocked
|
||||||
if (mSecretKey.getS2K() != null
|
if (mSecretKey.getS2K() != null
|
||||||
&& mSecretKey.getS2K().getType() == S2K.GNU_DUMMY_S2K
|
&& mSecretKey.getS2K().getType() == S2K.GNU_DUMMY_S2K
|
||||||
@ -161,7 +162,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
|
|||||||
// try to extract keys using the passphrase
|
// try to extract keys using the passphrase
|
||||||
try {
|
try {
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
|
||||||
mPrivateKey = mSecretKey.extractPrivateKey(keyDecryptor);
|
mPrivateKey = mSecretKey.extractPrivateKey(keyDecryptor);
|
||||||
mPrivateKeyState = PRIVATE_KEY_STATE_UNLOCKED;
|
mPrivateKeyState = PRIVATE_KEY_STATE_UNLOCKED;
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
|
@ -18,14 +18,16 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
public interface PassphraseCacheInterface {
|
public interface PassphraseCacheInterface {
|
||||||
public static class NoSecretKeyException extends Exception {
|
public static class NoSecretKeyException extends Exception {
|
||||||
public NoSecretKeyException() {
|
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
|||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.util.InputData;
|
import org.sufficientlysecure.keychain.util.InputData;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
@ -83,7 +84,7 @@ public class PgpDecryptVerify extends BaseOperation {
|
|||||||
private OutputStream mOutStream;
|
private OutputStream mOutStream;
|
||||||
|
|
||||||
private boolean mAllowSymmetricDecryption;
|
private boolean mAllowSymmetricDecryption;
|
||||||
private String mPassphrase;
|
private Passphrase mPassphrase;
|
||||||
private Set<Long> mAllowedKeyIds;
|
private Set<Long> mAllowedKeyIds;
|
||||||
private boolean mDecryptMetadataOnly;
|
private boolean mDecryptMetadataOnly;
|
||||||
private byte[] mDecryptedSessionKey;
|
private byte[] mDecryptedSessionKey;
|
||||||
@ -118,7 +119,7 @@ public class PgpDecryptVerify extends BaseOperation {
|
|||||||
private OutputStream mOutStream = null;
|
private OutputStream mOutStream = null;
|
||||||
private Progressable mProgressable = null;
|
private Progressable mProgressable = null;
|
||||||
private boolean mAllowSymmetricDecryption = true;
|
private boolean mAllowSymmetricDecryption = true;
|
||||||
private String mPassphrase = null;
|
private Passphrase mPassphrase = null;
|
||||||
private Set<Long> mAllowedKeyIds = null;
|
private Set<Long> mAllowedKeyIds = null;
|
||||||
private boolean mDecryptMetadataOnly = false;
|
private boolean mDecryptMetadataOnly = false;
|
||||||
private byte[] mDecryptedSessionKey = null;
|
private byte[] mDecryptedSessionKey = null;
|
||||||
@ -159,7 +160,7 @@ public class PgpDecryptVerify extends BaseOperation {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setPassphrase(String passphrase) {
|
public Builder setPassphrase(Passphrase passphrase) {
|
||||||
mPassphrase = passphrase;
|
mPassphrase = passphrase;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -572,7 +573,7 @@ public class PgpDecryptVerify extends BaseOperation {
|
|||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build();
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build();
|
||||||
PBEDataDecryptorFactory decryptorFactory = new JcePBEDataDecryptorFactoryBuilder(
|
PBEDataDecryptorFactory decryptorFactory = new JcePBEDataDecryptorFactoryBuilder(
|
||||||
digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||||
mPassphrase.toCharArray());
|
mPassphrase.getCharArray());
|
||||||
|
|
||||||
clear = encryptedDataSymmetric.getDataStream(decryptorFactory);
|
clear = encryptedDataSymmetric.getDataStream(decryptorFactory);
|
||||||
encryptedData = encryptedDataSymmetric;
|
encryptedData = encryptedDataSymmetric;
|
||||||
|
@ -57,6 +57,7 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
|
|||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
import org.sufficientlysecure.keychain.util.Primes;
|
import org.sufficientlysecure.keychain.util.Primes;
|
||||||
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
||||||
|
|
||||||
@ -316,7 +317,7 @@ public class PgpKeyOperation {
|
|||||||
masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator());
|
masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator());
|
||||||
|
|
||||||
subProgressPush(50, 100);
|
subProgressPush(50, 100);
|
||||||
return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, saveParcel, "", log);
|
return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, saveParcel, new Passphrase(), log);
|
||||||
|
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent);
|
log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent);
|
||||||
@ -348,7 +349,7 @@ public class PgpKeyOperation {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR, SaveKeyringParcel saveParcel,
|
public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR, SaveKeyringParcel saveParcel,
|
||||||
String passphrase) {
|
Passphrase passphrase) {
|
||||||
|
|
||||||
OperationLog log = new OperationLog();
|
OperationLog log = new OperationLog();
|
||||||
int indent = 0;
|
int indent = 0;
|
||||||
@ -404,7 +405,7 @@ public class PgpKeyOperation {
|
|||||||
|
|
||||||
private PgpEditKeyResult internal(PGPSecretKeyRing sKR, PGPSecretKey masterSecretKey,
|
private PgpEditKeyResult internal(PGPSecretKeyRing sKR, PGPSecretKey masterSecretKey,
|
||||||
int masterKeyFlags, long masterKeyExpiry,
|
int masterKeyFlags, long masterKeyExpiry,
|
||||||
SaveKeyringParcel saveParcel, String passphrase,
|
SaveKeyringParcel saveParcel, Passphrase passphrase,
|
||||||
OperationLog log) {
|
OperationLog log) {
|
||||||
|
|
||||||
int indent = 1;
|
int indent = 1;
|
||||||
@ -420,7 +421,7 @@ public class PgpKeyOperation {
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
|
||||||
masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
|
masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
|
||||||
} catch (PGPException e) {
|
} catch (PGPException e) {
|
||||||
log.add(LogType.MSG_MF_UNLOCK_ERROR, indent + 1);
|
log.add(LogType.MSG_MF_UNLOCK_ERROR, indent + 1);
|
||||||
@ -839,7 +840,7 @@ public class PgpKeyOperation {
|
|||||||
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
|
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
|
||||||
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
|
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
|
||||||
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
|
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
|
||||||
|
|
||||||
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
|
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
|
||||||
.build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
|
.build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
|
||||||
@ -967,7 +968,7 @@ public class PgpKeyOperation {
|
|||||||
PGPSecretKeyRing sKR,
|
PGPSecretKeyRing sKR,
|
||||||
PGPPublicKey masterPublicKey,
|
PGPPublicKey masterPublicKey,
|
||||||
PGPPrivateKey masterPrivateKey,
|
PGPPrivateKey masterPrivateKey,
|
||||||
String passphrase,
|
Passphrase passphrase,
|
||||||
ChangeUnlockParcel newUnlock,
|
ChangeUnlockParcel newUnlock,
|
||||||
OperationLog log, int indent) throws PGPException {
|
OperationLog log, int indent) throws PGPException {
|
||||||
|
|
||||||
@ -1051,20 +1052,20 @@ public class PgpKeyOperation {
|
|||||||
private static PGPSecretKeyRing applyNewPassphrase(
|
private static PGPSecretKeyRing applyNewPassphrase(
|
||||||
PGPSecretKeyRing sKR,
|
PGPSecretKeyRing sKR,
|
||||||
PGPPublicKey masterPublicKey,
|
PGPPublicKey masterPublicKey,
|
||||||
String passphrase,
|
Passphrase passphrase,
|
||||||
String newPassphrase,
|
Passphrase newPassphrase,
|
||||||
OperationLog log, int indent) throws PGPException {
|
OperationLog log, int indent) throws PGPException {
|
||||||
|
|
||||||
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder().build()
|
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder().build()
|
||||||
.get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
|
.get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
|
||||||
// Build key encryptor based on new passphrase
|
// Build key encryptor based on new passphrase
|
||||||
PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder(
|
PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder(
|
||||||
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
|
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
|
||||||
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
|
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||||
newPassphrase.toCharArray());
|
newPassphrase.getCharArray());
|
||||||
|
|
||||||
// noinspection unchecked
|
// noinspection unchecked
|
||||||
for (PGPSecretKey sKey : new IterableIterator<PGPSecretKey>(sKR.getSecretKeys())) {
|
for (PGPSecretKey sKey : new IterableIterator<PGPSecretKey>(sKR.getSecretKeys())) {
|
||||||
@ -1295,11 +1296,11 @@ public class PgpKeyOperation {
|
|||||||
|
|
||||||
private static PGPSignature generateSubkeyBindingSignature(
|
private static PGPSignature generateSubkeyBindingSignature(
|
||||||
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
|
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
|
||||||
PGPSecretKey sKey, PGPPublicKey pKey, int flags, long expiry, String passphrase)
|
PGPSecretKey sKey, PGPPublicKey pKey, int flags, long expiry, Passphrase passphrase)
|
||||||
throws IOException, PGPException, SignatureException {
|
throws IOException, PGPException, SignatureException {
|
||||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||||
passphrase.toCharArray());
|
passphrase.getCharArray());
|
||||||
PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
|
PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
|
||||||
return generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey, subPrivateKey,
|
return generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey, subPrivateKey,
|
||||||
pKey, flags, expiry);
|
pKey, flags, expiry);
|
||||||
|
@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.pgp;
|
|||||||
|
|
||||||
import org.spongycastle.bcpg.CompressionAlgorithmTags;
|
import org.spongycastle.bcpg.CompressionAlgorithmTags;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@ -29,12 +30,12 @@ public class PgpSignEncryptInput {
|
|||||||
protected boolean mEnableAsciiArmorOutput = false;
|
protected boolean mEnableAsciiArmorOutput = false;
|
||||||
protected int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED;
|
protected int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED;
|
||||||
protected long[] mEncryptionMasterKeyIds = null;
|
protected long[] mEncryptionMasterKeyIds = null;
|
||||||
protected String mSymmetricPassphrase = null;
|
protected Passphrase mSymmetricPassphrase = null;
|
||||||
protected int mSymmetricEncryptionAlgorithm = PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED;
|
protected int mSymmetricEncryptionAlgorithm = PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED;
|
||||||
protected long mSignatureMasterKeyId = Constants.key.none;
|
protected long mSignatureMasterKeyId = Constants.key.none;
|
||||||
protected Long mSignatureSubKeyId = null;
|
protected Long mSignatureSubKeyId = null;
|
||||||
protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED;
|
protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED;
|
||||||
protected String mSignaturePassphrase = null;
|
protected Passphrase mSignaturePassphrase = null;
|
||||||
protected long mAdditionalEncryptId = Constants.key.none;
|
protected long mAdditionalEncryptId = Constants.key.none;
|
||||||
protected byte[] mNfcSignedHash = null;
|
protected byte[] mNfcSignedHash = null;
|
||||||
protected Date mNfcCreationTimestamp = null;
|
protected Date mNfcCreationTimestamp = null;
|
||||||
@ -73,11 +74,11 @@ public class PgpSignEncryptInput {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSignaturePassphrase() {
|
public Passphrase getSignaturePassphrase() {
|
||||||
return mSignaturePassphrase;
|
return mSignaturePassphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PgpSignEncryptInput setSignaturePassphrase(String signaturePassphrase) {
|
public PgpSignEncryptInput setSignaturePassphrase(Passphrase signaturePassphrase) {
|
||||||
mSignaturePassphrase = signaturePassphrase;
|
mSignaturePassphrase = signaturePassphrase;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -118,11 +119,11 @@ public class PgpSignEncryptInput {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSymmetricPassphrase() {
|
public Passphrase getSymmetricPassphrase() {
|
||||||
return mSymmetricPassphrase;
|
return mSymmetricPassphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PgpSignEncryptInput setSymmetricPassphrase(String symmetricPassphrase) {
|
public PgpSignEncryptInput setSymmetricPassphrase(Passphrase symmetricPassphrase) {
|
||||||
mSymmetricPassphrase = symmetricPassphrase;
|
mSymmetricPassphrase = symmetricPassphrase;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -243,7 +243,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
|
|||||||
log.add(LogType.MSG_PSE_SYMMETRIC, indent);
|
log.add(LogType.MSG_PSE_SYMMETRIC, indent);
|
||||||
|
|
||||||
JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator =
|
JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator =
|
||||||
new JcePBEKeyEncryptionMethodGenerator(input.getSymmetricPassphrase().toCharArray());
|
new JcePBEKeyEncryptionMethodGenerator(input.getSymmetricPassphrase().getCharArray());
|
||||||
cPk.addMethod(symmetricEncryptionGenerator);
|
cPk.addMethod(symmetricEncryptionGenerator);
|
||||||
} else {
|
} else {
|
||||||
log.add(LogType.MSG_PSE_ASYMMETRIC, indent);
|
log.add(LogType.MSG_PSE_ASYMMETRIC, indent);
|
||||||
|
@ -22,6 +22,8 @@ import android.net.Uri;
|
|||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -57,12 +59,12 @@ public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable
|
|||||||
mEnableAsciiArmorOutput = src.readInt() == 1;
|
mEnableAsciiArmorOutput = src.readInt() == 1;
|
||||||
mCompressionId = src.readInt();
|
mCompressionId = src.readInt();
|
||||||
mEncryptionMasterKeyIds = src.createLongArray();
|
mEncryptionMasterKeyIds = src.createLongArray();
|
||||||
mSymmetricPassphrase = src.readString();
|
mSymmetricPassphrase = src.readParcelable(Passphrase.class.getClassLoader());
|
||||||
mSymmetricEncryptionAlgorithm = src.readInt();
|
mSymmetricEncryptionAlgorithm = src.readInt();
|
||||||
mSignatureMasterKeyId = src.readLong();
|
mSignatureMasterKeyId = src.readLong();
|
||||||
mSignatureSubKeyId = src.readInt() == 1 ? src.readLong() : null;
|
mSignatureSubKeyId = src.readInt() == 1 ? src.readLong() : null;
|
||||||
mSignatureHashAlgorithm = src.readInt();
|
mSignatureHashAlgorithm = src.readInt();
|
||||||
mSignaturePassphrase = src.readString();
|
mSignaturePassphrase = src.readParcelable(Passphrase.class.getClassLoader());
|
||||||
mAdditionalEncryptId = src.readLong();
|
mAdditionalEncryptId = src.readLong();
|
||||||
mNfcSignedHash = src.createByteArray();
|
mNfcSignedHash = src.createByteArray();
|
||||||
mNfcCreationTimestamp = src.readInt() == 1 ? new Date(src.readLong()) : null;
|
mNfcCreationTimestamp = src.readInt() == 1 ? new Date(src.readLong()) : null;
|
||||||
@ -112,7 +114,7 @@ public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable
|
|||||||
dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
|
dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
|
||||||
dest.writeInt(mCompressionId);
|
dest.writeInt(mCompressionId);
|
||||||
dest.writeLongArray(mEncryptionMasterKeyIds);
|
dest.writeLongArray(mEncryptionMasterKeyIds);
|
||||||
dest.writeString(mSymmetricPassphrase);
|
dest.writeParcelable(mSymmetricPassphrase, flags);
|
||||||
dest.writeInt(mSymmetricEncryptionAlgorithm);
|
dest.writeInt(mSymmetricEncryptionAlgorithm);
|
||||||
dest.writeLong(mSignatureMasterKeyId);
|
dest.writeLong(mSignatureMasterKeyId);
|
||||||
if (mSignatureSubKeyId != null) {
|
if (mSignatureSubKeyId != null) {
|
||||||
@ -122,7 +124,7 @@ public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable
|
|||||||
dest.writeInt(0);
|
dest.writeInt(0);
|
||||||
}
|
}
|
||||||
dest.writeInt(mSignatureHashAlgorithm);
|
dest.writeInt(mSignatureHashAlgorithm);
|
||||||
dest.writeString(mSignaturePassphrase);
|
dest.writeParcelable(mSignaturePassphrase, flags);
|
||||||
dest.writeLong(mAdditionalEncryptId);
|
dest.writeLong(mAdditionalEncryptId);
|
||||||
dest.writeByteArray(mNfcSignedHash);
|
dest.writeByteArray(mNfcSignedHash);
|
||||||
if (mNfcCreationTimestamp != null) {
|
if (mNfcCreationTimestamp != null) {
|
||||||
|
@ -54,6 +54,7 @@ import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
|
|||||||
import org.sufficientlysecure.keychain.ui.ViewKeyActivity;
|
import org.sufficientlysecure.keychain.ui.ViewKeyActivity;
|
||||||
import org.sufficientlysecure.keychain.util.InputData;
|
import org.sufficientlysecure.keychain.util.InputData;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -179,7 +180,7 @@ public class OpenPgpService extends RemoteService {
|
|||||||
return result;
|
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
|
// build PendingIntent for Yubikey NFC operations
|
||||||
Intent intent = new Intent(getBaseContext(), NfcActivity.class);
|
Intent intent = new Intent(getBaseContext(), NfcActivity.class);
|
||||||
intent.setAction(NfcActivity.ACTION_SIGN_HASH);
|
intent.setAction(NfcActivity.ACTION_SIGN_HASH);
|
||||||
@ -195,7 +196,7 @@ public class OpenPgpService extends RemoteService {
|
|||||||
PendingIntent.FLAG_CANCEL_CURRENT);
|
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
|
// build PendingIntent for Yubikey NFC operations
|
||||||
Intent intent = new Intent(getBaseContext(), NfcActivity.class);
|
Intent intent = new Intent(getBaseContext(), NfcActivity.class);
|
||||||
intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY);
|
intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY);
|
||||||
@ -508,7 +509,7 @@ public class OpenPgpService extends RemoteService {
|
|||||||
KeychainContract.ApiAllowedKeys.buildBaseUri(currentPkg));
|
KeychainContract.ApiAllowedKeys.buildBaseUri(currentPkg));
|
||||||
}
|
}
|
||||||
|
|
||||||
String passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE);
|
Passphrase passphrase = data.getParcelableExtra(OpenPgpApi.EXTRA_PASSPHRASE);
|
||||||
long inputLength = is.available();
|
long inputLength = is.available();
|
||||||
InputData inputData = new InputData(is, inputLength);
|
InputData inputData = new InputData(is, inputLength);
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ import org.sufficientlysecure.keychain.util.FileHelper;
|
|||||||
import org.sufficientlysecure.keychain.util.InputData;
|
import org.sufficientlysecure.keychain.util.InputData;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
import org.sufficientlysecure.keychain.util.ParcelableFileCache;
|
import org.sufficientlysecure.keychain.util.ParcelableFileCache;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@ -281,7 +282,7 @@ public class KeychainIntentService extends IntentService implements Progressable
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
/* Input */
|
/* Input */
|
||||||
String passphrase = data.getString(DECRYPT_PASSPHRASE);
|
Passphrase passphrase = data.getParcelable(DECRYPT_PASSPHRASE);
|
||||||
byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
|
byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
|
||||||
|
|
||||||
InputData inputData = createDecryptInputData(data);
|
InputData inputData = createDecryptInputData(data);
|
||||||
@ -411,7 +412,7 @@ public class KeychainIntentService extends IntentService implements Progressable
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
/* Input */
|
/* Input */
|
||||||
String passphrase = data.getString(DECRYPT_PASSPHRASE);
|
Passphrase passphrase = data.getParcelable(DECRYPT_PASSPHRASE);
|
||||||
byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
|
byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
|
||||||
|
|
||||||
InputData inputData = createDecryptInputData(data);
|
InputData inputData = createDecryptInputData(data);
|
||||||
@ -469,7 +470,7 @@ public class KeychainIntentService extends IntentService implements Progressable
|
|||||||
|
|
||||||
// Input
|
// Input
|
||||||
SaveKeyringParcel saveParcel = data.getParcelable(EDIT_KEYRING_PARCEL);
|
SaveKeyringParcel saveParcel = data.getParcelable(EDIT_KEYRING_PARCEL);
|
||||||
String passphrase = data.getString(EDIT_KEYRING_PASSPHRASE);
|
Passphrase passphrase = data.getParcelable(EDIT_KEYRING_PASSPHRASE);
|
||||||
|
|
||||||
// Operation
|
// Operation
|
||||||
EditKeyOperation op = new EditKeyOperation(this, providerHelper, this, mActionCanceled);
|
EditKeyOperation op = new EditKeyOperation(this, providerHelper, this, mActionCanceled);
|
||||||
|
@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
|
|||||||
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
import org.sufficientlysecure.keychain.util.Preferences;
|
import org.sufficientlysecure.keychain.util.Preferences;
|
||||||
|
|
||||||
import java.util.Date;
|
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.
|
* 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,
|
public static void addCachedPassphrase(Context context, long masterKeyId, long subKeyId,
|
||||||
String passphrase,
|
Passphrase passphrase,
|
||||||
String primaryUserId) {
|
String primaryUserId) {
|
||||||
Log.d(Constants.TAG, "PassphraseCacheService.cacheNewPassphrase() for " + masterKeyId);
|
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)
|
* @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 "
|
Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphrase() for masterKeyId "
|
||||||
+ masterKeyId + ", subKeyId " + subKeyId);
|
+ masterKeyId + ", subKeyId " + subKeyId);
|
||||||
|
|
||||||
@ -190,7 +191,9 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
switch (returnMessage.what) {
|
switch (returnMessage.what) {
|
||||||
case MSG_PASSPHRASE_CACHE_GET_OKAY:
|
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:
|
case MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND:
|
||||||
throw new KeyNotFoundException();
|
throw new KeyNotFoundException();
|
||||||
default:
|
default:
|
||||||
@ -202,11 +205,11 @@ public class PassphraseCacheService extends Service {
|
|||||||
/**
|
/**
|
||||||
* Internal implementation to get cached passphrase.
|
* 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?
|
// passphrase for symmetric encryption?
|
||||||
if (masterKeyId == Constants.key.symmetric) {
|
if (masterKeyId == Constants.key.symmetric) {
|
||||||
Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for symmetric encryption");
|
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) {
|
if (cachedPassphrase == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -232,13 +235,13 @@ public class PassphraseCacheService extends Service {
|
|||||||
case DIVERT_TO_CARD:
|
case DIVERT_TO_CARD:
|
||||||
if (Preferences.getPreferences(this).useDefaultYubikeyPin()) {
|
if (Preferences.getPreferences(this).useDefaultYubikeyPin()) {
|
||||||
Log.d(Constants.TAG, "PassphraseCacheService: Using default Yubikey PIN: 123456");
|
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 {
|
} else {
|
||||||
Log.d(Constants.TAG, "PassphraseCacheService: NOT using default Yubikey PIN");
|
Log.d(Constants.TAG, "PassphraseCacheService: NOT using default Yubikey PIN");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PASSPHRASE_EMPTY:
|
case PASSPHRASE_EMPTY:
|
||||||
return "";
|
return new Passphrase("");
|
||||||
case UNAVAILABLE:
|
case UNAVAILABLE:
|
||||||
throw new ProviderHelper.NotFoundException("secret key for this subkey is not available");
|
throw new ProviderHelper.NotFoundException("secret key for this subkey is not available");
|
||||||
case GNU_DUMMY:
|
case GNU_DUMMY:
|
||||||
@ -331,7 +334,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
long masterKeyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
|
long masterKeyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
|
||||||
long subKeyId = intent.getLongExtra(EXTRA_SUBKEY_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);
|
String primaryUserID = intent.getStringExtra(EXTRA_USER_ID);
|
||||||
|
|
||||||
Log.d(Constants.TAG,
|
Log.d(Constants.TAG,
|
||||||
@ -373,10 +376,10 @@ public class PassphraseCacheService extends Service {
|
|||||||
Log.e(Constants.TAG, "PassphraseCacheService: Bad request, missing masterKeyId or subKeyId!");
|
Log.e(Constants.TAG, "PassphraseCacheService: Bad request, missing masterKeyId or subKeyId!");
|
||||||
msg.what = MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND;
|
msg.what = MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND;
|
||||||
} else {
|
} else {
|
||||||
String passphrase = getCachedPassphraseImpl(masterKeyId, subKeyId);
|
Passphrase passphrase = getCachedPassphraseImpl(masterKeyId, subKeyId);
|
||||||
msg.what = MSG_PASSPHRASE_CACHE_GET_OKAY;
|
msg.what = MSG_PASSPHRASE_CACHE_GET_OKAY;
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString(EXTRA_PASSPHRASE, passphrase);
|
bundle.putParcelable(EXTRA_PASSPHRASE, passphrase);
|
||||||
msg.setData(bundle);
|
msg.setData(bundle);
|
||||||
}
|
}
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
} catch (ProviderHelper.NotFoundException e) {
|
||||||
@ -412,7 +415,10 @@ public class PassphraseCacheService extends Service {
|
|||||||
* Called when one specific passphrase for keyId timed out
|
* Called when one specific passphrase for keyId timed out
|
||||||
*/
|
*/
|
||||||
private void timeout(Context context, long keyId) {
|
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);
|
mPassphraseCache.remove(keyId);
|
||||||
|
|
||||||
Log.d(Constants.TAG, "PassphraseCacheService Timeout of keyId " + keyId + ", removed from memory!");
|
Log.d(Constants.TAG, "PassphraseCacheService Timeout of keyId " + keyId + ", removed from memory!");
|
||||||
@ -517,9 +523,9 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
public class CachedPassphrase {
|
public class CachedPassphrase {
|
||||||
private String primaryUserID;
|
private String primaryUserID;
|
||||||
private String passphrase;
|
private Passphrase passphrase;
|
||||||
|
|
||||||
public CachedPassphrase(String passphrase, String primaryUserID) {
|
public CachedPassphrase(Passphrase passphrase, String primaryUserID) {
|
||||||
setPassphrase(passphrase);
|
setPassphrase(passphrase);
|
||||||
setPrimaryUserID(primaryUserID);
|
setPrimaryUserID(primaryUserID);
|
||||||
}
|
}
|
||||||
@ -528,7 +534,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
return primaryUserID;
|
return primaryUserID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPassphrase() {
|
public Passphrase getPassphrase() {
|
||||||
return passphrase;
|
return passphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,7 +542,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
this.primaryUserID = primaryUserID;
|
this.primaryUserID = primaryUserID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPassphrase(String passphrase) {
|
public void setPassphrase(Passphrase passphrase) {
|
||||||
this.passphrase = passphrase;
|
this.passphrase = passphrase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import android.os.Parcel;
|
|||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
|
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -296,33 +297,30 @@ public class SaveKeyringParcel implements Parcelable {
|
|||||||
public static class ChangeUnlockParcel implements Parcelable {
|
public static class ChangeUnlockParcel implements Parcelable {
|
||||||
|
|
||||||
// The new passphrase to use
|
// The new passphrase to use
|
||||||
public final String mNewPassphrase;
|
public final Passphrase mNewPassphrase;
|
||||||
// A new pin to use. Must only contain [0-9]+
|
// 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);
|
this(newPassphrase, null);
|
||||||
}
|
}
|
||||||
public ChangeUnlockParcel(String newPassphrase, String newPin) {
|
public ChangeUnlockParcel(Passphrase newPassphrase, Passphrase newPin) {
|
||||||
if (newPassphrase == null && newPin == null) {
|
if (newPassphrase == null && newPin == null) {
|
||||||
throw new RuntimeException("Cannot set both passphrase and pin. THIS IS A BUG!");
|
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;
|
mNewPassphrase = newPassphrase;
|
||||||
mNewPin = newPin;
|
mNewPin = newPin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChangeUnlockParcel(Parcel source) {
|
public ChangeUnlockParcel(Parcel source) {
|
||||||
mNewPassphrase = source.readString();
|
mNewPassphrase = source.readParcelable(Passphrase.class.getClassLoader());
|
||||||
mNewPin = source.readString();
|
mNewPin = source.readParcelable(Passphrase.class.getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToParcel(Parcel destination, int flags) {
|
public void writeToParcel(Parcel destination, int flags) {
|
||||||
destination.writeString(mNewPassphrase);
|
destination.writeParcelable(mNewPassphrase, flags);
|
||||||
destination.writeString(mNewPin);
|
destination.writeParcelable(mNewPin, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -62,6 +62,7 @@ import org.sufficientlysecure.keychain.ui.util.Notify;
|
|||||||
import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
|
import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
|
||||||
import org.sufficientlysecure.keychain.ui.widget.KeySpinner;
|
import org.sufficientlysecure.keychain.ui.widget.KeySpinner;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
import org.sufficientlysecure.keychain.util.Preferences;
|
import org.sufficientlysecure.keychain.util.Preferences;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
@ -318,7 +319,7 @@ public class CertifyKeyFragment extends LoaderFragment
|
|||||||
*/
|
*/
|
||||||
private void initiateCertifying() {
|
private void initiateCertifying() {
|
||||||
// get the user's passphrase for this key (if required)
|
// get the user's passphrase for this key (if required)
|
||||||
String passphrase;
|
Passphrase passphrase;
|
||||||
try {
|
try {
|
||||||
passphrase = PassphraseCacheService.getCachedPassphrase(getActivity(), mSignMasterKeyId, mSignMasterKeyId);
|
passphrase = PassphraseCacheService.getCachedPassphrase(getActivity(), mSignMasterKeyId, mSignMasterKeyId);
|
||||||
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||||
@ -341,7 +342,6 @@ public class CertifyKeyFragment extends LoaderFragment
|
|||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_CODE_PASSPHRASE: {
|
case REQUEST_CODE_PASSPHRASE: {
|
||||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||||
String passphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
|
||||||
startCertifying();
|
startCertifying();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -23,11 +23,20 @@ import android.support.v4.app.FragmentTransaction;
|
|||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class CreateKeyActivity extends BaseActivity {
|
public class CreateKeyActivity extends BaseActivity {
|
||||||
|
|
||||||
public static final String EXTRA_NAME = "name";
|
public static final String EXTRA_NAME = "name";
|
||||||
public static final String EXTRA_EMAIL = "email";
|
public static final String EXTRA_EMAIL = "email";
|
||||||
|
|
||||||
|
public class State {
|
||||||
|
String name;
|
||||||
|
String email;
|
||||||
|
ArrayList<String> additionalEmails;
|
||||||
|
char[] passphrase;
|
||||||
|
}
|
||||||
|
|
||||||
public static enum FragAction {
|
public static enum FragAction {
|
||||||
START,
|
START,
|
||||||
TO_RIGHT,
|
TO_RIGHT,
|
||||||
@ -44,7 +53,7 @@ public class CreateKeyActivity extends BaseActivity {
|
|||||||
getIntent().getStringExtra(EXTRA_NAME),
|
getIntent().getStringExtra(EXTRA_NAME),
|
||||||
getIntent().getStringExtra(EXTRA_EMAIL)
|
getIntent().getStringExtra(EXTRA_EMAIL)
|
||||||
);
|
);
|
||||||
loadFragment(null, frag, FragAction.START);
|
loadFragment(savedInstanceState, frag, FragAction.START);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -85,7 +85,7 @@ public class CreateKeyEmailFragment extends Fragment {
|
|||||||
*/
|
*/
|
||||||
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
|
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
|
||||||
boolean output = true;
|
boolean output = true;
|
||||||
if (editText.getText().toString().length() == 0) {
|
if (editText.getText().length() == 0) {
|
||||||
editText.setError(context.getString(R.string.create_key_empty));
|
editText.setError(context.getString(R.string.create_key_empty));
|
||||||
editText.requestFocus();
|
editText.requestFocus();
|
||||||
output = false;
|
output = false;
|
||||||
|
@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
|
|||||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
|
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
|
||||||
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
|
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
import org.sufficientlysecure.keychain.util.Preferences;
|
import org.sufficientlysecure.keychain.util.Preferences;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -72,7 +73,7 @@ public class CreateKeyFinalFragment extends Fragment {
|
|||||||
String mName;
|
String mName;
|
||||||
String mEmail;
|
String mEmail;
|
||||||
ArrayList<String> mAdditionalEmails;
|
ArrayList<String> mAdditionalEmails;
|
||||||
String mPassphrase;
|
Passphrase mPassphrase;
|
||||||
|
|
||||||
SaveKeyringParcel mSaveKeyringParcel;
|
SaveKeyringParcel mSaveKeyringParcel;
|
||||||
|
|
||||||
@ -81,14 +82,14 @@ public class CreateKeyFinalFragment extends Fragment {
|
|||||||
*/
|
*/
|
||||||
public static CreateKeyFinalFragment newInstance(String name, String email,
|
public static CreateKeyFinalFragment newInstance(String name, String email,
|
||||||
ArrayList<String> additionalEmails,
|
ArrayList<String> additionalEmails,
|
||||||
String passphrase) {
|
Passphrase passphrase) {
|
||||||
CreateKeyFinalFragment frag = new CreateKeyFinalFragment();
|
CreateKeyFinalFragment frag = new CreateKeyFinalFragment();
|
||||||
|
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(ARG_NAME, name);
|
args.putString(ARG_NAME, name);
|
||||||
args.putString(ARG_EMAIL, email);
|
args.putString(ARG_EMAIL, email);
|
||||||
args.putStringArrayList(ARG_ADDITIONAL_EMAILS, additionalEmails);
|
args.putStringArrayList(ARG_ADDITIONAL_EMAILS, additionalEmails);
|
||||||
args.putString(ARG_PASSPHRASE, passphrase);
|
args.putParcelable(ARG_PASSPHRASE, passphrase);
|
||||||
|
|
||||||
frag.setArguments(args);
|
frag.setArguments(args);
|
||||||
|
|
||||||
@ -111,7 +112,7 @@ public class CreateKeyFinalFragment extends Fragment {
|
|||||||
mName = getArguments().getString(ARG_NAME);
|
mName = getArguments().getString(ARG_NAME);
|
||||||
mEmail = getArguments().getString(ARG_EMAIL);
|
mEmail = getArguments().getString(ARG_EMAIL);
|
||||||
mAdditionalEmails = getArguments().getStringArrayList(ARG_ADDITIONAL_EMAILS);
|
mAdditionalEmails = getArguments().getStringArrayList(ARG_ADDITIONAL_EMAILS);
|
||||||
mPassphrase = getArguments().getString(ARG_PASSPHRASE);
|
mPassphrase = getArguments().getParcelable(ARG_PASSPHRASE);
|
||||||
|
|
||||||
// set values
|
// set values
|
||||||
mNameEdit.setText(mName);
|
mNameEdit.setText(mName);
|
||||||
|
@ -68,7 +68,7 @@ public class CreateKeyNameFragment extends Fragment {
|
|||||||
*/
|
*/
|
||||||
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
|
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
|
||||||
boolean output = true;
|
boolean output = true;
|
||||||
if (editText.getText().toString().length() == 0) {
|
if (editText.getText().length() == 0) {
|
||||||
editText.setError(context.getString(R.string.create_key_empty));
|
editText.setError(context.getString(R.string.create_key_empty));
|
||||||
editText.requestFocus();
|
editText.requestFocus();
|
||||||
output = false;
|
output = false;
|
||||||
@ -79,19 +79,6 @@ public class CreateKeyNameFragment extends Fragment {
|
|||||||
return output;
|
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
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.create_key_name_fragment, container, false);
|
View view = inflater.inflate(R.layout.create_key_name_fragment, container, false);
|
||||||
|
@ -34,6 +34,7 @@ import android.widget.EditText;
|
|||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
|
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
|
||||||
import org.sufficientlysecure.keychain.ui.widget.PassphraseEditText;
|
import org.sufficientlysecure.keychain.ui.widget.PassphraseEditText;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ public class CreateKeyPassphraseFragment extends Fragment {
|
|||||||
*/
|
*/
|
||||||
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
|
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
|
||||||
boolean output = true;
|
boolean output = true;
|
||||||
if (editText.getText().toString().length() == 0) {
|
if (editText.getText().length() == 0) {
|
||||||
editText.setError(context.getString(R.string.create_key_empty));
|
editText.setError(context.getString(R.string.create_key_empty));
|
||||||
editText.requestFocus();
|
editText.requestFocus();
|
||||||
output = false;
|
output = false;
|
||||||
@ -95,11 +96,13 @@ public class CreateKeyPassphraseFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean areEditTextsEqual(Context context, EditText editText1, EditText editText2) {
|
private static boolean areEditTextsEqual(Context context, EditText editText1, EditText editText2) {
|
||||||
boolean output = true;
|
Passphrase p1 = new Passphrase(editText1);
|
||||||
if (!editText1.getText().toString().equals(editText2.getText().toString())) {
|
Passphrase p2 = new Passphrase(editText2);
|
||||||
|
boolean output = (p1.equals(p2));
|
||||||
|
|
||||||
|
if (!output) {
|
||||||
editText2.setError(context.getString(R.string.create_key_passphrases_not_equal));
|
editText2.setError(context.getString(R.string.create_key_passphrases_not_equal));
|
||||||
editText2.requestFocus();
|
editText2.requestFocus();
|
||||||
output = false;
|
|
||||||
} else {
|
} else {
|
||||||
editText2.setError(null);
|
editText2.setError(null);
|
||||||
}
|
}
|
||||||
@ -171,7 +174,7 @@ public class CreateKeyPassphraseFragment extends Fragment {
|
|||||||
mName,
|
mName,
|
||||||
mEmail,
|
mEmail,
|
||||||
mAdditionalEmails,
|
mAdditionalEmails,
|
||||||
mPassphraseEdit.getText().toString()
|
new Passphrase(mPassphraseEdit.getText())
|
||||||
);
|
);
|
||||||
|
|
||||||
hideKeyboard();
|
hideKeyboard();
|
||||||
|
@ -191,7 +191,7 @@ public class DecryptFilesFragment extends DecryptFragment {
|
|||||||
data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal());
|
data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal());
|
||||||
data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri);
|
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);
|
data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
|
||||||
|
|
||||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||||
@ -265,7 +265,7 @@ public class DecryptFilesFragment extends DecryptFragment {
|
|||||||
data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal());
|
data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal());
|
||||||
data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri);
|
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);
|
data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
|
||||||
|
|
||||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||||
@ -341,7 +341,7 @@ public class DecryptFilesFragment extends DecryptFragment {
|
|||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_CODE_PASSPHRASE: {
|
case REQUEST_CODE_PASSPHRASE: {
|
||||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||||
mPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
mPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
||||||
decryptOriginalFilename();
|
decryptOriginalFilename();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -32,6 +32,7 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
|
|||||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
public abstract class DecryptFragment extends Fragment {
|
public abstract class DecryptFragment extends Fragment {
|
||||||
private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006;
|
private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006;
|
||||||
@ -57,7 +58,7 @@ public abstract class DecryptFragment extends Fragment {
|
|||||||
|
|
||||||
|
|
||||||
// State
|
// State
|
||||||
protected String mPassphrase;
|
protected Passphrase mPassphrase;
|
||||||
protected byte[] mNfcDecryptedSessionKey;
|
protected byte[] mNfcDecryptedSessionKey;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -100,7 +101,7 @@ public abstract class DecryptFragment extends Fragment {
|
|||||||
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
|
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
|
// build PendingIntent for Yubikey NFC operations
|
||||||
Intent intent = new Intent(getActivity(), NfcActivity.class);
|
Intent intent = new Intent(getActivity(), NfcActivity.class);
|
||||||
intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY);
|
intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY);
|
||||||
|
@ -161,7 +161,7 @@ public class DecryptTextFragment extends DecryptFragment {
|
|||||||
// data
|
// data
|
||||||
data.putInt(KeychainIntentService.TARGET, IOType.BYTES.ordinal());
|
data.putInt(KeychainIntentService.TARGET, IOType.BYTES.ordinal());
|
||||||
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, mCiphertext.getBytes());
|
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);
|
data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
|
||||||
|
|
||||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||||
@ -247,7 +247,7 @@ public class DecryptTextFragment extends DecryptFragment {
|
|||||||
|
|
||||||
case REQUEST_CODE_PASSPHRASE: {
|
case REQUEST_CODE_PASSPHRASE: {
|
||||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||||
mPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
mPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
||||||
decryptStart();
|
decryptStart();
|
||||||
} else {
|
} else {
|
||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
|
@ -67,6 +67,7 @@ import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment;
|
|||||||
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
|
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
public class EditKeyFragment extends LoaderFragment implements
|
public class EditKeyFragment extends LoaderFragment implements
|
||||||
LoaderManager.LoaderCallbacks<Cursor> {
|
LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
@ -100,7 +101,7 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
private SaveKeyringParcel mSaveKeyringParcel;
|
private SaveKeyringParcel mSaveKeyringParcel;
|
||||||
|
|
||||||
private String mPrimaryUserId;
|
private String mPrimaryUserId;
|
||||||
private String mCurrentPassphrase;
|
private Passphrase mCurrentPassphrase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new instance of this fragment
|
* Creates new instance of this fragment
|
||||||
@ -267,7 +268,7 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_CODE_PASSPHRASE: {
|
case REQUEST_CODE_PASSPHRASE: {
|
||||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||||
mCurrentPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
mCurrentPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
||||||
// Prepare the loaders. Either re-connect with an existing ones,
|
// Prepare the loaders. Either re-connect with an existing ones,
|
||||||
// or start new ones.
|
// or start new ones.
|
||||||
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditKeyFragment.this);
|
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditKeyFragment.this);
|
||||||
@ -386,7 +387,7 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
|
|
||||||
// cache new returned passphrase!
|
// cache new returned passphrase!
|
||||||
mSaveKeyringParcel.mNewUnlock = new ChangeUnlockParcel(
|
mSaveKeyringParcel.mNewUnlock = new ChangeUnlockParcel(
|
||||||
data.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
|
(Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -593,7 +594,7 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveInDatabase(String passphrase) {
|
private void saveInDatabase(Passphrase passphrase) {
|
||||||
Log.d(Constants.TAG, "mSaveKeyringParcel:\n" + mSaveKeyringParcel.toString());
|
Log.d(Constants.TAG, "mSaveKeyringParcel:\n" + mSaveKeyringParcel.toString());
|
||||||
|
|
||||||
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
|
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
|
||||||
@ -640,7 +641,7 @@ public class EditKeyFragment extends LoaderFragment implements
|
|||||||
|
|
||||||
// fill values for this action
|
// fill values for this action
|
||||||
Bundle data = new Bundle();
|
Bundle data = new Bundle();
|
||||||
data.putString(KeychainIntentService.EDIT_KEYRING_PASSPHRASE, passphrase);
|
data.putParcelable(KeychainIntentService.EDIT_KEYRING_PASSPHRASE, passphrase);
|
||||||
data.putParcelable(KeychainIntentService.EDIT_KEYRING_PARCEL, mSaveKeyringParcel);
|
data.putParcelable(KeychainIntentService.EDIT_KEYRING_PARCEL, mSaveKeyringParcel);
|
||||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
|
|||||||
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
|
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
|
||||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ public abstract class EncryptActivity extends BaseActivity {
|
|||||||
public static final int REQUEST_CODE_NFC = 0x00008002;
|
public static final int REQUEST_CODE_NFC = 0x00008002;
|
||||||
|
|
||||||
// For NFC data
|
// For NFC data
|
||||||
protected String mSigningKeyPassphrase = null;
|
protected Passphrase mSigningKeyPassphrase = null;
|
||||||
protected Date mNfcTimestamp = null;
|
protected Date mNfcTimestamp = null;
|
||||||
protected byte[] mNfcHash = null;
|
protected byte[] mNfcHash = null;
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ public abstract class EncryptActivity extends BaseActivity {
|
|||||||
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
|
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void startNfcSign(long keyId, String pin, byte[] hashToSign, int hashAlgo) {
|
protected void startNfcSign(long keyId, Passphrase pin, byte[] hashToSign, int hashAlgo) {
|
||||||
// build PendingIntent for Yubikey NFC operations
|
// build PendingIntent for Yubikey NFC operations
|
||||||
Intent intent = new Intent(this, NfcActivity.class);
|
Intent intent = new Intent(this, NfcActivity.class);
|
||||||
intent.setAction(NfcActivity.ACTION_SIGN_HASH);
|
intent.setAction(NfcActivity.ACTION_SIGN_HASH);
|
||||||
@ -84,7 +85,7 @@ public abstract class EncryptActivity extends BaseActivity {
|
|||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_CODE_PASSPHRASE: {
|
case REQUEST_CODE_PASSPHRASE: {
|
||||||
if (resultCode == RESULT_OK && data != null) {
|
if (resultCode == RESULT_OK && data != null) {
|
||||||
mSigningKeyPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
mSigningKeyPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
||||||
startEncrypt();
|
startEncrypt();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ package org.sufficientlysecure.keychain.ui;
|
|||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public interface EncryptActivityInterface {
|
public interface EncryptActivityInterface {
|
||||||
@ -39,7 +41,7 @@ public interface EncryptActivityInterface {
|
|||||||
public void setEncryptionKeys(long[] encryptionKeys);
|
public void setEncryptionKeys(long[] encryptionKeys);
|
||||||
public void setEncryptionUsers(String[] encryptionUsers);
|
public void setEncryptionUsers(String[] encryptionUsers);
|
||||||
|
|
||||||
public void setPassphrase(String passphrase);
|
public void setPassphrase(Passphrase passphrase);
|
||||||
|
|
||||||
// ArrayList on purpose as only those are parcelable
|
// ArrayList on purpose as only those are parcelable
|
||||||
public ArrayList<Uri> getInputUris();
|
public ArrayList<Uri> getInputUris();
|
||||||
|
@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
|
|||||||
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
|
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
import org.sufficientlysecure.keychain.util.ShareHelper;
|
import org.sufficientlysecure.keychain.util.ShareHelper;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -72,7 +73,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
|
|||||||
private long mEncryptionKeyIds[] = null;
|
private long mEncryptionKeyIds[] = null;
|
||||||
private String mEncryptionUserIds[] = null;
|
private String mEncryptionUserIds[] = null;
|
||||||
private long mSigningKeyId = Constants.key.none;
|
private long mSigningKeyId = Constants.key.none;
|
||||||
private String mPassphrase = "";
|
private Passphrase mPassphrase = new Passphrase();
|
||||||
|
|
||||||
private ArrayList<Uri> mInputUris;
|
private ArrayList<Uri> mInputUris;
|
||||||
private ArrayList<Uri> mOutputUris;
|
private ArrayList<Uri> mOutputUris;
|
||||||
@ -136,7 +137,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPassphrase(String passphrase) {
|
public void setPassphrase(Passphrase passphrase) {
|
||||||
mPassphrase = passphrase;
|
mPassphrase = passphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,8 +244,8 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
|
|||||||
|
|
||||||
if (isModeSymmetric()) {
|
if (isModeSymmetric()) {
|
||||||
Log.d(Constants.TAG, "Symmetric encryption enabled!");
|
Log.d(Constants.TAG, "Symmetric encryption enabled!");
|
||||||
String passphrase = mPassphrase;
|
Passphrase passphrase = mPassphrase;
|
||||||
if (passphrase.length() == 0) {
|
if (passphrase.isEmpty()) {
|
||||||
passphrase = null;
|
passphrase = null;
|
||||||
}
|
}
|
||||||
data.setSymmetricPassphrase(passphrase);
|
data.setSymmetricPassphrase(passphrase);
|
||||||
|
@ -28,6 +28,7 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
public class EncryptSymmetricFragment extends Fragment implements EncryptActivityInterface.UpdateListener {
|
public class EncryptSymmetricFragment extends Fragment implements EncryptActivityInterface.UpdateListener {
|
||||||
|
|
||||||
@ -67,8 +68,13 @@ public class EncryptSymmetricFragment extends Fragment implements EncryptActivit
|
|||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable s) {
|
public void afterTextChanged(Editable s) {
|
||||||
// update passphrase in EncryptActivity
|
// update passphrase in EncryptActivity
|
||||||
if (mPassphrase.getText().toString().equals(mPassphraseAgain.getText().toString())) {
|
Passphrase p1 = new Passphrase(mPassphrase.getText());
|
||||||
mEncryptInterface.setPassphrase(s.toString());
|
Passphrase p2 = new Passphrase(mPassphraseAgain.getText());
|
||||||
|
boolean passesEquals = (p1.equals(p2));
|
||||||
|
p1.removeFromMemory();
|
||||||
|
p2.removeFromMemory();
|
||||||
|
if (passesEquals) {
|
||||||
|
mEncryptInterface.setPassphrase(new Passphrase(mPassphrase.getText()));
|
||||||
} else {
|
} else {
|
||||||
mEncryptInterface.setPassphrase(null);
|
mEncryptInterface.setPassphrase(null);
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.pgp.PgpConstants;
|
|||||||
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
|
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
import org.sufficientlysecure.keychain.util.ShareHelper;
|
import org.sufficientlysecure.keychain.util.ShareHelper;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -70,7 +71,7 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
|
|||||||
private String mEncryptionUserIds[] = null;
|
private String mEncryptionUserIds[] = null;
|
||||||
// TODO Constants.key.none? What's wrong with a null value?
|
// TODO Constants.key.none? What's wrong with a null value?
|
||||||
private long mSigningKeyId = Constants.key.none;
|
private long mSigningKeyId = Constants.key.none;
|
||||||
private String mPassphrase = "";
|
private Passphrase mPassphrase = new Passphrase();
|
||||||
|
|
||||||
private ArrayList<Uri> mInputUris;
|
private ArrayList<Uri> mInputUris;
|
||||||
private ArrayList<Uri> mOutputUris;
|
private ArrayList<Uri> mOutputUris;
|
||||||
@ -134,7 +135,8 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPassphrase(String passphrase) {
|
public void setPassphrase(Passphrase passphrase) {
|
||||||
|
mPassphrase.removeFromMemory();
|
||||||
mPassphrase = passphrase;
|
mPassphrase = passphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,8 +225,8 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
|
|||||||
|
|
||||||
if (isModeSymmetric()) {
|
if (isModeSymmetric()) {
|
||||||
Log.d(Constants.TAG, "Symmetric encryption enabled!");
|
Log.d(Constants.TAG, "Symmetric encryption enabled!");
|
||||||
String passphrase = mPassphrase;
|
Passphrase passphrase = mPassphrase;
|
||||||
if (passphrase.length() == 0) {
|
if (passphrase.isEmpty()) {
|
||||||
passphrase = null;
|
passphrase = null;
|
||||||
}
|
}
|
||||||
data.setSymmetricPassphrase(passphrase);
|
data.setSymmetricPassphrase(passphrase);
|
||||||
|
@ -55,6 +55,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
|||||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||||
import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
|
import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
import org.sufficientlysecure.keychain.util.Preferences;
|
import org.sufficientlysecure.keychain.util.Preferences;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -318,7 +319,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
|||||||
positive.setOnClickListener(new View.OnClickListener() {
|
positive.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
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
|
// Early breakout if we are dealing with a symmetric key
|
||||||
if (mSecretRing == null) {
|
if (mSecretRing == null) {
|
||||||
@ -395,7 +396,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.
|
// any indication this isn't needed anymore, don't do it.
|
||||||
if (mIsCancelled || getActivity() == null) {
|
if (mIsCancelled || getActivity() == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.Constants;
|
|||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.ui.widget.PassphraseEditText;
|
import org.sufficientlysecure.keychain.ui.widget.PassphraseEditText;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||||
|
|
||||||
public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
|
public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
|
||||||
private static final String ARG_MESSENGER = "messenger";
|
private static final String ARG_MESSENGER = "messenger";
|
||||||
@ -67,12 +68,12 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
* @param messenger to communicate back after setting the passphrase
|
* @param messenger to communicate back after setting the passphrase
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static SetPassphraseDialogFragment newInstance(Messenger messenger, String oldPassphrase, int title) {
|
public static SetPassphraseDialogFragment newInstance(Messenger messenger, Passphrase oldPassphrase, int title) {
|
||||||
SetPassphraseDialogFragment frag = new SetPassphraseDialogFragment();
|
SetPassphraseDialogFragment frag = new SetPassphraseDialogFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putInt(ARG_TITLE, title);
|
args.putInt(ARG_TITLE, title);
|
||||||
args.putParcelable(ARG_MESSENGER, messenger);
|
args.putParcelable(ARG_MESSENGER, messenger);
|
||||||
args.putString(ARG_OLD_PASSPHRASE, oldPassphrase);
|
args.putParcelable(ARG_OLD_PASSPHRASE, oldPassphrase);
|
||||||
|
|
||||||
frag.setArguments(args);
|
frag.setArguments(args);
|
||||||
|
|
||||||
@ -88,7 +89,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
|
|
||||||
int title = getArguments().getInt(ARG_TITLE);
|
int title = getArguments().getInt(ARG_TITLE);
|
||||||
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
|
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
|
||||||
String oldPassphrase = getArguments().getString(ARG_OLD_PASSPHRASE);
|
Passphrase oldPassphrase = getArguments().getParcelable(ARG_OLD_PASSPHRASE);
|
||||||
|
|
||||||
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
|
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
|
||||||
|
|
||||||
@ -103,7 +104,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
mNoPassphraseCheckBox = (CheckBox) view.findViewById(R.id.passphrase_no_passphrase);
|
mNoPassphraseCheckBox = (CheckBox) view.findViewById(R.id.passphrase_no_passphrase);
|
||||||
|
|
||||||
|
|
||||||
if (TextUtils.isEmpty(oldPassphrase)) {
|
if (oldPassphrase.isEmpty()) {
|
||||||
mNoPassphraseCheckBox.setChecked(true);
|
mNoPassphraseCheckBox.setChecked(true);
|
||||||
mPassphraseEditText.setEnabled(false);
|
mPassphraseEditText.setEnabled(false);
|
||||||
mPassphraseAgainEditText.setEnabled(false);
|
mPassphraseAgainEditText.setEnabled(false);
|
||||||
@ -123,12 +124,12 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
dismiss();
|
dismiss();
|
||||||
|
|
||||||
String passphrase1;
|
Passphrase passphrase1 = new Passphrase();
|
||||||
if (mNoPassphraseCheckBox.isChecked()) {
|
if (mNoPassphraseCheckBox.isChecked()) {
|
||||||
passphrase1 = "";
|
passphrase1.setEmpty();
|
||||||
} else {
|
} else {
|
||||||
passphrase1 = mPassphraseEditText.getText().toString();
|
passphrase1 = new Passphrase(mPassphraseEditText);
|
||||||
String passphrase2 = mPassphraseAgainEditText.getText().toString();
|
Passphrase passphrase2 = new Passphrase(mPassphraseAgainEditText);
|
||||||
if (!passphrase1.equals(passphrase2)) {
|
if (!passphrase1.equals(passphrase2)) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
activity,
|
activity,
|
||||||
@ -139,7 +140,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (passphrase1.equals("")) {
|
if (passphrase1.isEmpty()) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
activity,
|
activity,
|
||||||
getString(R.string.error_message,
|
getString(R.string.error_message,
|
||||||
@ -152,7 +153,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
|||||||
|
|
||||||
// return resulting data back to activity
|
// return resulting data back to activity
|
||||||
Bundle data = new Bundle();
|
Bundle data = new Bundle();
|
||||||
data.putString(MESSAGE_NEW_PASSPHRASE, passphrase1);
|
data.putParcelable(MESSAGE_NEW_PASSPHRASE, passphrase1);
|
||||||
|
|
||||||
sendMessageToHandler(MESSAGE_OKAY, data);
|
sendMessageToHandler(MESSAGE_OKAY, data);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
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()
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Passphrase(EditText editText) {
|
||||||
|
this(editText.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Passphrase(String passphrase) {
|
||||||
|
mPassphrase = passphrase.toCharArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Passphrase() {
|
||||||
|
setEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public char[] getCharArray() {
|
||||||
|
return mPassphrase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return (mPassphrase.length == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmpty() {
|
||||||
|
removeFromMemory();
|
||||||
|
mPassphrase = new char[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeFromMemory() {
|
||||||
|
if (mPassphrase != null) {
|
||||||
|
Arrays.fill(mPassphrase, ' ');
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user