add encrypt-save-decrypt roundtrip test
This commit is contained in:
parent
60999c7eab
commit
e5650ec756
21 changed files with 75 additions and 18 deletions
1
passKitTests/Fixtures/password-store-empty.git/HEAD
Normal file
1
passKitTests/Fixtures/password-store-empty.git/HEAD
Normal file
|
|
@ -0,0 +1 @@
|
|||
ref: refs/heads/main
|
||||
6
passKitTests/Fixtures/password-store-empty.git/config
Normal file
6
passKitTests/Fixtures/password-store-empty.git/config
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = true
|
||||
ignorecase = true
|
||||
precomposeunicode = true
|
||||
|
|
@ -0,0 +1 @@
|
|||
Unnamed repository; edit this file 'description' to name the repository.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,3 @@
|
|||
x•ÍM
|
||||
Â0@a×9Åì™ü<E284A2>¤ â\z<>i:Å@›BœzzKÕ¸}‹ï¥ež³€îôN*3Sôv¤48J=ÙÞEoØŽÎDÒˆÈk"EMnK…ËóN¥ÀµRy,<2C>_pœ¶r–_9p;<3B>Á¢‹ˆìqETÚ¾Âÿ
|
||||
&ú¯ rÉ’i‚¥ÞÃ@í
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
# pack-refs with: peeled fully-peeled sorted
|
||||
f095bb4897e4cd58faadfe4d4f678fb697be3ffd refs/heads/main
|
||||
|
|
@ -0,0 +1 @@
|
|||
Example password store repository for passforios tests with .gpg-id files.
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
# git ls-files --others --exclude-from=.git/info/exclude
|
||||
# Lines that start with '#' are comments.
|
||||
# For a project mostly in C, the following would be a good set of
|
||||
# exclude patterns (uncomment them if you want to use them):
|
||||
# *.[oa]
|
||||
# *~
|
||||
|
|
@ -1 +0,0 @@
|
|||
Example password store repository for passforios tests.
|
||||
|
|
@ -13,7 +13,6 @@ import XCTest
|
|||
@testable import passKit
|
||||
|
||||
final class PasswordStoreTest: XCTestCase {
|
||||
private lazy var remoteRepoURL: URL = Bundle(for: type(of: self)).resourceURL!.appendingPathComponent("Fixtures/password-store.git")
|
||||
private let localRepoURL: URL = Globals.sharedContainerURL.appendingPathComponent("Library/password-store-test/")
|
||||
|
||||
private var passwordStore: PasswordStore! = nil
|
||||
|
|
@ -25,10 +24,12 @@ final class PasswordStoreTest: XCTestCase {
|
|||
override func tearDown() {
|
||||
passwordStore.erase()
|
||||
passwordStore = nil
|
||||
|
||||
Defaults.removeAll()
|
||||
}
|
||||
|
||||
func testInitPasswordEntityCoreData() throws {
|
||||
try cloneRepository()
|
||||
try cloneRepository(.withGPGID)
|
||||
|
||||
XCTAssertEqual(passwordStore.numberOfPasswords, 4)
|
||||
|
||||
|
|
@ -50,7 +51,7 @@ final class PasswordStoreTest: XCTestCase {
|
|||
}
|
||||
|
||||
func testEraseStoreData() throws {
|
||||
try cloneRepository()
|
||||
try cloneRepository(.withGPGID)
|
||||
XCTAssertTrue(FileManager.default.fileExists(atPath: localRepoURL.path))
|
||||
XCTAssertGreaterThan(passwordStore.numberOfPasswords, 0)
|
||||
XCTAssertNotNil(passwordStore.gitRepository)
|
||||
|
|
@ -63,8 +64,8 @@ final class PasswordStoreTest: XCTestCase {
|
|||
}
|
||||
|
||||
func testErase() throws {
|
||||
try cloneRepository()
|
||||
try importPGPKeys()
|
||||
try cloneRepository(.withGPGID)
|
||||
try importSinglePGPKey()
|
||||
Defaults.gitSignatureName = "Test User"
|
||||
PasscodeLock.shared.save(passcode: "1234")
|
||||
|
||||
|
|
@ -84,7 +85,7 @@ final class PasswordStoreTest: XCTestCase {
|
|||
}
|
||||
|
||||
func testFetchPasswordEntityCoreDataByParent() throws {
|
||||
try cloneRepository()
|
||||
try cloneRepository(.withGPGID)
|
||||
|
||||
let rootChildren = passwordStore.fetchPasswordEntityCoreData(parent: nil)
|
||||
XCTAssertGreaterThan(rootChildren.count, 0)
|
||||
|
|
@ -99,7 +100,7 @@ final class PasswordStoreTest: XCTestCase {
|
|||
}
|
||||
|
||||
func testFetchPasswordEntityCoreDataWithDir() throws {
|
||||
try cloneRepository()
|
||||
try cloneRepository(.withGPGID)
|
||||
|
||||
let allPasswords = passwordStore.fetchPasswordEntityCoreData(withDir: false)
|
||||
XCTAssertEqual(allPasswords.count, 4)
|
||||
|
|
@ -108,14 +109,21 @@ final class PasswordStoreTest: XCTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
func testEncryptSaveDecryptMultiline() throws {
|
||||
try cloneRepository(.empty)
|
||||
try importSinglePGPKey()
|
||||
|
||||
let password = Password(name: "test", path: "test.gpg", plainText: "foobar\nwith\nmultiple\nlines")
|
||||
_ = try passwordStore.add(password: password)
|
||||
let decryptedPassword = try decrypt(path: "test.gpg")
|
||||
XCTAssertEqual(decryptedPassword.plainText, "foobar\nwith\nmultiple\nlines")
|
||||
}
|
||||
|
||||
func testCloneAndDecryptMultiKeys() throws {
|
||||
try cloneRepository()
|
||||
try importPGPKeys()
|
||||
try cloneRepository(.withGPGID)
|
||||
try importMultiplePGPKeys()
|
||||
|
||||
Defaults.isEnableGPGIDOn = true
|
||||
defer {
|
||||
Defaults.isEnableGPGIDOn = false
|
||||
}
|
||||
|
||||
[
|
||||
("work/github.com", "4712286271220DB299883EA7062E678DA1024DAE"),
|
||||
|
|
@ -139,21 +147,51 @@ final class PasswordStoreTest: XCTestCase {
|
|||
|
||||
// MARK: - Helpers
|
||||
|
||||
private func cloneRepository() throws {
|
||||
try passwordStore.cloneRepository(remoteRepoURL: remoteRepoURL, branchName: "master")
|
||||
private enum RemoteRepo {
|
||||
case empty
|
||||
case withGPGID
|
||||
|
||||
var url: URL {
|
||||
switch self {
|
||||
case .empty:
|
||||
Bundle(for: PasswordStoreTest.self).resourceURL!.appendingPathComponent("Fixtures/password-store-empty.git")
|
||||
case .withGPGID:
|
||||
Bundle(for: PasswordStoreTest.self).resourceURL!.appendingPathComponent("Fixtures/password-store-with-gpgid.git")
|
||||
}
|
||||
}
|
||||
|
||||
var branchName: String {
|
||||
switch self {
|
||||
case .empty:
|
||||
"main"
|
||||
case .withGPGID:
|
||||
"master"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func cloneRepository(_ remote: RemoteRepo) throws {
|
||||
try passwordStore.cloneRepository(remoteRepoURL: remote.url, branchName: remote.branchName)
|
||||
expectation(for: NSPredicate { _, _ in FileManager.default.fileExists(atPath: self.localRepoURL.path) }, evaluatedWith: nil)
|
||||
waitForExpectations(timeout: 3, handler: nil)
|
||||
}
|
||||
|
||||
private func importPGPKeys() throws {
|
||||
private func importSinglePGPKey() throws {
|
||||
let keychain = AppKeychain.shared
|
||||
try KeyFileManager(keyType: PGPKey.PUBLIC, keyPath: "", keyHandler: keychain.add).importKey(from: RSA4096.publicKey)
|
||||
try KeyFileManager(keyType: PGPKey.PRIVATE, keyPath: "", keyHandler: keychain.add).importKey(from: RSA4096.privateKey)
|
||||
try PGPAgent.shared.initKeys()
|
||||
}
|
||||
|
||||
private func importMultiplePGPKeys() throws {
|
||||
let keychain = AppKeychain.shared
|
||||
try KeyFileManager(keyType: PGPKey.PUBLIC, keyPath: "", keyHandler: keychain.add).importKey(from: RSA2048_RSA4096.publicKeys)
|
||||
try KeyFileManager(keyType: PGPKey.PRIVATE, keyPath: "", keyHandler: keychain.add).importKey(from: RSA2048_RSA4096.privateKeys)
|
||||
try PGPAgent.shared.initKeys()
|
||||
}
|
||||
|
||||
private func decrypt(path: String) throws -> Password {
|
||||
private func decrypt(path: String, keyID: String? = nil) throws -> Password {
|
||||
let entity = passwordStore.fetchPasswordEntity(with: path)!
|
||||
return try passwordStore.decrypt(passwordEntity: entity, requestPGPKeyPassphrase: requestPGPKeyPassphrase)
|
||||
return try passwordStore.decrypt(passwordEntity: entity, keyID: keyID, requestPGPKeyPassphrase: requestPGPKeyPassphrase)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue