aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp
diff options
context:
space:
mode:
authorAlex Fong <alexfongg@gmail.com>2016-03-15 10:24:28 +0800
committerAlex Fong <alexfongg@gmail.com>2016-05-04 22:36:23 +0800
commit525788359c6821a958ee7306ef3aa34d7b211a6f (patch)
treedf76551c2d2b187db62bba313eda1886fa1e7bf1 /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp
parent6b7a0597af7aa42b375ca34d8a47515fa8adcc9f (diff)
downloadopen-keychain-525788359c6821a958ee7306ef3aa34d7b211a6f.tar.gz
open-keychain-525788359c6821a958ee7306ef3aa34d7b211a6f.tar.bz2
open-keychain-525788359c6821a958ee7306ef3aa34d7b211a6f.zip
(WIP) Change password when key is stripped #1692
Approach: Find the first unstripped secret key and use it for passphrase verification All unstripped keys will have their passphrase changed to new passphrase, if possible. Current Progress: Changing the passphrase of keys works fine. Refactoring to combine "modifySecretKeyring" and newly added method, "modifyKeyRingPassword" may be possible if given the go-ahead.
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java72
1 files changed, 66 insertions, 6 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
index ce9c30894..abfdf0966 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
@@ -72,6 +72,8 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog;
import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult;
+import org.sufficientlysecure.keychain.service.ChangeUnlockParcel;
+import org.sufficientlysecure.keychain.service.PassphraseChangeParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve;
@@ -345,6 +347,64 @@ public class PgpKeyOperation {
}
+
+ public PgpEditKeyResult modifyKeyRingPassword(CanonicalizedSecretKeyRing wsKR,
+ CryptoInputParcel cryptoInput,
+ PassphraseChangeParcel passphraseParcel) {
+
+ OperationLog log = new OperationLog();
+ int indent = 0;
+
+ if (passphraseParcel.mMasterKeyId == null || passphraseParcel.mMasterKeyId != wsKR.getMasterKeyId()) {
+ log.add(LogType.MSG_MF_ERROR_KEYID, indent);
+ return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
+ }
+
+ log.add(LogType.MSG_MF, indent,
+ KeyFormattingUtils.convertKeyIdToHex(wsKR.getMasterKeyId()));
+ indent += 1;
+ progress(R.string.progress_building_key, 0);
+
+ // We work on bouncycastle object level here
+ PGPSecretKeyRing sKR = wsKR.getRing();
+ PGPSecretKey masterSecretKey = sKR.getSecretKey();
+ PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
+ // Make sure the fingerprint matches
+ if (passphraseParcel.mFingerprint == null || !Arrays.equals(passphraseParcel.mFingerprint,
+ masterSecretKey.getPublicKey().getFingerprint())) {
+ log.add(LogType.MSG_MF_ERROR_FINGERPRINT, indent);
+ return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
+ }
+
+ if (!cryptoInput.hasPassphrase()) {
+ log.add(LogType.MSG_MF_REQUIRE_PASSPHRASE, indent);
+
+ return new PgpEditKeyResult(log, RequiredInputParcel.createRequiredSignPassphrase(
+ masterSecretKey.getKeyID(), passphraseParcel.mValidSubkeyId,
+ cryptoInput.getSignatureTime()), cryptoInput);
+ } else {
+ progress(R.string.progress_modify_passphrase, 70);
+ log.add(LogType.MSG_MF_PASSPHRASE, indent);
+ indent += 1;
+
+ try {
+ sKR = applyNewPassphrase(sKR, masterPublicKey, cryptoInput.getPassphrase(),
+ passphraseParcel.mNewUnlock.mNewPassphrase, log, indent);
+ if (sKR == null) {
+ // The error has been logged above, just return a bad state
+ return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
+ }
+ } catch (PGPException e) {
+ throw new UnsupportedOperationException("Failed to build encryptor/decryptor!");
+ }
+
+ indent -= 1;
+ progress(R.string.progress_done, 100);
+ log.add(LogType.MSG_MF_SUCCESS, indent);
+ return new PgpEditKeyResult(OperationResult.RESULT_OK, log, new UncachedKeyRing(sKR));
+ }
+ }
+
/** This method introduces a list of modifications specified by a SaveKeyringParcel to a
* WrappedSecretKeyRing.
*
@@ -1223,6 +1283,7 @@ public class PgpKeyOperation {
PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(newPassphrase.getCharArray());
+ int keysModified = 0;
for (PGPSecretKey sKey : new IterableIterator<>(sKR.getSecretKeys())) {
log.add(LogType.MSG_MF_PASSPHRASE_KEY, indent,
@@ -1236,12 +1297,6 @@ public class PgpKeyOperation {
ok = true;
} catch (PGPException e) {
- // if this is the master key, error!
- if (sKey.getKeyID() == masterPublicKey.getKeyID()) {
- log.add(LogType.MSG_MF_ERROR_PASSPHRASE_MASTER, indent+1);
- return null;
- }
-
// being in here means decrypt failed, likely due to a bad passphrase try
// again with an empty passphrase, maybe we can salvage this
try {
@@ -1264,7 +1319,12 @@ public class PgpKeyOperation {
}
sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
+ keysModified++;
+ }
+ if(keysModified == 0) {
+ log.add(LogType.MSG_MF_ERROR_PASSPHRASES_UNCHANGED, indent+1);
+ return null;
}
return sKR;