Store PGP keys in Keychain
This commit is contained in:
parent
ca3271b20a
commit
a66a79abc6
5 changed files with 40 additions and 53 deletions
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue