mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-05 08:59:05 +00:00
101 lines
3.6 KiB
Swift
101 lines
3.6 KiB
Swift
import Foundation
|
|
import Security
|
|
|
|
enum KeychainCredentialStore {
|
|
private static let service = "local.firelink.site-login"
|
|
|
|
static func password(for id: UUID) -> String? {
|
|
let query: [String: Any] = [
|
|
kSecClass as String: kSecClassGenericPassword,
|
|
kSecAttrService as String: service,
|
|
kSecAttrAccount as String: id.uuidString,
|
|
kSecReturnData as String: true,
|
|
kSecMatchLimit as String: kSecMatchLimitOne,
|
|
kSecUseAuthenticationUI as String: kSecUseAuthenticationUIFail
|
|
]
|
|
|
|
var result: CFTypeRef?
|
|
guard SecItemCopyMatching(query as CFDictionary, &result) == errSecSuccess,
|
|
let data = result as? Data else {
|
|
return nil
|
|
}
|
|
|
|
return String(data: data, encoding: .utf8)
|
|
}
|
|
|
|
@discardableResult
|
|
static func setPassword(_ password: String, for id: UUID) -> Bool {
|
|
deletePassword(for: id)
|
|
|
|
let attributes: [String: Any] = [
|
|
kSecClass as String: kSecClassGenericPassword,
|
|
kSecAttrService as String: service,
|
|
kSecAttrAccount as String: id.uuidString,
|
|
kSecValueData as String: Data(password.utf8),
|
|
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
|
|
]
|
|
|
|
return SecItemAdd(attributes as CFDictionary, nil) == errSecSuccess
|
|
}
|
|
|
|
@discardableResult
|
|
static func deletePassword(for id: UUID) -> Bool {
|
|
let query: [String: Any] = [
|
|
kSecClass as String: kSecClassGenericPassword,
|
|
kSecAttrService as String: service,
|
|
kSecAttrAccount as String: id.uuidString
|
|
]
|
|
|
|
let status = SecItemDelete(query as CFDictionary)
|
|
return status == errSecSuccess || status == errSecItemNotFound
|
|
}
|
|
private static let extensionTokenService = "local.firelink.extension-token"
|
|
private static let extensionTokenAccount = "pairing-token"
|
|
|
|
static func extensionToken() -> String? {
|
|
let query: [String: Any] = [
|
|
kSecClass as String: kSecClassGenericPassword,
|
|
kSecAttrService as String: extensionTokenService,
|
|
kSecAttrAccount as String: extensionTokenAccount,
|
|
kSecReturnData as String: true,
|
|
kSecMatchLimit as String: kSecMatchLimitOne,
|
|
kSecUseAuthenticationUI as String: kSecUseAuthenticationUIFail
|
|
]
|
|
|
|
var result: CFTypeRef?
|
|
guard SecItemCopyMatching(query as CFDictionary, &result) == errSecSuccess,
|
|
let data = result as? Data else {
|
|
return nil
|
|
}
|
|
|
|
return String(data: data, encoding: .utf8)
|
|
}
|
|
|
|
@discardableResult
|
|
static func setExtensionToken(_ token: String) -> Bool {
|
|
deleteExtensionToken()
|
|
|
|
let attributes: [String: Any] = [
|
|
kSecClass as String: kSecClassGenericPassword,
|
|
kSecAttrService as String: extensionTokenService,
|
|
kSecAttrAccount as String: extensionTokenAccount,
|
|
kSecValueData as String: Data(token.utf8),
|
|
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
|
|
]
|
|
|
|
return SecItemAdd(attributes as CFDictionary, nil) == errSecSuccess
|
|
}
|
|
|
|
@discardableResult
|
|
static func deleteExtensionToken() -> Bool {
|
|
let query: [String: Any] = [
|
|
kSecClass as String: kSecClassGenericPassword,
|
|
kSecAttrService as String: extensionTokenService,
|
|
kSecAttrAccount as String: extensionTokenAccount
|
|
]
|
|
|
|
let status = SecItemDelete(query as CFDictionary)
|
|
return status == errSecSuccess || status == errSecItemNotFound
|
|
}
|
|
}
|