wrapped-key-ring: more work on passphrase caching and certification
This commit is contained in:
@@ -81,23 +81,6 @@ public class PgpKeyHelper {
|
|||||||
return getExpiryDate(key.getPublicKey());
|
return getExpiryDate(key.getPublicKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Deprecated
|
|
||||||
public static PGPSecretKey getKeyNum(PGPSecretKeyRing keyRing, long num) {
|
|
||||||
long cnt = 0;
|
|
||||||
if (keyRing == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
|
|
||||||
if (cnt == num) {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getKeyUsage(PGPSecretKey key) {
|
public static int getKeyUsage(PGPSecretKey key) {
|
||||||
return getKeyUsage(key.getPublicKey());
|
return getKeyUsage(key.getPublicKey());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
|||||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
@@ -163,38 +164,46 @@ public class PassphraseCacheService extends Service {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private String getCachedPassphraseImpl(long keyId) {
|
private String getCachedPassphraseImpl(long keyId) {
|
||||||
Log.d(TAG, "getCachedPassphraseImpl() get masterKeyId for " + keyId);
|
// passphrase for symmetric encryption?
|
||||||
|
if (keyId == Constants.key.symmetric) {
|
||||||
|
Log.d(TAG, "getCachedPassphraseImpl() for symmetric encryption");
|
||||||
|
String cachedPassphrase = mPassphraseCache.get(Constants.key.symmetric);
|
||||||
|
if (cachedPassphrase == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
addCachedPassphrase(this, Constants.key.symmetric, cachedPassphrase);
|
||||||
|
return cachedPassphrase;
|
||||||
|
}
|
||||||
|
|
||||||
// try to get master key id which is used as an identifier for cached passphrases
|
// try to get master key id which is used as an identifier for cached passphrases
|
||||||
long masterKeyId = keyId;
|
try {
|
||||||
if (masterKeyId != Constants.key.symmetric) {
|
Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + keyId);
|
||||||
try {
|
CachedSecretKeyRing key = new ProviderHelper(this).getCachedSecretKeyRing(
|
||||||
masterKeyId = new ProviderHelper(this).getMasterKeyId(
|
KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId)));
|
||||||
KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId)));
|
// no passphrase needed? just add empty string and return it, then
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
if (!key.hasPassphrase()) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + masterKeyId);
|
|
||||||
|
|
||||||
// get cached passphrase
|
|
||||||
String cachedPassphrase = mPassphraseCache.get(masterKeyId);
|
|
||||||
if (cachedPassphrase == null) {
|
|
||||||
// if key has no passphrase -> cache and return empty passphrase
|
|
||||||
if (!hasPassphrase(this, masterKeyId)) {
|
|
||||||
Log.d(Constants.TAG, "Key has no passphrase! Caches and returns empty passphrase!");
|
Log.d(Constants.TAG, "Key has no passphrase! Caches and returns empty passphrase!");
|
||||||
|
|
||||||
addCachedPassphrase(this, masterKeyId, "");
|
addCachedPassphrase(this, keyId, "");
|
||||||
return "";
|
return "";
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
// get cached passphrase
|
||||||
|
String cachedPassphrase = mPassphraseCache.get(keyId);
|
||||||
|
if (cachedPassphrase == null) {
|
||||||
|
// this is an error
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// set it again to reset the cache life cycle
|
|
||||||
Log.d(TAG, "Cache passphrase again when getting it!");
|
|
||||||
addCachedPassphrase(this, masterKeyId, cachedPassphrase);
|
|
||||||
|
|
||||||
return cachedPassphrase;
|
// set it again to reset the cache life cycle
|
||||||
|
Log.d(TAG, "Cache passphrase again when getting it!");
|
||||||
|
addCachedPassphrase(this, keyId, cachedPassphrase);
|
||||||
|
return cachedPassphrase;
|
||||||
|
|
||||||
|
} catch (ProviderHelper.NotFoundException e) {
|
||||||
|
Log.e(TAG, "Passphrase for unknown key was requested!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@@ -230,16 +239,9 @@ public class PassphraseCacheService extends Service {
|
|||||||
* @return true if it has a passphrase
|
* @return true if it has a passphrase
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static boolean hasPassphrase(Context context, long secretKeyId) {
|
public static boolean hasPassphrase(Context context, long secretKeyId)
|
||||||
// check if the key has no passphrase
|
throws ProviderHelper.NotFoundException {
|
||||||
try {
|
return new ProviderHelper(context).getCachedSecretKeyRing(secretKeyId).hasPassphrase();
|
||||||
PGPSecretKeyRing secRing = new ProviderHelper(context).getPGPSecretKeyRing(secretKeyId);
|
|
||||||
return hasPassphrase(secRing);
|
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
|
||||||
Log.e(Constants.TAG, "key not found!", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -226,53 +226,22 @@ public class CertifyKeyActivity extends ActionBarActivity implements
|
|||||||
* handles the UI bits of the signing process on the UI thread
|
* handles the UI bits of the signing process on the UI thread
|
||||||
*/
|
*/
|
||||||
private void initiateSigning() {
|
private void initiateSigning() {
|
||||||
try {
|
// get the user's passphrase for this key (if required)
|
||||||
PGPPublicKeyRing pubring = new ProviderHelper(this).getPGPPublicKeyRing(mPubKeyId);
|
String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId);
|
||||||
|
if (passphrase == null) {
|
||||||
// if we have already signed this key, dont bother doing it again
|
PassphraseDialogFragment.show(this, mMasterKeyId,
|
||||||
boolean alreadySigned = false;
|
new Handler() {
|
||||||
|
@Override
|
||||||
/* todo: reconsider this at a later point when certs are in the db
|
public void handleMessage(Message message) {
|
||||||
@SuppressWarnings("unchecked")
|
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
|
||||||
Iterator<PGPSignature> itr = pubring.getPublicKey(mPubKeyId).getSignatures();
|
startSigning();
|
||||||
while (itr.hasNext()) {
|
}
|
||||||
PGPSignature sig = itr.next();
|
}
|
||||||
if (sig.getKeyID() == mMasterKeyId) {
|
});
|
||||||
alreadySigned = true;
|
// bail out; need to wait until the user has entered the passphrase before trying again
|
||||||
break;
|
return;
|
||||||
}
|
} else {
|
||||||
}
|
startSigning();
|
||||||
*/
|
|
||||||
|
|
||||||
if (!alreadySigned) {
|
|
||||||
/*
|
|
||||||
* get the user's passphrase for this key (if required)
|
|
||||||
*/
|
|
||||||
String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId);
|
|
||||||
if (passphrase == null) {
|
|
||||||
PassphraseDialogFragment.show(this, mMasterKeyId,
|
|
||||||
new Handler() {
|
|
||||||
@Override
|
|
||||||
public void handleMessage(Message message) {
|
|
||||||
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
|
|
||||||
startSigning();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// bail out; need to wait until the user has entered the passphrase before trying again
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
startSigning();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
AppMsg.makeText(this, R.string.key_has_already_been_certified, AppMsg.STYLE_ALERT)
|
|
||||||
.show();
|
|
||||||
|
|
||||||
setResult(RESULT_CANCELED);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
|
||||||
Log.e(Constants.TAG, "key not found!", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,8 +101,12 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
|||||||
long secretKeyId) throws PgpGeneralException {
|
long secretKeyId) throws PgpGeneralException {
|
||||||
// check if secret key has a passphrase
|
// check if secret key has a passphrase
|
||||||
if (!(secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none)) {
|
if (!(secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none)) {
|
||||||
if (!PassphraseCacheService.hasPassphrase(context, secretKeyId)) {
|
try {
|
||||||
throw new PgpGeneralException("No passphrase! No passphrase dialog needed!");
|
if (new ProviderHelper(context).getCachedSecretKeyRing(secretKeyId).hasPassphrase()) {
|
||||||
|
throw new PgpGeneralException("No passphrase! No passphrase dialog needed!");
|
||||||
|
}
|
||||||
|
} catch(ProviderHelper.NotFoundException e) {
|
||||||
|
throw new PgpGeneralException("Error: Key not found!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user