59 lines
2.3 KiB
Swift
59 lines
2.3 KiB
Swift
|
|
import Foundation
|
||
|
|
import Security
|
||
|
|
|
||
|
|
enum HoloLakeKeychain {
|
||
|
|
private static let service = "com.guanghulab.hololake.mobile-sync"
|
||
|
|
private static let account = "HLP-IOS-CLIENT-001"
|
||
|
|
|
||
|
|
static func load() throws -> StoredSession? {
|
||
|
|
let query: [String: Any] = [
|
||
|
|
kSecClass as String: kSecClassGenericPassword,
|
||
|
|
kSecAttrService as String: service,
|
||
|
|
kSecAttrAccount as String: account,
|
||
|
|
kSecReturnData as String: true,
|
||
|
|
kSecMatchLimit as String: kSecMatchLimitOne
|
||
|
|
]
|
||
|
|
var result: CFTypeRef?
|
||
|
|
let status = SecItemCopyMatching(query as CFDictionary, &result)
|
||
|
|
if status == errSecItemNotFound { return nil }
|
||
|
|
guard status == errSecSuccess, let data = result as? Data else {
|
||
|
|
throw HoloLakeMobileError.keychain(status)
|
||
|
|
}
|
||
|
|
return try JSONDecoder().decode(StoredSession.self, from: data)
|
||
|
|
}
|
||
|
|
|
||
|
|
static func save(_ session: StoredSession) throws {
|
||
|
|
let data = try JSONEncoder().encode(session)
|
||
|
|
let query: [String: Any] = [
|
||
|
|
kSecClass as String: kSecClassGenericPassword,
|
||
|
|
kSecAttrService as String: service,
|
||
|
|
kSecAttrAccount as String: account
|
||
|
|
]
|
||
|
|
let attributes: [String: Any] = [
|
||
|
|
kSecValueData as String: data,
|
||
|
|
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
|
||
|
|
]
|
||
|
|
let update = SecItemUpdate(query as CFDictionary, attributes as CFDictionary)
|
||
|
|
if update == errSecItemNotFound {
|
||
|
|
var insertion = query
|
||
|
|
insertion.merge(attributes) { _, new in new }
|
||
|
|
let status = SecItemAdd(insertion as CFDictionary, nil)
|
||
|
|
guard status == errSecSuccess else { throw HoloLakeMobileError.keychain(status) }
|
||
|
|
} else if update != errSecSuccess {
|
||
|
|
throw HoloLakeMobileError.keychain(update)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static func remove() throws {
|
||
|
|
let query: [String: Any] = [
|
||
|
|
kSecClass as String: kSecClassGenericPassword,
|
||
|
|
kSecAttrService as String: service,
|
||
|
|
kSecAttrAccount as String: account
|
||
|
|
]
|
||
|
|
let status = SecItemDelete(query as CFDictionary)
|
||
|
|
guard status == errSecSuccess || status == errSecItemNotFound else {
|
||
|
|
throw HoloLakeMobileError.keychain(status)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|