From c917262957e3fd182f77fa32b9de5bd24abbd6e1 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 23 Mar 2016 17:49:26 +0100 Subject: get rid of code path for pin and notation data handling --- .../keychain/pgp/PgpKeyOperation.java | 113 ++++----------------- 1 file changed, 21 insertions(+), 92 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java') 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 e43548165..102e11674 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -18,6 +18,23 @@ package org.sufficientlysecure.keychain.pgp; + +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.spec.ECGenParameterSpec; +import java.util.Arrays; +import java.util.Date; +import java.util.Iterator; +import java.util.Stack; +import java.util.concurrent.atomic.AtomicBoolean; + import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; import org.bouncycastle.bcpg.S2K; import org.bouncycastle.bcpg.sig.Features; @@ -57,13 +74,12 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.Operat import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; -import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; -import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcKeyToCardOperationsBuilder; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; @@ -71,22 +87,6 @@ import org.sufficientlysecure.keychain.util.Passphrase; import org.sufficientlysecure.keychain.util.Primes; import org.sufficientlysecure.keychain.util.ProgressScaler; -import java.io.IOException; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.security.InvalidAlgorithmParameterException; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.SecureRandom; -import java.security.SignatureException; -import java.security.spec.ECGenParameterSpec; -import java.util.Arrays; -import java.util.Date; -import java.util.Iterator; -import java.util.Stack; -import java.util.concurrent.atomic.AtomicBoolean; - /** * This class is the single place where ALL operations that actually modify a PGP public or secret * key take place. @@ -1058,8 +1058,8 @@ public class PgpKeyOperation { log.add(LogType.MSG_MF_PASSPHRASE, indent); indent += 1; - sKR = applyNewUnlock(sKR, masterPublicKey, masterPrivateKey, - cryptoInput.getPassphrase(), saveParcel.mNewUnlock, log, indent); + sKR = applyNewPassphrase(sKR, masterPublicKey, cryptoInput.getPassphrase(), + saveParcel.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); @@ -1191,76 +1191,6 @@ public class PgpKeyOperation { } - - private static PGPSecretKeyRing applyNewUnlock( - PGPSecretKeyRing sKR, - PGPPublicKey masterPublicKey, - PGPPrivateKey masterPrivateKey, - Passphrase passphrase, - ChangeUnlockParcel newUnlock, - OperationLog log, int indent) throws PGPException { - - if (newUnlock.mNewPassphrase != null) { - sKR = applyNewPassphrase(sKR, masterPublicKey, passphrase, newUnlock.mNewPassphrase, log, indent); - - // if there is any old packet with notation data - if (hasNotationData(sKR)) { - - log.add(LogType.MSG_MF_NOTATION_EMPTY, indent); - - // add packet with EMPTY notation data (updates old one, but will be stripped later) - PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPrivateKey.getPublicKeyPacket().getAlgorithm(), - PgpSecurityConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO) - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); - { // set subpackets - PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator(); - hashedPacketsGen.setExportable(false, false); - sGen.setHashedSubpackets(hashedPacketsGen.generate()); - } - sGen.init(PGPSignature.DIRECT_KEY, masterPrivateKey); - PGPSignature emptySig = sGen.generateCertification(masterPublicKey); - - masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, emptySig); - sKR = PGPSecretKeyRing.insertSecretKey(sKR, - PGPSecretKey.replacePublicKey(sKR.getSecretKey(), masterPublicKey)); - } - - return sKR; - } - - if (newUnlock.mNewPin != null) { - sKR = applyNewPassphrase(sKR, masterPublicKey, passphrase, newUnlock.mNewPin, log, indent); - - log.add(LogType.MSG_MF_NOTATION_PIN, indent); - - // add packet with "pin" notation data - PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( - masterPrivateKey.getPublicKeyPacket().getAlgorithm(), - PgpSecurityConstants.SECRET_KEY_BINDING_SIGNATURE_HASH_ALGO) - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); - { // set subpackets - PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator(); - hashedPacketsGen.setExportable(false, false); - hashedPacketsGen.setNotationData(false, true, "unlock.pin@sufficientlysecure.org", "1"); - sGen.setHashedSubpackets(hashedPacketsGen.generate()); - } - sGen.init(PGPSignature.DIRECT_KEY, masterPrivateKey); - PGPSignature emptySig = sGen.generateCertification(masterPublicKey); - - masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, emptySig); - sKR = PGPSecretKeyRing.insertSecretKey(sKR, - PGPSecretKey.replacePublicKey(sKR.getSecretKey(), masterPublicKey)); - - return sKR; - } - - throw new UnsupportedOperationException("PIN passphrases not yet implemented!"); - - } - /** This method returns true iff the provided keyring has a local direct key signature * with notation data. */ @@ -1294,8 +1224,7 @@ public class PgpKeyOperation { PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(newPassphrase.getCharArray()); - // noinspection unchecked - for (PGPSecretKey sKey : new IterableIterator(sKR.getSecretKeys())) { + for (PGPSecretKey sKey : new IterableIterator<>(sKR.getSecretKeys())) { log.add(LogType.MSG_MF_PASSPHRASE_KEY, indent, KeyFormattingUtils.convertKeyIdToHex(sKey.getKeyID())); -- cgit v1.2.3 From 163aef4c6b57c9501038e0a63408360e67ccf4a0 Mon Sep 17 00:00:00 2001 From: Nikita Mikhailov Date: Sat, 16 Apr 2016 00:15:04 +0600 Subject: Update obsolete Nfc class prefixes --- .../org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java') 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 102e11674..ce9c30894 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -78,8 +78,8 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; -import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcKeyToCardOperationsBuilder; -import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.NfcSignOperationsBuilder; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.SecurityTokenKeyToCardOperationsBuilder; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.SecurityTokenSignOperationsBuilder; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; @@ -496,10 +496,10 @@ public class PgpKeyOperation { OperationLog log, int indent) { - NfcSignOperationsBuilder nfcSignOps = new NfcSignOperationsBuilder( + SecurityTokenSignOperationsBuilder nfcSignOps = new SecurityTokenSignOperationsBuilder( cryptoInput.getSignatureTime(), masterSecretKey.getKeyID(), masterSecretKey.getKeyID()); - NfcKeyToCardOperationsBuilder nfcKeyToCardOps = new NfcKeyToCardOperationsBuilder( + SecurityTokenKeyToCardOperationsBuilder nfcKeyToCardOps = new SecurityTokenKeyToCardOperationsBuilder( masterSecretKey.getKeyID()); progress(R.string.progress_modify, 0); @@ -1277,7 +1277,7 @@ public class PgpKeyOperation { PGPPublicKey masterPublicKey, int flags, long expiry, CryptoInputParcel cryptoInput, - NfcSignOperationsBuilder nfcSignOps, + SecurityTokenSignOperationsBuilder nfcSignOps, int indent, OperationLog log) throws PGPException, IOException, SignatureException { -- cgit v1.2.3 From 525788359c6821a958ee7306ef3aa34d7b211a6f Mon Sep 17 00:00:00 2001 From: Alex Fong Date: Tue, 15 Mar 2016 10:24:28 +0800 Subject: (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. --- .../keychain/pgp/PgpKeyOperation.java | 72 ++++++++++++++++++++-- 1 file changed, 66 insertions(+), 6 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java') 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; -- cgit v1.2.3 From b490be9c1c979fd4a75b5844fb68b0179bcfe598 Mon Sep 17 00:00:00 2001 From: Alex Fong Date: Tue, 15 Mar 2016 20:59:42 +0800 Subject: Refactored code to use functions already present in code, reduced liberties taken when modifying functions. Todo: Fix indentation for error messages --- .../keychain/pgp/PgpKeyOperation.java | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java') 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 abfdf0966..cd4d9e5bb 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,7 @@ 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.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.ChangeUnlockParcel; import org.sufficientlysecure.keychain.service.PassphraseChangeParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; @@ -376,6 +377,16 @@ public class PgpKeyOperation { return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } + if (passphraseParcel.mValidSubkeyId == null) { + PGPSecretKey nonDummy = firstNonDummySecretKeyID(sKR); + if(nonDummy== null) { + log.add(OperationResult.LogType.MSG_MF_ERROR_ALL_KEYS_STRIPPED, 0); + return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); + } else { + passphraseParcel.mValidSubkeyId = nonDummy.getKeyID(); + } + } + if (!cryptoInput.hasPassphrase()) { log.add(LogType.MSG_MF_REQUIRE_PASSPHRASE, indent); @@ -405,6 +416,18 @@ public class PgpKeyOperation { } } + private static PGPSecretKey firstNonDummySecretKeyID(PGPSecretKeyRing secRing) { + Iterator secretKeyIterator = secRing.getSecretKeys(); + + while(secretKeyIterator.hasNext()) { + PGPSecretKey secretKey = secretKeyIterator.next(); + if(!isDummy(secretKey)){ + return secretKey; + } + } + return null; + } + /** This method introduces a list of modifications specified by a SaveKeyringParcel to a * WrappedSecretKeyRing. * @@ -1297,6 +1320,12 @@ public class PgpKeyOperation { ok = true; } catch (PGPException e) { + // if this is the master key, error! + if (sKey.getKeyID() == masterPublicKey.getKeyID() && !isDummy(sKey)) { + 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 { -- cgit v1.2.3 From dfcde9242d7b39bf1ab9f0b66fc5829fb0af0f8c Mon Sep 17 00:00:00 2001 From: Alex Fong Date: Thu, 17 Mar 2016 08:03:22 +0800 Subject: Removed unrequired code, standardized terms used. --- .../keychain/pgp/PgpKeyOperation.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java') 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 cd4d9e5bb..bfc48ccbe 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -72,7 +72,6 @@ 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.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.ChangeUnlockParcel; import org.sufficientlysecure.keychain.service.PassphraseChangeParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; @@ -349,9 +348,9 @@ public class PgpKeyOperation { } - public PgpEditKeyResult modifyKeyRingPassword(CanonicalizedSecretKeyRing wsKR, - CryptoInputParcel cryptoInput, - PassphraseChangeParcel passphraseParcel) { + public PgpEditKeyResult modifyKeyRingPassphrase(CanonicalizedSecretKeyRing wsKR, + CryptoInputParcel cryptoInput, + PassphraseChangeParcel passphraseParcel) { OperationLog log = new OperationLog(); int indent = 0; @@ -1274,6 +1273,9 @@ public class PgpKeyOperation { } + + + /** This method returns true iff the provided keyring has a local direct key signature * with notation data. */ @@ -1306,7 +1308,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; + boolean keysModified = false; for (PGPSecretKey sKey : new IterableIterator<>(sKR.getSecretKeys())) { log.add(LogType.MSG_MF_PASSPHRASE_KEY, indent, @@ -1321,6 +1323,7 @@ public class PgpKeyOperation { } catch (PGPException e) { // if this is the master key, error! + // skipped when changing key passphrase if (sKey.getKeyID() == masterPublicKey.getKeyID() && !isDummy(sKey)) { log.add(LogType.MSG_MF_ERROR_PASSPHRASE_MASTER, indent+1); return null; @@ -1348,10 +1351,11 @@ public class PgpKeyOperation { } sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey); - keysModified++; + keysModified = true; } - if(keysModified == 0) { + if(!keysModified) { + // no passphrase is changed log.add(LogType.MSG_MF_ERROR_PASSPHRASES_UNCHANGED, indent+1); return null; } -- cgit v1.2.3 From f43edcdd7afb1692fab1239c54c3cd535506c9e1 Mon Sep 17 00:00:00 2001 From: Alex Fong Date: Sun, 17 Apr 2016 11:34:08 +0800 Subject: Refactoring: Removed PassphraseChangeParcel and placed its functionality into ChangeUnlockParcel. --- .../keychain/pgp/PgpKeyOperation.java | 160 ++++++++++----------- 1 file changed, 76 insertions(+), 84 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java') 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 bfc48ccbe..f98ee0d06 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -73,7 +73,6 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp 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; @@ -347,86 +346,6 @@ public class PgpKeyOperation { } - - public PgpEditKeyResult modifyKeyRingPassphrase(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 (passphraseParcel.mValidSubkeyId == null) { - PGPSecretKey nonDummy = firstNonDummySecretKeyID(sKR); - if(nonDummy== null) { - log.add(OperationResult.LogType.MSG_MF_ERROR_ALL_KEYS_STRIPPED, 0); - return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); - } else { - passphraseParcel.mValidSubkeyId = nonDummy.getKeyID(); - } - } - - 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)); - } - } - - private static PGPSecretKey firstNonDummySecretKeyID(PGPSecretKeyRing secRing) { - Iterator secretKeyIterator = secRing.getSecretKeys(); - - while(secretKeyIterator.hasNext()) { - PGPSecretKey secretKey = secretKeyIterator.next(); - if(!isDummy(secretKey)){ - return secretKey; - } - } - return null; - } - /** This method introduces a list of modifications specified by a SaveKeyringParcel to a * WrappedSecretKeyRing. * @@ -1135,13 +1054,13 @@ public class PgpKeyOperation { } // 6. If requested, change passphrase - if (saveParcel.mNewUnlock != null) { + if (saveParcel.getChangeUnlockParcel() != null) { progress(R.string.progress_modify_passphrase, 90); log.add(LogType.MSG_MF_PASSPHRASE, indent); indent += 1; sKR = applyNewPassphrase(sKR, masterPublicKey, cryptoInput.getPassphrase(), - saveParcel.mNewUnlock.mNewPassphrase, log, indent); + saveParcel.getChangeUnlockParcel().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); @@ -1274,7 +1193,81 @@ public class PgpKeyOperation { } + public PgpEditKeyResult modifyKeyRingPassphrase(CanonicalizedSecretKeyRing wsKR, + CryptoInputParcel cryptoInput, + ChangeUnlockParcel changeUnlockParcel) { + + OperationLog log = new OperationLog(); + int indent = 0; + + if (changeUnlockParcel.mMasterKeyId == null || changeUnlockParcel.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 (changeUnlockParcel.mFingerprint == null || !Arrays.equals(changeUnlockParcel.mFingerprint, + masterSecretKey.getPublicKey().getFingerprint())) { + log.add(LogType.MSG_MF_ERROR_FINGERPRINT, indent); + return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); + } + + // Find the first unstripped secret key + PGPSecretKey nonDummy = firstNonDummySecretKeyID(sKR); + if(nonDummy == null) { + log.add(OperationResult.LogType.MSG_MF_ERROR_ALL_KEYS_STRIPPED, 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(), nonDummy.getKeyID(), + cryptoInput.getSignatureTime()), cryptoInput); + } else { + progress(R.string.progress_modify_passphrase, 50); + log.add(LogType.MSG_MF_PASSPHRASE, indent); + indent += 1; + + try { + sKR = applyNewPassphrase(sKR, masterPublicKey, cryptoInput.getPassphrase(), + changeUnlockParcel.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)); + } + } + + private static PGPSecretKey firstNonDummySecretKeyID(PGPSecretKeyRing secRing) { + Iterator secretKeyIterator = secRing.getSecretKeys(); + + while(secretKeyIterator.hasNext()) { + PGPSecretKey secretKey = secretKeyIterator.next(); + if(!isDummy(secretKey)){ + return secretKey; + } + } + return null; + } /** This method returns true iff the provided keyring has a local direct key signature * with notation data. @@ -1323,7 +1316,6 @@ public class PgpKeyOperation { } catch (PGPException e) { // if this is the master key, error! - // skipped when changing key passphrase if (sKey.getKeyID() == masterPublicKey.getKeyID() && !isDummy(sKey)) { log.add(LogType.MSG_MF_ERROR_PASSPHRASE_MASTER, indent+1); return null; -- cgit v1.2.3 From 01c2e1429bfbf399856c25ad291a63d88139cfc6 Mon Sep 17 00:00:00 2001 From: Alex Fong Date: Sun, 17 Apr 2016 18:07:23 +0800 Subject: Edited comments --- .../java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java') 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 f98ee0d06..404e07230 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -1315,7 +1315,7 @@ public class PgpKeyOperation { ok = true; } catch (PGPException e) { - // if this is the master key, error! + // if the master key failed && it's not stripped, error! if (sKey.getKeyID() == masterPublicKey.getKeyID() && !isDummy(sKey)) { log.add(LogType.MSG_MF_ERROR_PASSPHRASE_MASTER, indent+1); return null; @@ -1347,7 +1347,7 @@ public class PgpKeyOperation { } if(!keysModified) { - // no passphrase is changed + // no passphrase was changed log.add(LogType.MSG_MF_ERROR_PASSPHRASES_UNCHANGED, indent+1); return null; } -- cgit v1.2.3