wrapped-key-ring: more work on passphrase caching and certification

This commit is contained in:
Vincent Breitmoser
2014-05-04 16:59:20 +02:00
parent 8cf0638f54
commit cd8af25ba7
4 changed files with 58 additions and 100 deletions

View File

@@ -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());
} }

View File

@@ -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;
if (masterKeyId != Constants.key.symmetric) {
try { try {
masterKeyId = new ProviderHelper(this).getMasterKeyId( Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + keyId);
CachedSecretKeyRing key = new ProviderHelper(this).getCachedSecretKeyRing(
KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId))); KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId)));
} catch (ProviderHelper.NotFoundException e) { // no passphrase needed? just add empty string and return it, then
return null; if (!key.hasPassphrase()) {
}
}
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 // set it again to reset the cache life cycle
Log.d(TAG, "Cache passphrase again when getting it!"); Log.d(TAG, "Cache passphrase again when getting it!");
addCachedPassphrase(this, masterKeyId, cachedPassphrase); addCachedPassphrase(this, keyId, cachedPassphrase);
return 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;
} }
/** /**

View File

@@ -226,28 +226,7 @@ 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);
// if we have already signed this key, dont bother doing it again
boolean alreadySigned = false;
/* todo: reconsider this at a later point when certs are in the db
@SuppressWarnings("unchecked")
Iterator<PGPSignature> itr = pubring.getPublicKey(mPubKeyId).getSignatures();
while (itr.hasNext()) {
PGPSignature sig = itr.next();
if (sig.getKeyID() == mMasterKeyId) {
alreadySigned = true;
break;
}
}
*/
if (!alreadySigned) {
/*
* get the user's passphrase for this key (if required)
*/
String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId); String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId);
if (passphrase == null) { if (passphrase == null) {
PassphraseDialogFragment.show(this, mMasterKeyId, PassphraseDialogFragment.show(this, mMasterKeyId,
@@ -264,16 +243,6 @@ public class CertifyKeyActivity extends ActionBarActivity implements
} else { } else {
startSigning(); 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);
}
} }
/** /**

View File

@@ -101,9 +101,13 @@ 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 {
if (new ProviderHelper(context).getCachedSecretKeyRing(secretKeyId).hasPassphrase()) {
throw new PgpGeneralException("No passphrase! No passphrase dialog needed!"); throw new PgpGeneralException("No passphrase! No passphrase dialog needed!");
} }
} catch(ProviderHelper.NotFoundException e) {
throw new PgpGeneralException("Error: Key not found!", e);
}
} }
PassphraseDialogFragment frag = new PassphraseDialogFragment(); PassphraseDialogFragment frag = new PassphraseDialogFragment();