Add PGPAgent tests and minor updated
This commit is contained in:
parent
a628a9b4da
commit
e967bb1f4c
8 changed files with 68 additions and 43 deletions
|
|
@ -31,7 +31,7 @@ class AddPasswordTableViewController: PasswordEditorTableViewController {
|
||||||
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||||
if identifier == "saveAddPasswordSegue" {
|
if identifier == "saveAddPasswordSegue" {
|
||||||
// check PGP key
|
// check PGP key
|
||||||
guard passwordStore.pgpAgent?.imported ?? false else {
|
guard passwordStore.pgpAgent?.isImported ?? false else {
|
||||||
let alertTitle = "CannotAddPassword".localize()
|
let alertTitle = "CannotAddPassword".localize()
|
||||||
let alertMessage = "PgpKeyNotSet.".localize()
|
let alertMessage = "PgpKeyNotSet.".localize()
|
||||||
Utils.alert(title: alertTitle, message: alertMessage, controller: self, completion: nil)
|
Utils.alert(title: alertTitle, message: alertMessage, controller: self, completion: nil)
|
||||||
|
|
|
||||||
|
|
@ -391,7 +391,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
}
|
}
|
||||||
|
|
||||||
private func decryptThenCopyPassword(from indexPath: IndexPath) {
|
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)
|
Utils.alert(title: "CannotCopyPassword".localize(), message: "SetPgpKey.".localize(), controller: self, completion: nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -453,7 +453,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
|
|
||||||
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||||
if identifier == "showPasswordDetail" {
|
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)
|
Utils.alert(title: "CannotShowPassword".localize(), message: "SetPgpKey.".localize(), controller: self, completion: nil)
|
||||||
if let s = sender as? UITableViewCell {
|
if let s = sender as? UITableViewCell {
|
||||||
let selectedIndexPath = tableView.indexPath(for: s)!
|
let selectedIndexPath = tableView.indexPath(for: s)!
|
||||||
|
|
@ -462,7 +462,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
} else if identifier == "addPasswordSegue" {
|
} 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)
|
Utils.alert(title: "CannotAddPassword".localize(), message: "MakeSurePgpAndGitProperlySet.".localize(), controller: self, completion: nil)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,7 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
||||||
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.pgpAgent?.pgpKeyImportFromFileSharing()
|
try self.passwordStore.pgpAgent?.initPGPKeyFromFileSharing()
|
||||||
try self.passwordStore.pgpAgent?.initPGPKeys()
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.pgpKeyTableViewCell.detailTextLabel?.text = self.passwordStore.pgpAgent?.pgpKeyID
|
self.pgpKeyTableViewCell.detailTextLabel?.text = self.passwordStore.pgpAgent?.pgpKeyID
|
||||||
SVProgressHUD.showSuccess(withStatus: "Imported".localize())
|
SVProgressHUD.showSuccess(withStatus: "Imported".localize())
|
||||||
|
|
@ -193,7 +192,7 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
||||||
optionMenu.addAction(urlAction)
|
optionMenu.addAction(urlAction)
|
||||||
optionMenu.addAction(armorAction)
|
optionMenu.addAction(armorAction)
|
||||||
|
|
||||||
if passwordStore.pgpKeyExists(inFileSharing: true) {
|
if passwordStore.pgpAgent?.isFileSharingReady ?? false {
|
||||||
fileActionTitle.append(" (\("Import".localize()))")
|
fileActionTitle.append(" (\("Import".localize()))")
|
||||||
let fileAction = UIAlertAction(title: fileActionTitle, style: .default) { _ in
|
let fileAction = UIAlertAction(title: fileActionTitle, style: .default) { _ in
|
||||||
// passphrase related
|
// passphrase related
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ class CredentialProviderViewController: ASCredentialProviderViewController, UITa
|
||||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
let entry = getPasswordEntry(by: 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)
|
Utils.alert(title: "CannotCopyPassword".localize(), message: "PgpKeyNotSet.".localize(), controller: self, completion: nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ class ExtensionViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
let entry = getPasswordEntry(by: 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)
|
Utils.alert(title: "CannotCopyPassword".localize(), message: "PgpKeyNotSet.".localize(), controller: self, completion: nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,6 @@ import Gopenpgpwrapper
|
||||||
|
|
||||||
public class PGPAgent {
|
public class PGPAgent {
|
||||||
|
|
||||||
public var imported: Bool {
|
|
||||||
get {
|
|
||||||
return (publicKey != nil || publicKeyV2 != nil) && (privateKey != nil || privateKeyV2 != nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public var pgpKeyID: String?
|
public var pgpKeyID: String?
|
||||||
// PGP passphrase
|
// PGP passphrase
|
||||||
public var passphrase: String? {
|
public var passphrase: String? {
|
||||||
|
|
@ -46,6 +40,17 @@ public class PGPAgent {
|
||||||
}
|
}
|
||||||
private var privateKeyV2: Key?
|
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 {
|
public func initPGPKeys() throws {
|
||||||
try initPGPKey(.PUBLIC)
|
try initPGPKey(.PUBLIC)
|
||||||
try initPGPKey(.PRIVATE)
|
try initPGPKey(.PRIVATE)
|
||||||
|
|
@ -112,9 +117,10 @@ public class PGPAgent {
|
||||||
try initPGPKey(keyType)
|
try initPGPKey(keyType)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func pgpKeyImportFromFileSharing() throws {
|
public func initPGPKeyFromFileSharing() throws {
|
||||||
try KeyFileManager.PublicPgp.importKeyAndDeleteFile()
|
try KeyFileManager.PublicPgp.importKeyAndDeleteFile()
|
||||||
try KeyFileManager.PrivatePgp.importKeyAndDeleteFile()
|
try KeyFileManager.PrivatePgp.importKeyAndDeleteFile()
|
||||||
|
try initPGPKeys()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func decrypt(encryptedData: Data, requestPGPKeyPassphrase: () -> String) throws -> Data? {
|
public func decrypt(encryptedData: Data, requestPGPKeyPassphrase: () -> String) throws -> Data? {
|
||||||
|
|
|
||||||
|
|
@ -730,14 +730,6 @@ public class PasswordStore {
|
||||||
gitSSHPrivateKeyPassphrase = nil
|
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 {
|
public func gitSSHKeyImportFromFileSharing() throws {
|
||||||
try KeyFileManager.PrivateSsh.importKeyAndDeleteFile()
|
try KeyFileManager.PrivateSsh.importKeyAndDeleteFile()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,50 +13,78 @@ import XCTest
|
||||||
class PGPAgentTest: XCTestCase {
|
class PGPAgentTest: XCTestCase {
|
||||||
|
|
||||||
override func setUp() {
|
override func setUp() {
|
||||||
print("setup")
|
PGPAgent().removePGPKeys()
|
||||||
AppKeychain.removeAllContent()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tearDown() {
|
override func tearDown() {
|
||||||
print("tearDown")
|
PGPAgent().removePGPKeys()
|
||||||
AppKeychain.removeAllContent()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func encrypt_decrypt(pgpAgent: PGPAgent) {
|
func basicEncryptDecrypt(pgpAgent: PGPAgent) -> Bool {
|
||||||
// Encrypt and decrypt.
|
// Encrypt and decrypt.
|
||||||
let plainData = "Hello World!".data(using: .utf8)!
|
let plainData = "Hello World!".data(using: .utf8)!
|
||||||
let encryptedData = try? pgpAgent.encrypt(plainData: plainData)
|
guard let encryptedData = try? pgpAgent.encrypt(plainData: plainData) else {
|
||||||
XCTAssertNotNil(encryptedData)
|
return false
|
||||||
let decryptedData = try? pgpAgent.decrypt(encryptedData: encryptedData!, requestPGPKeyPassphrase: requestPGPKeyPassphrase)
|
}
|
||||||
XCTAssertEqual(plainData, decryptedData)
|
guard let decryptedData = try? pgpAgent.decrypt(encryptedData: encryptedData, requestPGPKeyPassphrase: requestPGPKeyPassphrase) else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return plainData == decryptedData
|
||||||
}
|
}
|
||||||
|
|
||||||
func testInitPGPKey() {
|
func testInitPGPKey() {
|
||||||
let pgpAgent = PGPAgent()
|
let pgpAgent = PGPAgent()
|
||||||
|
|
||||||
// [RSA2048] Setup keys.
|
// [RSA2048] Setup keys.
|
||||||
try? pgpAgent.initPGPKey(with: PGP_RSA2048_PUBLIC_KEY, keyType: .PUBLIC)
|
try? pgpAgent.initPGPKey(with: PGP_RSA2048_PUBLIC_KEY, keyType: .PUBLIC)
|
||||||
try? pgpAgent.initPGPKey(with: PGP_RSA2048_PRIVATE_KEY, keyType: .PRIVATE)
|
try? pgpAgent.initPGPKey(with: PGP_RSA2048_PRIVATE_KEY, keyType: .PRIVATE)
|
||||||
XCTAssertTrue(pgpAgent.imported)
|
XCTAssertTrue(pgpAgent.isImported)
|
||||||
XCTAssertEqual(pgpAgent.pgpKeyID, "A1024DAE")
|
XCTAssertEqual(pgpAgent.pgpKeyID, "A1024DAE")
|
||||||
self.encrypt_decrypt(pgpAgent: pgpAgent)
|
XCTAssertTrue(self.basicEncryptDecrypt(pgpAgent: pgpAgent))
|
||||||
let pgpAgent2 = PGPAgent()
|
let pgpAgent2 = PGPAgent()
|
||||||
try? pgpAgent2.initPGPKeys() // load from the keychain
|
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.
|
// [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_PUBLIC_KEY, keyType: .PUBLIC)
|
||||||
try? pgpAgent.initPGPKey(with: PGP_RSA2048_PRIVATE_SUBKEY, keyType: .PRIVATE)
|
try? pgpAgent.initPGPKey(with: PGP_RSA2048_PRIVATE_SUBKEY, keyType: .PRIVATE)
|
||||||
XCTAssertTrue(pgpAgent.imported)
|
XCTAssertTrue(pgpAgent.isImported)
|
||||||
XCTAssertEqual(pgpAgent.pgpKeyID, "A1024DAE")
|
XCTAssertEqual(pgpAgent.pgpKeyID, "A1024DAE")
|
||||||
self.encrypt_decrypt(pgpAgent: pgpAgent)
|
XCTAssertTrue(self.basicEncryptDecrypt(pgpAgent: pgpAgent))
|
||||||
|
pgpAgent.removePGPKeys()
|
||||||
|
|
||||||
// [ED25519] Setup keys.
|
// [ED25519] Setup keys.
|
||||||
try? pgpAgent.initPGPKey(with: PGP_ED25519_PUBLIC_KEY, keyType: .PUBLIC)
|
try? pgpAgent.initPGPKey(with: PGP_ED25519_PUBLIC_KEY, keyType: .PUBLIC)
|
||||||
try? pgpAgent.initPGPKey(with: PGP_ED25519_PRIVATE_KEY, keyType: .PRIVATE)
|
try? pgpAgent.initPGPKey(with: PGP_ED25519_PRIVATE_KEY, keyType: .PRIVATE)
|
||||||
XCTAssertTrue(pgpAgent.imported)
|
XCTAssertTrue(pgpAgent.isImported)
|
||||||
XCTAssertEqual(pgpAgent.pgpKeyID, "E9444483")
|
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() {
|
func testInitPGPKeyBadPrivateKeys() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue