mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-11 11:35:07 -05:00
private keys without master keys and some fixes for things which broke along the way
This commit is contained in:
parent
99122fa8d9
commit
115d34ba0e
@ -24,12 +24,16 @@ import java.util.Locale;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
||||
import org.spongycastle.openpgp.PGPPublicKey;
|
||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.spongycastle.openpgp.PGPSignature;
|
||||
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
||||
import org.spongycastle.openpgp.PGPException;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||
@ -76,6 +80,22 @@ public class PgpHelper {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
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;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Vector<PGPPublicKey> getEncryptKeys(PGPPublicKeyRing keyRing) {
|
||||
Vector<PGPPublicKey> encryptKeys = new Vector<PGPPublicKey>();
|
||||
@ -144,7 +164,17 @@ public class PgpHelper {
|
||||
for (int i = 0; i < signingKeys.size(); ++i) {
|
||||
PGPSecretKey key = signingKeys.get(i);
|
||||
if (key.isMasterKey()) {
|
||||
masterKey = key;
|
||||
try {
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
||||
.setProvider(PgpMain.BOUNCY_CASTLE_PROVIDER_NAME).build(new char[] {});
|
||||
PGPPrivateKey testKey = key.extractPrivateKey(
|
||||
keyDecryptor);
|
||||
if (testKey != null) {
|
||||
masterKey = key;
|
||||
}
|
||||
} catch (PGPException e) {
|
||||
// all good if this fails, we likely didn't use the right password
|
||||
}
|
||||
} else {
|
||||
usableKeys.add(key);
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
|
||||
import org.sufficientlysecure.keychain.util.Primes;
|
||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||
import org.sufficientlysecure.keychain.util.KeyServer.AddKeyException;
|
||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
|
||||
import android.content.Context;
|
||||
@ -483,25 +484,28 @@ public class PgpMain {
|
||||
* @param keyring
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static int storeKeyRingInCache(Context context, PGPKeyRing keyring) {
|
||||
int status = Integer.MIN_VALUE; // out of bounds value (Id.return_value.*)
|
||||
try {
|
||||
if (keyring instanceof PGPSecretKeyRing) {
|
||||
PGPSecretKeyRing secretKeyRing = (PGPSecretKeyRing) keyring;
|
||||
boolean save = true;
|
||||
try {
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
||||
.setProvider(BOUNCY_CASTLE_PROVIDER_NAME).build(new char[] {});
|
||||
PGPPrivateKey testKey = secretKeyRing.getSecretKey().extractPrivateKey(
|
||||
keyDecryptor);
|
||||
if (testKey == null) {
|
||||
// this is bad, something is very wrong... likely a --export-secret-subkeys
|
||||
// export
|
||||
save = false;
|
||||
status = Id.return_value.bad;
|
||||
|
||||
for (PGPSecretKey testSecretKey : new IterableIterator<PGPSecretKey>(secretKeyRing.getSecretKeys())) {
|
||||
try {
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
||||
.setProvider(BOUNCY_CASTLE_PROVIDER_NAME).build(new char[] {});
|
||||
PGPPrivateKey testKey = testSecretKey.extractPrivateKey(
|
||||
keyDecryptor);
|
||||
if (testKey == null && !testSecretKey.isMasterKey()) {
|
||||
// this is bad, something is very wrong...
|
||||
save = false;
|
||||
status = Id.return_value.bad;
|
||||
}
|
||||
} catch (PGPException e) {
|
||||
// all good if this fails, we likely didn't use the right password
|
||||
}
|
||||
} catch (PGPException e) {
|
||||
// all good if this fails, we likely didn't use the right password
|
||||
}
|
||||
|
||||
if (save) {
|
||||
|
@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.ui.dialog;
|
||||
import org.spongycastle.openpgp.PGPException;
|
||||
import org.spongycastle.openpgp.PGPPrivateKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
@ -63,6 +64,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
|
||||
private Messenger mMessenger;
|
||||
private EditText mPassphraseEditText;
|
||||
private boolean canKB;
|
||||
|
||||
/**
|
||||
* Creates new instance of this dialog fragment
|
||||
@ -137,8 +139,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Activity activity = getActivity();
|
||||
|
||||
long secretKeyId = getArguments().getLong(ARG_SECRET_KEY_ID);
|
||||
final long secretKeyId = getArguments().getLong(ARG_SECRET_KEY_ID);
|
||||
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
|
||||
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
|
||||
@ -152,8 +153,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
alert.setMessage(R.string.passPhraseForSymmetricEncryption);
|
||||
} else {
|
||||
// TODO: by master key id???
|
||||
secretKey = PgpHelper.getMasterKey(ProviderHelper.getPGPSecretKeyRingByMasterKeyId(
|
||||
activity, secretKeyId));
|
||||
secretKey = PgpHelper.getMasterKey(ProviderHelper.getPGPSecretKeyRingByKeyId(activity, secretKeyId));
|
||||
// secretKey = PGPHelper.getMasterKey(PGPMain.getSecretKeyRing(secretKeyId));
|
||||
|
||||
if (secretKey == null) {
|
||||
@ -165,6 +165,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
}
|
||||
});
|
||||
alert.setCancelable(false);
|
||||
canKB = false;
|
||||
return alert.create();
|
||||
}
|
||||
String userId = PgpHelper.getMainUserIdSafe(activity, secretKey);
|
||||
@ -184,24 +185,43 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dismiss();
|
||||
|
||||
long curKeyIndex = 0;
|
||||
boolean keyOK = true;
|
||||
String passPhrase = mPassphraseEditText.getText().toString();
|
||||
long keyId;
|
||||
if (secretKey != null) {
|
||||
try {
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
||||
.setProvider(PgpMain.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||
passPhrase.toCharArray());
|
||||
PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
|
||||
if (testKey == null) {
|
||||
PGPSecretKey clickSecretKey = secretKey;
|
||||
|
||||
if (clickSecretKey != null) {
|
||||
while (keyOK == true) {
|
||||
if (clickSecretKey != null) { //check again for loop
|
||||
try {
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
||||
.setProvider(PgpMain.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||
passPhrase.toCharArray());
|
||||
PGPPrivateKey testKey = clickSecretKey.extractPrivateKey(keyDecryptor);
|
||||
if (testKey == null) {
|
||||
if (!clickSecretKey.isMasterKey()) {
|
||||
Toast.makeText(activity, R.string.error_couldNotExtractPrivateKey,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
} else {
|
||||
clickSecretKey = PgpHelper.getKeyNum(ProviderHelper.getPGPSecretKeyRingByKeyId(activity, secretKeyId), curKeyIndex);
|
||||
curKeyIndex++; //does post-increment work like C?
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
keyOK = false;
|
||||
}
|
||||
} catch (PGPException e) {
|
||||
Toast.makeText(activity, R.string.wrongPassPhrase, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(activity, R.string.error_couldNotExtractPrivateKey,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
return; //ran out of keys to try
|
||||
}
|
||||
} catch (PGPException e) {
|
||||
Toast.makeText(activity, R.string.wrongPassPhrase, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
keyId = secretKey.getKeyID();
|
||||
} else {
|
||||
@ -211,6 +231,9 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
// cache the new passphrase
|
||||
Log.d(Constants.TAG, "Everything okay! Caching entered passphrase");
|
||||
PassphraseCacheService.addCachedPassphrase(activity, keyId, passPhrase);
|
||||
if (keyOK == false) {
|
||||
PassphraseCacheService.addCachedPassphrase(activity, clickSecretKey.getKeyID(), passPhrase);
|
||||
}
|
||||
|
||||
sendMessageToHandler(MESSAGE_OKAY);
|
||||
}
|
||||
@ -224,18 +247,20 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
}
|
||||
});
|
||||
|
||||
canKB = true;
|
||||
return alert.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle arg0) {
|
||||
super.onActivityCreated(arg0);
|
||||
|
||||
if (canKB) {
|
||||
// request focus and open soft keyboard
|
||||
mPassphraseEditText.requestFocus();
|
||||
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
||||
mPassphraseEditText.requestFocus();
|
||||
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
||||
|
||||
mPassphraseEditText.setOnEditorActionListener(this);
|
||||
mPassphraseEditText.setOnEditorActionListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -272,4 +297,5 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user