diff --git a/passKit/Crypto/PGPAgent.swift b/passKit/Crypto/PGPAgent.swift index 51d6e6a..44b3443 100644 --- a/passKit/Crypto/PGPAgent.swift +++ b/passKit/Crypto/PGPAgent.swift @@ -60,13 +60,8 @@ public class PGPAgent { throw AppError.decryption } - var keyID = keyID if !pgpInterface.containsPrivateKey(with: keyID) { - if pgpInterface.keyID.count == 1 { - keyID = pgpInterface.keyID.first! - } else { - throw AppError.pgpPrivateKeyNotFound(keyID: keyID) - } + throw AppError.pgpPrivateKeyNotFound(keyID: keyID) } // Remember the previous status and set the current status diff --git a/passKitTests/LowLevel/PGPAgentLowLevelTests.swift b/passKitTests/LowLevel/PGPAgentLowLevelTests.swift index f562621..7ef764c 100644 --- a/passKitTests/LowLevel/PGPAgentLowLevelTests.swift +++ b/passKitTests/LowLevel/PGPAgentLowLevelTests.swift @@ -69,21 +69,7 @@ final class PGPAgentLowLevelTests: XCTestCase { XCTAssertEqual(mockPGP.decryptCalls[0].encryptedData, testEncryptedData) } - /// When the private key is NOT found but there's exactly one key, falls back to that key. - func testDecryptWithKeyID_keyNotFound_singleKey_fallsBackToOnlyKey() throws { - let longFingerprint = "4712286271220db299883ea7062e678da1024dae" - mockPGP.privateKeyIDs = [] // requested key not found - mockPGP.keyIDs = [longFingerprint] - - _ = try agent.decrypt(encryptedData: testEncryptedData, keyID: "UNKNOWN", requestPGPKeyPassphrase: passphraseCallback("pass")) - - XCTAssertEqual(mockPGP.decryptCalls.count, 1) - // The keyID passed to pgpInterface.decrypt should be the fallback key, not the requested one. - XCTAssertEqual(mockPGP.decryptCalls[0].keyID, longFingerprint) - } - - /// When the private key is NOT found and there are multiple keys, throws pgpPrivateKeyNotFound. - func testDecryptWithKeyID_keyNotFound_multipleKeys_throws() { + func testDecryptWithKeyID_keyNotFound_throws() { mockPGP.privateKeyIDs = [] mockPGP.keyIDs = ["4712286271220db299883ea7062e678da1024dae", "787eae1a5fa3e749aa34cc6aa0645ebed862027e"] @@ -378,9 +364,8 @@ final class PGPAgentLowLevelTests: XCTestCase { // MARK: - Key resolution error vs decrypt status ordering - /// When pgpPrivateKeyNotFound is thrown (key not found, multiple keys), - /// latestDecryptStatus is NOT changed because the error occurs BEFORE the status update. - func testDecryptWithKeyID_keyNotFound_multipleKeys_doesNotChangeDecryptStatus() throws { + /// When pgpPrivateKeyNotFound is thrown, latestDecryptStatus is NOT changed because the error occurs BEFORE the status update. + func testDecryptWithKeyID_keyNotFound_doesNotChangeDecryptStatus() throws { let longFingerprint = "4712286271220db299883ea7062e678da1024dae" mockPGP.privateKeyIDs = [] mockPGP.keyIDs = [longFingerprint, "787eae1a5fa3e749aa34cc6aa0645ebed862027e"] @@ -401,33 +386,6 @@ final class PGPAgentLowLevelTests: XCTestCase { XCTAssertEqual(mockPGP.resolvedPassphrases, ["cached-pass"]) } - /// After failure + key fallback: passphrase is always requested using the RESOLVED (fallback) keyID. - func testDecryptWithKeyID_afterFailure_keyFallback_requestsWithResolvedKeyID() throws { - let shortID = "a1024dae" - let longFingerprint1 = "4712286271220db299883ea7062e678da1024dae" - let longFingerprint2 = "5fccb081ab8af48972999e2ae750acbfe9444483" - mockPGP.privateKeyIDs = [longFingerprint1] - - // Force a failure using a short ID that suffix-matches longFingerprint1. - mockPGP.decryptError = AppError.wrongPassphrase - _ = try? agent.decrypt(encryptedData: testEncryptedData, keyID: shortID, requestPGPKeyPassphrase: passphraseCallback("bad")) - - // Now try with an unknown key that falls back to a different long fingerprint. - mockPGP.decryptError = nil - mockPGP.privateKeyIDs = [] - mockPGP.keyIDs = [longFingerprint2] - mockPGP.decryptCalls.removeAll() - mockPGP.resolvedPassphrases.removeAll() - mockPGP.selectedKeyForPassphrase = longFingerprint2 - passphraseRequests.removeAll() - - _ = try agent.decrypt(encryptedData: testEncryptedData, keyID: "e9444483", requestPGPKeyPassphrase: passphraseCallback("pass")) - - XCTAssertEqual(mockPGP.decryptCalls[0].keyID, longFingerprint2) - XCTAssertEqual(mockPGP.resolvedPassphrases, ["pass"]) - XCTAssertEqual(passphraseRequests, [longFingerprint2]) - } - // MARK: - Cross-overload latestDecryptStatus interaction /// latestDecryptStatus is shared between both overloads. @@ -494,20 +452,6 @@ final class PGPAgentLowLevelTests: XCTestCase { XCTAssertEqual(mockPGP.decryptCalls[0].keyID, shortID) } - /// When caller passes a short ID and containsPrivateKey does NOT match, but there's one key, - /// the long fingerprint from keyID[0] is forwarded instead. - func testDecryptWithKeyID_shortIDNotRecognized_singleKey_resolvesToLongFingerprint() throws { - let shortID = "a1024dae" - let longFingerprint = "4712286271220db299883ea7062e678da1024dae" - mockPGP.privateKeyIDs = [] // short ID doesn't match - mockPGP.keyIDs = [longFingerprint] - - _ = try agent.decrypt(encryptedData: testEncryptedData, keyID: shortID, requestPGPKeyPassphrase: passphraseCallback("pass")) - - XCTAssertEqual(mockPGP.containsPrivateKeyCalls, [shortID]) - XCTAssertEqual(mockPGP.decryptCalls[0].keyID, longFingerprint) - } - /// Passphrase stored under long fingerprint is NOT found when the short ID is used for lookup func testDecryptWithKeyID_shortIDRecognized_passphraseStoredUnderLongID_missesKeystore() throws { let shortID = "a1024dae"