Store PGP keys in Keychain

This commit is contained in:
Danny Moesch 2019-06-24 23:37:01 +02:00 committed by Mingshen Sun
parent ca3271b20a
commit a66a79abc6
5 changed files with 40 additions and 53 deletions

View file

@ -90,8 +90,8 @@ class PGPKeyArmorSettingTableViewController: AutoCellHeightUITableViewController
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
armorPublicKeyTextView.text = SharedDefaults[.pgpPublicKeyArmor] armorPublicKeyTextView.text = String(data: Utils.getDataFromKeychain(for: PasswordStore.PGPKeyType.PUBLIC.rawValue)!, encoding: .ascii)
armorPrivateKeyTextView.text = SharedDefaults[.pgpPrivateKeyArmor] armorPrivateKeyTextView.text = String(data: Utils.getDataFromKeychain(for: PasswordStore.PGPKeyType.PRIVATE.rawValue)!, encoding: .ascii)
pgpPassphrase = passwordStore.pgpKeyPassphrase pgpPassphrase = passwordStore.pgpKeyPassphrase
scanPublicKeyCell?.textLabel?.text = "ScanPublicKeyQrCodes".localize() scanPublicKeyCell?.textLabel?.text = "ScanPublicKeyQrCodes".localize()

View file

@ -59,17 +59,13 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
if SharedDefaults[.isRememberPGPPassphraseOn] { if SharedDefaults[.isRememberPGPPassphraseOn] {
self.passwordStore.pgpKeyPassphrase = controller.pgpPassphrase self.passwordStore.pgpKeyPassphrase = controller.pgpPassphrase
} }
SharedDefaults[.pgpPublicKeyArmor] = controller.armorPublicKeyTextView.text!
SharedDefaults[.pgpPrivateKeyArmor] = controller.armorPrivateKeyTextView.text!
SVProgressHUD.setDefaultMaskType(.black) SVProgressHUD.setDefaultMaskType(.black)
SVProgressHUD.setDefaultStyle(.light) SVProgressHUD.setDefaultStyle(.light)
SVProgressHUD.show(withStatus: "FetchingPgpKey".localize()) SVProgressHUD.show(withStatus: "FetchingPgpKey".localize())
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
do { do {
try self.passwordStore.initPGPKey(with: SharedDefaults[.pgpPublicKeyArmor] ?? "", keyType: .PUBLIC) try self.passwordStore.initPGPKey(with: controller.armorPublicKeyTextView.text ?? "", keyType: .PUBLIC)
try self.passwordStore.initPGPKey(with: SharedDefaults[.pgpPrivateKeyArmor] ?? "", keyType: .PRIVATE) try self.passwordStore.initPGPKey(with: controller.armorPrivateKeyTextView.text ?? "", keyType: .PRIVATE)
DispatchQueue.main.async { DispatchQueue.main.async {
self.pgpKeyTableViewCell.detailTextLabel?.text = self.passwordStore.pgpKeyID self.pgpKeyTableViewCell.detailTextLabel?.text = self.passwordStore.pgpKeyID
SVProgressHUD.showSuccess(withStatus: "Success".localize()) SVProgressHUD.showSuccess(withStatus: "Success".localize())

View file

@ -16,9 +16,6 @@ public extension DefaultsKeys {
static let pgpPublicKeyURL = DefaultsKey<URL?>("pgpPublicKeyURL") static let pgpPublicKeyURL = DefaultsKey<URL?>("pgpPublicKeyURL")
static let pgpPrivateKeyURL = DefaultsKey<URL?>("pgpPrivateKeyURL") static let pgpPrivateKeyURL = DefaultsKey<URL?>("pgpPrivateKeyURL")
static let pgpPublicKeyArmor = DefaultsKey<String?>("pgpPublicKeyArmor")
static let pgpPrivateKeyArmor = DefaultsKey<String?>("pgpPrivateKeyArmor")
static let gitURL = DefaultsKey<URL?>("gitURL") static let gitURL = DefaultsKey<URL?>("gitURL")
static let gitAuthenticationMethod = DefaultsKey<String?>("gitAuthenticationMethod") static let gitAuthenticationMethod = DefaultsKey<String?>("gitAuthenticationMethod")
static let gitUsername = DefaultsKey<String?>("gitUsername") static let gitUsername = DefaultsKey<String?>("gitUsername")

View file

@ -32,6 +32,14 @@ public class Utils {
try? keychain.removeAll() 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?) { public static func copyToPasteboard(textToCopy: String?) {
guard textToCopy != nil else { guard textToCopy != nil else {
return return

View file

@ -34,8 +34,9 @@ public class PasswordStore {
} }
} }
public var privateKey: GopenpgpwrapperKey? public var privateKey: GopenpgpwrapperKey?
public enum PGPKeyType { public enum PGPKeyType: String {
case PUBLIC, PRIVATE case PUBLIC = "pgpPublicKey"
case PRIVATE = "pgpPrivateKey"
} }
public var gitSignatureForNow: GTSignature? { public var gitSignatureForNow: GTSignature? {
@ -196,55 +197,31 @@ public class PasswordStore {
try initPGPKey(.PRIVATE) try initPGPKey(.PRIVATE)
} }
public func initPGPKey(_ keyType: PGPKeyType) throws { private func initPGPKey(_ keyType: PGPKeyType) throws {
switch keyType { if let key = GopenpgpwrapperReadKey(Utils.getDataFromKeychain(for: keyType.rawValue)) {
case .PUBLIC: switch keyType {
let keyPath = Globals.pgpPublicKeyPath case .PUBLIC:
self.publicKey = importKey(from: keyPath) self.publicKey = key
if self.publicKey == nil { case .PRIVATE:
throw AppError.KeyImport self.privateKey = key
}
case .PRIVATE:
let keyPath = Globals.pgpPrivateKeyPath
self.privateKey = importKey(from: keyPath)
if self.privateKey == nil {
throw AppError.KeyImport
} }
return
} }
throw AppError.KeyImport
} }
public func initPGPKey(from url: URL, keyType: PGPKeyType) throws { 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) 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) try initPGPKey(keyType)
} }
public func initPGPKey(with armorKey: String, keyType: PGPKeyType) throws { public func initPGPKey(with armorKey: String, keyType: PGPKeyType) throws {
var pgpKeyLocalPath = "" let pgpKeyData = armorKey.data(using: .ascii)!
if keyType == .PUBLIC { Utils.addDataToKeychain(key: keyType.rawValue, data: pgpKeyData)
pgpKeyLocalPath = Globals.pgpPublicKeyPath
} else {
pgpKeyLocalPath = Globals.pgpPrivateKeyPath
}
try armorKey.write(toFile: pgpKeyLocalPath, atomically: true, encoding: .ascii)
try initPGPKey(keyType) 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 { public func repositoryExisted() -> Bool {
let fm = FileManager() let fm = FileManager()
return fm.fileExists(atPath: Globals.repositoryPath) return fm.fileExists(atPath: Globals.repositoryPath)
@ -846,11 +823,11 @@ public class PasswordStore {
try? fm.removeItem(atPath: Globals.pgpPublicKeyPath) try? fm.removeItem(atPath: Globals.pgpPublicKeyPath)
try? fm.removeItem(atPath: Globals.pgpPrivateKeyPath) try? fm.removeItem(atPath: Globals.pgpPrivateKeyPath)
SharedDefaults.remove(.pgpKeySource) SharedDefaults.remove(.pgpKeySource)
SharedDefaults.remove(.pgpPublicKeyArmor)
SharedDefaults.remove(.pgpPrivateKeyArmor)
SharedDefaults.remove(.pgpPrivateKeyURL) SharedDefaults.remove(.pgpPrivateKeyURL)
SharedDefaults.remove(.pgpPublicKeyURL) SharedDefaults.remove(.pgpPublicKeyURL)
Utils.removeKeychain(name: ".pgpKeyPassphrase") Utils.removeKeychain(name: ".pgpKeyPassphrase")
Utils.removeKeychain(name: PGPKeyType.PUBLIC.rawValue)
Utils.removeKeychain(name: PGPKeyType.PRIVATE.rawValue)
publicKey = nil publicKey = nil
privateKey = nil privateKey = nil
} }
@ -883,7 +860,16 @@ public class PasswordStore {
} }
public func pgpKeyImportFromFileSharing() throws { public func pgpKeyImportFromFileSharing() throws {
try fm.moveItem(atPath: Globals.iTunesFileSharingPGPPublic, toPath: Globals.pgpPublicKeyPath) let publicKeyFileUrl = URL(fileURLWithPath: Globals.iTunesFileSharingPGPPublic)
try fm.moveItem(atPath: Globals.iTunesFileSharingPGPPrivate, toPath: Globals.pgpPrivateKeyPath) 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)
} }
} }