diff --git a/pass/Controllers/AddPasswordTableViewController.swift b/pass/Controllers/AddPasswordTableViewController.swift index e3421a3..23f2f19 100644 --- a/pass/Controllers/AddPasswordTableViewController.swift +++ b/pass/Controllers/AddPasswordTableViewController.swift @@ -31,7 +31,7 @@ class AddPasswordTableViewController: PasswordEditorTableViewController { override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { if identifier == "saveAddPasswordSegue" { // check PGP key - guard passwordStore.pgpAgent?.imported ?? false else { + guard passwordStore.pgpAgent?.isImported ?? false else { let alertTitle = "CannotAddPassword".localize() let alertMessage = "PgpKeyNotSet.".localize() Utils.alert(title: alertTitle, message: alertMessage, controller: self, completion: nil) diff --git a/pass/Controllers/PasswordsViewController.swift b/pass/Controllers/PasswordsViewController.swift index 224e7c1..0fd4c89 100644 --- a/pass/Controllers/PasswordsViewController.swift +++ b/pass/Controllers/PasswordsViewController.swift @@ -391,7 +391,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV } private func decryptThenCopyPassword(from indexPath: IndexPath) { - guard self.passwordStore.pgpAgent?.imported ?? false else { + guard self.passwordStore.pgpAgent?.isImported ?? false else { Utils.alert(title: "CannotCopyPassword".localize(), message: "SetPgpKey.".localize(), controller: self, completion: nil) return } @@ -453,7 +453,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { if identifier == "showPasswordDetail" { - guard self.passwordStore.pgpAgent?.imported ?? false else { + guard self.passwordStore.pgpAgent?.isImported ?? false else { Utils.alert(title: "CannotShowPassword".localize(), message: "SetPgpKey.".localize(), controller: self, completion: nil) if let s = sender as? UITableViewCell { let selectedIndexPath = tableView.indexPath(for: s)! @@ -462,7 +462,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV return false } } else if identifier == "addPasswordSegue" { - guard self.passwordStore.pgpAgent?.imported ?? false && self.passwordStore.storeRepository != nil else { + guard self.passwordStore.pgpAgent?.isImported ?? false && self.passwordStore.storeRepository != nil else { Utils.alert(title: "CannotAddPassword".localize(), message: "MakeSurePgpAndGitProperlySet.".localize(), controller: self, completion: nil) return false } diff --git a/pass/Controllers/SettingsTableViewController.swift b/pass/Controllers/SettingsTableViewController.swift index 57ffd9c..6a936af 100644 --- a/pass/Controllers/SettingsTableViewController.swift +++ b/pass/Controllers/SettingsTableViewController.swift @@ -89,8 +89,7 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele SVProgressHUD.show(withStatus: "FetchingPgpKey".localize()) DispatchQueue.global(qos: .userInitiated).async { [unowned self] in do { - try self.passwordStore.pgpAgent?.pgpKeyImportFromFileSharing() - try self.passwordStore.pgpAgent?.initPGPKeys() + try self.passwordStore.pgpAgent?.initPGPKeyFromFileSharing() DispatchQueue.main.async { self.pgpKeyTableViewCell.detailTextLabel?.text = self.passwordStore.pgpAgent?.pgpKeyID SVProgressHUD.showSuccess(withStatus: "Imported".localize()) @@ -193,7 +192,7 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele optionMenu.addAction(urlAction) optionMenu.addAction(armorAction) - if passwordStore.pgpKeyExists(inFileSharing: true) { + if passwordStore.pgpAgent?.isFileSharingReady ?? false { fileActionTitle.append(" (\("Import".localize()))") let fileAction = UIAlertAction(title: fileActionTitle, style: .default) { _ in // passphrase related diff --git a/passAutoFillExtension/Controllers/CredentialProviderViewController.swift b/passAutoFillExtension/Controllers/CredentialProviderViewController.swift index 66f9ec7..6bef8da 100644 --- a/passAutoFillExtension/Controllers/CredentialProviderViewController.swift +++ b/passAutoFillExtension/Controllers/CredentialProviderViewController.swift @@ -145,7 +145,7 @@ class CredentialProviderViewController: ASCredentialProviderViewController, UITa func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let entry = getPasswordEntry(by: indexPath) - guard self.passwordStore.pgpAgent?.imported ?? false else { + guard self.passwordStore.pgpAgent?.isImported ?? false else { Utils.alert(title: "CannotCopyPassword".localize(), message: "PgpKeyNotSet.".localize(), controller: self, completion: nil) return } diff --git a/passExtension/Controllers/ExtensionViewController.swift b/passExtension/Controllers/ExtensionViewController.swift index 63b33c0..c6f208b 100644 --- a/passExtension/Controllers/ExtensionViewController.swift +++ b/passExtension/Controllers/ExtensionViewController.swift @@ -153,7 +153,7 @@ class ExtensionViewController: UIViewController, UITableViewDataSource, UITableV func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let entry = getPasswordEntry(by: indexPath) - guard self.passwordStore.pgpAgent?.imported ?? false else { + guard self.passwordStore.pgpAgent?.isImported ?? false else { Utils.alert(title: "CannotCopyPassword".localize(), message: "PgpKeyNotSet.".localize(), controller: self, completion: nil) return } diff --git a/passKit/Models/PGPAgent.swift b/passKit/Models/PGPAgent.swift index 1396ad4..72a1a42 100644 --- a/passKit/Models/PGPAgent.swift +++ b/passKit/Models/PGPAgent.swift @@ -13,12 +13,6 @@ import Gopenpgpwrapper public class PGPAgent { - public var imported: Bool { - get { - return (publicKey != nil || publicKeyV2 != nil) && (privateKey != nil || privateKeyV2 != nil) - } - } - public var pgpKeyID: String? // PGP passphrase public var passphrase: String? { @@ -46,6 +40,17 @@ public class PGPAgent { } private var privateKeyV2: Key? + public var isImported: Bool { + get { + return (publicKey != nil || publicKeyV2 != nil) && (privateKey != nil || privateKeyV2 != nil) + } + } + public var isFileSharingReady: Bool { + get { + return KeyFileManager.PublicPgp.doesKeyFileExist() && KeyFileManager.PrivatePgp.doesKeyFileExist() + } + } + public func initPGPKeys() throws { try initPGPKey(.PUBLIC) try initPGPKey(.PRIVATE) @@ -112,9 +117,10 @@ public class PGPAgent { try initPGPKey(keyType) } - public func pgpKeyImportFromFileSharing() throws { + public func initPGPKeyFromFileSharing() throws { try KeyFileManager.PublicPgp.importKeyAndDeleteFile() try KeyFileManager.PrivatePgp.importKeyAndDeleteFile() + try initPGPKeys() } public func decrypt(encryptedData: Data, requestPGPKeyPassphrase: () -> String) throws -> Data? { diff --git a/passKit/Models/PasswordStore.swift b/passKit/Models/PasswordStore.swift index 79504fb..fbbef0c 100644 --- a/passKit/Models/PasswordStore.swift +++ b/passKit/Models/PasswordStore.swift @@ -730,14 +730,6 @@ public class PasswordStore { gitSSHPrivateKeyPassphrase = nil } - public func pgpKeyExists(inFileSharing: Bool = false) -> Bool { - if inFileSharing == false { - return fm.fileExists(atPath: Globals.pgpPublicKeyPath) && fm.fileExists(atPath: Globals.pgpPrivateKeyPath) - } else { - return KeyFileManager.PublicPgp.doesKeyFileExist() && KeyFileManager.PrivatePgp.doesKeyFileExist() - } - } - public func gitSSHKeyImportFromFileSharing() throws { try KeyFileManager.PrivateSsh.importKeyAndDeleteFile() } diff --git a/passKitTests/Models/PGPAgentTest.swift b/passKitTests/Models/PGPAgentTest.swift index cd40709..e3f7db0 100644 --- a/passKitTests/Models/PGPAgentTest.swift +++ b/passKitTests/Models/PGPAgentTest.swift @@ -13,50 +13,78 @@ import XCTest class PGPAgentTest: XCTestCase { override func setUp() { - print("setup") - AppKeychain.removeAllContent() + PGPAgent().removePGPKeys() } override func tearDown() { - print("tearDown") - AppKeychain.removeAllContent() + PGPAgent().removePGPKeys() } - func encrypt_decrypt(pgpAgent: PGPAgent) { + func basicEncryptDecrypt(pgpAgent: PGPAgent) -> Bool { // Encrypt and decrypt. let plainData = "Hello World!".data(using: .utf8)! - let encryptedData = try? pgpAgent.encrypt(plainData: plainData) - XCTAssertNotNil(encryptedData) - let decryptedData = try? pgpAgent.decrypt(encryptedData: encryptedData!, requestPGPKeyPassphrase: requestPGPKeyPassphrase) - XCTAssertEqual(plainData, decryptedData) + guard let encryptedData = try? pgpAgent.encrypt(plainData: plainData) else { + return false + } + guard let decryptedData = try? pgpAgent.decrypt(encryptedData: encryptedData, requestPGPKeyPassphrase: requestPGPKeyPassphrase) else { + return false + } + return plainData == decryptedData } func testInitPGPKey() { let pgpAgent = PGPAgent() - + // [RSA2048] Setup keys. try? pgpAgent.initPGPKey(with: PGP_RSA2048_PUBLIC_KEY, keyType: .PUBLIC) try? pgpAgent.initPGPKey(with: PGP_RSA2048_PRIVATE_KEY, keyType: .PRIVATE) - XCTAssertTrue(pgpAgent.imported) + XCTAssertTrue(pgpAgent.isImported) XCTAssertEqual(pgpAgent.pgpKeyID, "A1024DAE") - self.encrypt_decrypt(pgpAgent: pgpAgent) + XCTAssertTrue(self.basicEncryptDecrypt(pgpAgent: pgpAgent)) let pgpAgent2 = PGPAgent() try? pgpAgent2.initPGPKeys() // load from the keychain - self.encrypt_decrypt(pgpAgent: pgpAgent2) - + XCTAssertTrue(self.basicEncryptDecrypt(pgpAgent: pgpAgent2)) + pgpAgent.removePGPKeys() + // [RSA2048] Setup keys. The private key is a subkey. try? pgpAgent.initPGPKey(with: PGP_RSA2048_PUBLIC_KEY, keyType: .PUBLIC) try? pgpAgent.initPGPKey(with: PGP_RSA2048_PRIVATE_SUBKEY, keyType: .PRIVATE) - XCTAssertTrue(pgpAgent.imported) + XCTAssertTrue(pgpAgent.isImported) XCTAssertEqual(pgpAgent.pgpKeyID, "A1024DAE") - self.encrypt_decrypt(pgpAgent: pgpAgent) - + XCTAssertTrue(self.basicEncryptDecrypt(pgpAgent: pgpAgent)) + pgpAgent.removePGPKeys() + // [ED25519] Setup keys. try? pgpAgent.initPGPKey(with: PGP_ED25519_PUBLIC_KEY, keyType: .PUBLIC) try? pgpAgent.initPGPKey(with: PGP_ED25519_PRIVATE_KEY, keyType: .PRIVATE) - XCTAssertTrue(pgpAgent.imported) + XCTAssertTrue(pgpAgent.isImported) XCTAssertEqual(pgpAgent.pgpKeyID, "E9444483") - self.encrypt_decrypt(pgpAgent: pgpAgent) + XCTAssertTrue(self.basicEncryptDecrypt(pgpAgent: pgpAgent)) + pgpAgent.removePGPKeys() + + // [RSA2048] Setup keys from URL. + let publicKeyURL = URL(fileURLWithPath: PgpKey.PUBLIC.getFileSharingPath()) + let privateKeyURL = URL(fileURLWithPath: PgpKey.PRIVATE.getFileSharingPath()) + try? PGP_RSA2048_PUBLIC_KEY.write(to: publicKeyURL, atomically: false, encoding: .utf8) + try? PGP_RSA2048_PRIVATE_KEY.write(to: privateKeyURL, atomically: false, encoding: .utf8) + try? pgpAgent.initPGPKey(from: publicKeyURL, keyType: .PUBLIC) + try? pgpAgent.initPGPKey(from: privateKeyURL, keyType: .PRIVATE) + XCTAssertTrue(pgpAgent.isImported) + XCTAssertEqual(pgpAgent.pgpKeyID, "A1024DAE") + XCTAssertTrue(self.basicEncryptDecrypt(pgpAgent: pgpAgent)) + pgpAgent.removePGPKeys() + + // [RSA2048] Setup keys from iTunes file sharing. + try? PGP_RSA2048_PUBLIC_KEY.write(to: publicKeyURL, atomically: false, encoding: .utf8) + try? PGP_RSA2048_PRIVATE_KEY.write(to: privateKeyURL, atomically: false, encoding: .utf8) + XCTAssertTrue(pgpAgent.isFileSharingReady) + try? pgpAgent.initPGPKeyFromFileSharing() + XCTAssertTrue(pgpAgent.isImported) + XCTAssertEqual(pgpAgent.pgpKeyID, "A1024DAE") + XCTAssertTrue(self.basicEncryptDecrypt(pgpAgent: pgpAgent)) + XCTAssertFalse(FileManager.default.fileExists(atPath: publicKeyURL.absoluteString)) + XCTAssertFalse(FileManager.default.fileExists(atPath: privateKeyURL.absoluteString)) + pgpAgent.removePGPKeys() } func testInitPGPKeyBadPrivateKeys() {