From a66a79abc66f2ed8ce2a13f78c24c4950fb7d962 Mon Sep 17 00:00:00 2001 From: Danny Moesch Date: Mon, 24 Jun 2019 23:37:01 +0200 Subject: [PATCH] Store PGP keys in Keychain --- ...GPKeyArmorSettingTableViewController.swift | 4 +- .../SettingsTableViewController.swift | 8 +-- passKit/Helpers/DefaultsKeys.swift | 3 - passKit/Helpers/Utils.swift | 8 +++ passKit/Models/PasswordStore.swift | 70 ++++++++----------- 5 files changed, 40 insertions(+), 53 deletions(-) diff --git a/pass/Controllers/PGPKeyArmorSettingTableViewController.swift b/pass/Controllers/PGPKeyArmorSettingTableViewController.swift index 76136f1..9fb4ac1 100644 --- a/pass/Controllers/PGPKeyArmorSettingTableViewController.swift +++ b/pass/Controllers/PGPKeyArmorSettingTableViewController.swift @@ -90,8 +90,8 @@ class PGPKeyArmorSettingTableViewController: AutoCellHeightUITableViewController override func viewDidLoad() { super.viewDidLoad() - armorPublicKeyTextView.text = SharedDefaults[.pgpPublicKeyArmor] - armorPrivateKeyTextView.text = SharedDefaults[.pgpPrivateKeyArmor] + armorPublicKeyTextView.text = String(data: Utils.getDataFromKeychain(for: PasswordStore.PGPKeyType.PUBLIC.rawValue)!, encoding: .ascii) + armorPrivateKeyTextView.text = String(data: Utils.getDataFromKeychain(for: PasswordStore.PGPKeyType.PRIVATE.rawValue)!, encoding: .ascii) pgpPassphrase = passwordStore.pgpKeyPassphrase scanPublicKeyCell?.textLabel?.text = "ScanPublicKeyQrCodes".localize() diff --git a/pass/Controllers/SettingsTableViewController.swift b/pass/Controllers/SettingsTableViewController.swift index a5dca05..4157c56 100644 --- a/pass/Controllers/SettingsTableViewController.swift +++ b/pass/Controllers/SettingsTableViewController.swift @@ -59,17 +59,13 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele if SharedDefaults[.isRememberPGPPassphraseOn] { self.passwordStore.pgpKeyPassphrase = controller.pgpPassphrase } - - SharedDefaults[.pgpPublicKeyArmor] = controller.armorPublicKeyTextView.text! - SharedDefaults[.pgpPrivateKeyArmor] = controller.armorPrivateKeyTextView.text! - SVProgressHUD.setDefaultMaskType(.black) SVProgressHUD.setDefaultStyle(.light) SVProgressHUD.show(withStatus: "FetchingPgpKey".localize()) DispatchQueue.global(qos: .userInitiated).async { [unowned self] in do { - try self.passwordStore.initPGPKey(with: SharedDefaults[.pgpPublicKeyArmor] ?? "", keyType: .PUBLIC) - try self.passwordStore.initPGPKey(with: SharedDefaults[.pgpPrivateKeyArmor] ?? "", keyType: .PRIVATE) + try self.passwordStore.initPGPKey(with: controller.armorPublicKeyTextView.text ?? "", keyType: .PUBLIC) + try self.passwordStore.initPGPKey(with: controller.armorPrivateKeyTextView.text ?? "", keyType: .PRIVATE) DispatchQueue.main.async { self.pgpKeyTableViewCell.detailTextLabel?.text = self.passwordStore.pgpKeyID SVProgressHUD.showSuccess(withStatus: "Success".localize()) diff --git a/passKit/Helpers/DefaultsKeys.swift b/passKit/Helpers/DefaultsKeys.swift index 3218d5a..700681c 100644 --- a/passKit/Helpers/DefaultsKeys.swift +++ b/passKit/Helpers/DefaultsKeys.swift @@ -16,9 +16,6 @@ public extension DefaultsKeys { static let pgpPublicKeyURL = DefaultsKey("pgpPublicKeyURL") static let pgpPrivateKeyURL = DefaultsKey("pgpPrivateKeyURL") - static let pgpPublicKeyArmor = DefaultsKey("pgpPublicKeyArmor") - static let pgpPrivateKeyArmor = DefaultsKey("pgpPrivateKeyArmor") - static let gitURL = DefaultsKey("gitURL") static let gitAuthenticationMethod = DefaultsKey("gitAuthenticationMethod") static let gitUsername = DefaultsKey("gitUsername") diff --git a/passKit/Helpers/Utils.swift b/passKit/Helpers/Utils.swift index 67c3b40..eb91b22 100644 --- a/passKit/Helpers/Utils.swift +++ b/passKit/Helpers/Utils.swift @@ -32,6 +32,14 @@ public class Utils { try? keychain.removeAll() } + public static func addDataToKeychain(key: String, data: Data) { + keychain[data: key] = data + } + + public static func getDataFromKeychain(for key: String) -> Data? { + return try? keychain.getData(key) + } + public static func copyToPasteboard(textToCopy: String?) { guard textToCopy != nil else { return diff --git a/passKit/Models/PasswordStore.swift b/passKit/Models/PasswordStore.swift index 7feda39..3e7f91d 100644 --- a/passKit/Models/PasswordStore.swift +++ b/passKit/Models/PasswordStore.swift @@ -34,8 +34,9 @@ public class PasswordStore { } } public var privateKey: GopenpgpwrapperKey? - public enum PGPKeyType { - case PUBLIC, PRIVATE + public enum PGPKeyType: String { + case PUBLIC = "pgpPublicKey" + case PRIVATE = "pgpPrivateKey" } public var gitSignatureForNow: GTSignature? { @@ -196,55 +197,31 @@ public class PasswordStore { try initPGPKey(.PRIVATE) } - public func initPGPKey(_ keyType: PGPKeyType) throws { - switch keyType { - case .PUBLIC: - let keyPath = Globals.pgpPublicKeyPath - self.publicKey = importKey(from: keyPath) - if self.publicKey == nil { - throw AppError.KeyImport - } - case .PRIVATE: - let keyPath = Globals.pgpPrivateKeyPath - self.privateKey = importKey(from: keyPath) - if self.privateKey == nil { - throw AppError.KeyImport + private func initPGPKey(_ keyType: PGPKeyType) throws { + if let key = GopenpgpwrapperReadKey(Utils.getDataFromKeychain(for: keyType.rawValue)) { + switch keyType { + case .PUBLIC: + self.publicKey = key + case .PRIVATE: + self.privateKey = key } + return } + throw AppError.KeyImport } public func initPGPKey(from url: URL, keyType: PGPKeyType) throws { - var pgpKeyLocalPath = "" - if keyType == .PUBLIC { - pgpKeyLocalPath = Globals.pgpPublicKeyPath - } else { - pgpKeyLocalPath = Globals.pgpPrivateKeyPath - } let pgpKeyData = try Data(contentsOf: url) - try pgpKeyData.write(to: URL(fileURLWithPath: pgpKeyLocalPath), options: .atomic) + Utils.addDataToKeychain(key: keyType.rawValue, data: pgpKeyData) try initPGPKey(keyType) } public func initPGPKey(with armorKey: String, keyType: PGPKeyType) throws { - var pgpKeyLocalPath = "" - if keyType == .PUBLIC { - pgpKeyLocalPath = Globals.pgpPublicKeyPath - } else { - pgpKeyLocalPath = Globals.pgpPrivateKeyPath - } - try armorKey.write(toFile: pgpKeyLocalPath, atomically: true, encoding: .ascii) + let pgpKeyData = armorKey.data(using: .ascii)! + Utils.addDataToKeychain(key: keyType.rawValue, data: pgpKeyData) try initPGPKey(keyType) } - - private func importKey(from keyPath: String) -> GopenpgpwrapperKey? { - if fm.fileExists(atPath: keyPath) { - return GopenpgpwrapperReadKey(fm.contents(atPath: keyPath)) - } - return nil - } - - public func repositoryExisted() -> Bool { let fm = FileManager() return fm.fileExists(atPath: Globals.repositoryPath) @@ -846,11 +823,11 @@ public class PasswordStore { try? fm.removeItem(atPath: Globals.pgpPublicKeyPath) try? fm.removeItem(atPath: Globals.pgpPrivateKeyPath) SharedDefaults.remove(.pgpKeySource) - SharedDefaults.remove(.pgpPublicKeyArmor) - SharedDefaults.remove(.pgpPrivateKeyArmor) SharedDefaults.remove(.pgpPrivateKeyURL) SharedDefaults.remove(.pgpPublicKeyURL) Utils.removeKeychain(name: ".pgpKeyPassphrase") + Utils.removeKeychain(name: PGPKeyType.PUBLIC.rawValue) + Utils.removeKeychain(name: PGPKeyType.PRIVATE.rawValue) publicKey = nil privateKey = nil } @@ -883,7 +860,16 @@ public class PasswordStore { } public func pgpKeyImportFromFileSharing() throws { - try fm.moveItem(atPath: Globals.iTunesFileSharingPGPPublic, toPath: Globals.pgpPublicKeyPath) - try fm.moveItem(atPath: Globals.iTunesFileSharingPGPPrivate, toPath: Globals.pgpPrivateKeyPath) + let publicKeyFileUrl = URL(fileURLWithPath: Globals.iTunesFileSharingPGPPublic) + let privateKeyFileUrl = URL(fileURLWithPath: Globals.iTunesFileSharingPGPPrivate) + + let publicKeyFileContent = try Data(contentsOf: publicKeyFileUrl) + let privateKeyFileContent = try Data(contentsOf: privateKeyFileUrl) + + Utils.addDataToKeychain(key: PGPKeyType.PUBLIC.rawValue, data: publicKeyFileContent) + Utils.addDataToKeychain(key: PGPKeyType.PRIVATE.rawValue, data: privateKeyFileContent) + + try fm.removeItem(at: publicKeyFileUrl) + try fm.removeItem(at: privateKeyFileUrl) } }