@Test public void testPassphraseChange() throws Exception { builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(new Passphrase())); UncachedKeyRing modified = applyModificationWithChecks(builder.build(), ring, onlyA, onlyB, cryptoInput); assertEquals("exactly three packets should have been modified (the secret keys)", 3, onlyB.size()); RawPacket sKeyNoPassphrase = onlyB.get(1); assertEquals("extracted packet should be a secret subkey", PacketTags.SECRET_SUBKEY, sKeyNoPassphrase.tag); Passphrase otherPassphrase = TestingUtils.testPassphrase1; CryptoInputParcel otherCryptoInput = CryptoInputParcel.createCryptoInputParcel(otherPassphrase); builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(otherPassphrase)); modified = applyModificationWithChecks(builder.build(), modified, onlyA, onlyB, CryptoInputParcel.createCryptoInputParcel(new Date(), new Passphrase())); assertEquals("exactly three packets should have been modified (the secret keys)", 3, onlyB.size()); { HashSet<ByteBuffer> ivs = new HashSet<>(); for (int i = 0; i < 3; i++) { SecretKeyPacket p = (SecretKeyPacket) new BCPGInputStream( new ByteArrayInputStream(onlyB.get(i).buf)).readPacket(); ByteBuffer iv = ByteBuffer.wrap(p.getIV()); Assert.assertFalse( "no two secret keys should have the same s2k iv (slightly non-deterministic!)", ivs.contains(iv) ); ivs.add(iv); } } RawPacket sKeyWithPassphrase = onlyB.get(1); assertEquals("extracted packet should be a secret subkey", PacketTags.SECRET_SUBKEY, sKeyNoPassphrase.tag); Passphrase otherPassphrase2 = TestingUtils.testPassphrase2; builder.setNewUnlock(ChangeUnlockParcel.createUnLockParcelForNewKey(otherPassphrase2)); { modified = KeyringTestingHelper.removePacket(modified, sKeyNoPassphrase.position); modified = KeyringTestingHelper.injectPacket(modified, sKeyNoPassphrase.buf, sKeyNoPassphrase.position); PgpKeyOperation op = new PgpKeyOperation(null); CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(modified.getEncoded(), VerificationStatus.UNVERIFIED); PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, otherCryptoInput, builder.build()); Assert.assertTrue("key modification must succeed", result.success()); Assert.assertFalse("log must not contain a warning", result.getLog().containsWarnings()); modified = result.getRing(); } { modified = KeyringTestingHelper.removePacket(modified, sKeyWithPassphrase.position); modified = KeyringTestingHelper.injectPacket(modified, sKeyWithPassphrase.buf, sKeyWithPassphrase.position); PgpKeyOperation op = new PgpKeyOperation(null); CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(modified.getEncoded(), VerificationStatus.UNVERIFIED); PgpEditKeyResult result = op.modifySecretKeyRing(secretRing, CryptoInputParcel.createCryptoInputParcel(otherPassphrase2), builder.build()); Assert.assertTrue("key modification must succeed", result.success()); Assert.assertTrue("log must contain a failed passphrase change warning", result.getLog().containsType(LogType.MSG_MF_PASSPHRASE_FAIL)); } }
public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR, CryptoInputParcel cryptoInput, SaveKeyringParcel saveParcel) { OperationLog log = new OperationLog(); int indent = 0; log.add(LogType.MSG_MF, indent, KeyFormattingUtils.convertKeyIdToHex(wsKR.getMasterKeyId())); indent += 1; progress(R.string.progress_building_key, 0); if (saveParcel.getMasterKeyId() == null || saveParcel.getMasterKeyId() != wsKR.getMasterKeyId()) { log.add(LogType.MSG_MF_ERROR_KEYID, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } PGPSecretKeyRing sKR = wsKR.getRing(); PGPSecretKey masterSecretKey = sKR.getSecretKey(); if (saveParcel.getFingerprint() == null || !Arrays.equals(saveParcel.getFingerprint(), masterSecretKey.getPublicKey().getFingerprint())) { log.add(LogType.MSG_MF_ERROR_FINGERPRINT, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isParcelEmpty(saveParcel)) { log.add(LogType.MSG_MF_ERROR_NOOP, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } saveParcel = parseSecurityTokenSerialNumberIntoSubkeyChanges(cryptoInput, saveParcel); if (!checkCapabilitiesAreUnique(wsKR, saveParcel, log, indent)) { return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isDummy(masterSecretKey) && ! isParcelRestrictedOnly(saveParcel)) { log.add(LogType.MSG_EK_ERROR_DUMMY, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isDummy(masterSecretKey) || isParcelRestrictedOnly(saveParcel)) { log.add(LogType.MSG_MF_RESTRICTED_MODE, indent); return internalRestricted(sKR, saveParcel, log, indent + 1); } if (!isDivertToCard(masterSecretKey) && !cryptoInput.hasPassphraseForSubkey(masterSecretKey.getKeyID())) { log.add(LogType.MSG_MF_REQUIRE_PASSPHRASE, indent); return new PgpEditKeyResult(log, RequiredInputParcel.createRequiredSignPassphrase( masterSecretKey.getKeyID(), masterSecretKey.getKeyID(), cryptoInput.getSignatureTime()), cryptoInput); } PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey(); int masterKeyFlags = readKeyFlags(masterPublicKey) | KeyFlags.CERTIFY_OTHER; Date expiryTime = wsKR.getPublicKey().getExpiryTime(); long masterKeyExpiry = expiryTime != null ? expiryTime.getTime() / 1000 : 0L; return internal(sKR, masterSecretKey, masterKeyFlags, masterKeyExpiry, cryptoInput, saveParcel, log, indent); }
PgpKeyOperation { public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR, CryptoInputParcel cryptoInput, SaveKeyringParcel saveParcel) { OperationLog log = new OperationLog(); int indent = 0; log.add(LogType.MSG_MF, indent, KeyFormattingUtils.convertKeyIdToHex(wsKR.getMasterKeyId())); indent += 1; progress(R.string.progress_building_key, 0); if (saveParcel.getMasterKeyId() == null || saveParcel.getMasterKeyId() != wsKR.getMasterKeyId()) { log.add(LogType.MSG_MF_ERROR_KEYID, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } PGPSecretKeyRing sKR = wsKR.getRing(); PGPSecretKey masterSecretKey = sKR.getSecretKey(); if (saveParcel.getFingerprint() == null || !Arrays.equals(saveParcel.getFingerprint(), masterSecretKey.getPublicKey().getFingerprint())) { log.add(LogType.MSG_MF_ERROR_FINGERPRINT, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isParcelEmpty(saveParcel)) { log.add(LogType.MSG_MF_ERROR_NOOP, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } saveParcel = parseSecurityTokenSerialNumberIntoSubkeyChanges(cryptoInput, saveParcel); if (!checkCapabilitiesAreUnique(wsKR, saveParcel, log, indent)) { return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isDummy(masterSecretKey) && ! isParcelRestrictedOnly(saveParcel)) { log.add(LogType.MSG_EK_ERROR_DUMMY, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isDummy(masterSecretKey) || isParcelRestrictedOnly(saveParcel)) { log.add(LogType.MSG_MF_RESTRICTED_MODE, indent); return internalRestricted(sKR, saveParcel, log, indent + 1); } if (!isDivertToCard(masterSecretKey) && !cryptoInput.hasPassphraseForSubkey(masterSecretKey.getKeyID())) { log.add(LogType.MSG_MF_REQUIRE_PASSPHRASE, indent); return new PgpEditKeyResult(log, RequiredInputParcel.createRequiredSignPassphrase( masterSecretKey.getKeyID(), masterSecretKey.getKeyID(), cryptoInput.getSignatureTime()), cryptoInput); } PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey(); int masterKeyFlags = readKeyFlags(masterPublicKey) | KeyFlags.CERTIFY_OTHER; Date expiryTime = wsKR.getPublicKey().getExpiryTime(); long masterKeyExpiry = expiryTime != null ? expiryTime.getTime() / 1000 : 0L; return internal(sKR, masterSecretKey, masterKeyFlags, masterKeyExpiry, cryptoInput, saveParcel, log, indent); } }
PgpKeyOperation { public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR, CryptoInputParcel cryptoInput, SaveKeyringParcel saveParcel) { OperationLog log = new OperationLog(); int indent = 0; log.add(LogType.MSG_MF, indent, KeyFormattingUtils.convertKeyIdToHex(wsKR.getMasterKeyId())); indent += 1; progress(R.string.progress_building_key, 0); if (saveParcel.getMasterKeyId() == null || saveParcel.getMasterKeyId() != wsKR.getMasterKeyId()) { log.add(LogType.MSG_MF_ERROR_KEYID, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } PGPSecretKeyRing sKR = wsKR.getRing(); PGPSecretKey masterSecretKey = sKR.getSecretKey(); if (saveParcel.getFingerprint() == null || !Arrays.equals(saveParcel.getFingerprint(), masterSecretKey.getPublicKey().getFingerprint())) { log.add(LogType.MSG_MF_ERROR_FINGERPRINT, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isParcelEmpty(saveParcel)) { log.add(LogType.MSG_MF_ERROR_NOOP, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } saveParcel = parseSecurityTokenSerialNumberIntoSubkeyChanges(cryptoInput, saveParcel); if (!checkCapabilitiesAreUnique(wsKR, saveParcel, log, indent)) { return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isDummy(masterSecretKey) && ! isParcelRestrictedOnly(saveParcel)) { log.add(LogType.MSG_EK_ERROR_DUMMY, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isDummy(masterSecretKey) || isParcelRestrictedOnly(saveParcel)) { log.add(LogType.MSG_MF_RESTRICTED_MODE, indent); return internalRestricted(sKR, saveParcel, log, indent + 1); } if (!isDivertToCard(masterSecretKey) && !cryptoInput.hasPassphraseForSubkey(masterSecretKey.getKeyID())) { log.add(LogType.MSG_MF_REQUIRE_PASSPHRASE, indent); return new PgpEditKeyResult(log, RequiredInputParcel.createRequiredSignPassphrase( masterSecretKey.getKeyID(), masterSecretKey.getKeyID(), cryptoInput.getSignatureTime()), cryptoInput); } PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey(); int masterKeyFlags = readKeyFlags(masterPublicKey) | KeyFlags.CERTIFY_OTHER; Date expiryTime = wsKR.getPublicKey().getExpiryTime(); long masterKeyExpiry = expiryTime != null ? expiryTime.getTime() / 1000 : 0L; return internal(sKR, masterSecretKey, masterKeyFlags, masterKeyExpiry, cryptoInput, saveParcel, log, indent); } PgpKeyOperation(Progressable progress);  PgpKeyOperation(Progressable progress, AtomicBoolean cancelled); }
PgpKeyOperation { public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR, CryptoInputParcel cryptoInput, SaveKeyringParcel saveParcel) { OperationLog log = new OperationLog(); int indent = 0; log.add(LogType.MSG_MF, indent, KeyFormattingUtils.convertKeyIdToHex(wsKR.getMasterKeyId())); indent += 1; progress(R.string.progress_building_key, 0); if (saveParcel.getMasterKeyId() == null || saveParcel.getMasterKeyId() != wsKR.getMasterKeyId()) { log.add(LogType.MSG_MF_ERROR_KEYID, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } PGPSecretKeyRing sKR = wsKR.getRing(); PGPSecretKey masterSecretKey = sKR.getSecretKey(); if (saveParcel.getFingerprint() == null || !Arrays.equals(saveParcel.getFingerprint(), masterSecretKey.getPublicKey().getFingerprint())) { log.add(LogType.MSG_MF_ERROR_FINGERPRINT, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isParcelEmpty(saveParcel)) { log.add(LogType.MSG_MF_ERROR_NOOP, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } saveParcel = parseSecurityTokenSerialNumberIntoSubkeyChanges(cryptoInput, saveParcel); if (!checkCapabilitiesAreUnique(wsKR, saveParcel, log, indent)) { return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isDummy(masterSecretKey) && ! isParcelRestrictedOnly(saveParcel)) { log.add(LogType.MSG_EK_ERROR_DUMMY, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isDummy(masterSecretKey) || isParcelRestrictedOnly(saveParcel)) { log.add(LogType.MSG_MF_RESTRICTED_MODE, indent); return internalRestricted(sKR, saveParcel, log, indent + 1); } if (!isDivertToCard(masterSecretKey) && !cryptoInput.hasPassphraseForSubkey(masterSecretKey.getKeyID())) { log.add(LogType.MSG_MF_REQUIRE_PASSPHRASE, indent); return new PgpEditKeyResult(log, RequiredInputParcel.createRequiredSignPassphrase( masterSecretKey.getKeyID(), masterSecretKey.getKeyID(), cryptoInput.getSignatureTime()), cryptoInput); } PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey(); int masterKeyFlags = readKeyFlags(masterPublicKey) | KeyFlags.CERTIFY_OTHER; Date expiryTime = wsKR.getPublicKey().getExpiryTime(); long masterKeyExpiry = expiryTime != null ? expiryTime.getTime() / 1000 : 0L; return internal(sKR, masterSecretKey, masterKeyFlags, masterKeyExpiry, cryptoInput, saveParcel, log, indent); } PgpKeyOperation(Progressable progress);  PgpKeyOperation(Progressable progress, AtomicBoolean cancelled); PgpEditKeyResult createSecretKeyRing(SaveKeyringParcel saveParcel); PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR,
                                                CryptoInputParcel cryptoInput,
                                                SaveKeyringParcel saveParcel); PgpEditKeyResult modifyKeyRingPassphrase(CanonicalizedSecretKeyRing wsKR,
                                                    CryptoInputParcel cryptoInput,
                                                    ChangeUnlockParcel changeUnlockParcel); }
PgpKeyOperation { public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR, CryptoInputParcel cryptoInput, SaveKeyringParcel saveParcel) { OperationLog log = new OperationLog(); int indent = 0; log.add(LogType.MSG_MF, indent, KeyFormattingUtils.convertKeyIdToHex(wsKR.getMasterKeyId())); indent += 1; progress(R.string.progress_building_key, 0); if (saveParcel.getMasterKeyId() == null || saveParcel.getMasterKeyId() != wsKR.getMasterKeyId()) { log.add(LogType.MSG_MF_ERROR_KEYID, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } PGPSecretKeyRing sKR = wsKR.getRing(); PGPSecretKey masterSecretKey = sKR.getSecretKey(); if (saveParcel.getFingerprint() == null || !Arrays.equals(saveParcel.getFingerprint(), masterSecretKey.getPublicKey().getFingerprint())) { log.add(LogType.MSG_MF_ERROR_FINGERPRINT, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isParcelEmpty(saveParcel)) { log.add(LogType.MSG_MF_ERROR_NOOP, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } saveParcel = parseSecurityTokenSerialNumberIntoSubkeyChanges(cryptoInput, saveParcel); if (!checkCapabilitiesAreUnique(wsKR, saveParcel, log, indent)) { return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isDummy(masterSecretKey) && ! isParcelRestrictedOnly(saveParcel)) { log.add(LogType.MSG_EK_ERROR_DUMMY, indent); return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null); } if (isDummy(masterSecretKey) || isParcelRestrictedOnly(saveParcel)) { log.add(LogType.MSG_MF_RESTRICTED_MODE, indent); return internalRestricted(sKR, saveParcel, log, indent + 1); } if (!isDivertToCard(masterSecretKey) && !cryptoInput.hasPassphraseForSubkey(masterSecretKey.getKeyID())) { log.add(LogType.MSG_MF_REQUIRE_PASSPHRASE, indent); return new PgpEditKeyResult(log, RequiredInputParcel.createRequiredSignPassphrase( masterSecretKey.getKeyID(), masterSecretKey.getKeyID(), cryptoInput.getSignatureTime()), cryptoInput); } PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey(); int masterKeyFlags = readKeyFlags(masterPublicKey) | KeyFlags.CERTIFY_OTHER; Date expiryTime = wsKR.getPublicKey().getExpiryTime(); long masterKeyExpiry = expiryTime != null ? expiryTime.getTime() / 1000 : 0L; return internal(sKR, masterSecretKey, masterKeyFlags, masterKeyExpiry, cryptoInput, saveParcel, log, indent); } PgpKeyOperation(Progressable progress);  PgpKeyOperation(Progressable progress, AtomicBoolean cancelled); PgpEditKeyResult createSecretKeyRing(SaveKeyringParcel saveParcel); PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR,
                                                CryptoInputParcel cryptoInput,
                                                SaveKeyringParcel saveParcel); PgpEditKeyResult modifyKeyRingPassphrase(CanonicalizedSecretKeyRing wsKR,
                                                    CryptoInputParcel cryptoInput,
                                                    ChangeUnlockParcel changeUnlockParcel);  }