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());
}
@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) {
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.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.Log;
@ -163,38 +164,46 @@ public class PassphraseCacheService extends Service {
* @return
*/
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
long masterKeyId = keyId;
if (masterKeyId != Constants.key.symmetric) {
try {
masterKeyId = new ProviderHelper(this).getMasterKeyId(
KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId)));
} catch (ProviderHelper.NotFoundException e) {
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)) {
try {
Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + keyId);
CachedSecretKeyRing key = new ProviderHelper(this).getCachedSecretKeyRing(
KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(Long.toString(keyId)));
// no passphrase needed? just add empty string and return it, then
if (!key.hasPassphrase()) {
Log.d(Constants.TAG, "Key has no passphrase! Caches and returns empty passphrase!");
addCachedPassphrase(this, masterKeyId, "");
addCachedPassphrase(this, keyId, "");
return "";
} else {
}
// get cached passphrase
String cachedPassphrase = mPassphraseCache.get(keyId);
if (cachedPassphrase == null) {
// this is an error
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
@ -230,16 +239,9 @@ public class PassphraseCacheService extends Service {
* @return true if it has a passphrase
*/
@Deprecated
public static boolean hasPassphrase(Context context, long secretKeyId) {
// check if the key has no passphrase
try {
PGPSecretKeyRing secRing = new ProviderHelper(context).getPGPSecretKeyRing(secretKeyId);
return hasPassphrase(secRing);
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
}
return true;
public static boolean hasPassphrase(Context context, long secretKeyId)
throws ProviderHelper.NotFoundException {
return new ProviderHelper(context).getCachedSecretKeyRing(secretKeyId).hasPassphrase();
}
/**

View File

@ -226,53 +226,22 @@ public class CertifyKeyActivity extends ActionBarActivity implements
* handles the UI bits of the signing process on the UI thread
*/
private void initiateSigning() {
try {
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);
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);
// 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();
}
}

View File

@ -101,8 +101,12 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
long secretKeyId) throws PgpGeneralException {
// check if secret key has a passphrase
if (!(secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none)) {
if (!PassphraseCacheService.hasPassphrase(context, secretKeyId)) {
throw new PgpGeneralException("No passphrase! No passphrase dialog needed!");
try {
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);
}
}