dimensionhub/dimensionhub/Core/KeychainHelper.swift
2025-06-26 17:36:10 +08:00

98 lines
2.8 KiB
Swift

//
// KeychainHelper.swift
// dimensionhub
//
// Created by on 2025/6/26.
//
import Foundation
import Security
import UIKit
struct KeychainHelper {
// MARK: -
static func getPersistentUserId() -> String {
let keychainAccount = "com.jihe.dimensionhub.deviceUUID"
// 1. Keychain
if let uuid = load(key: keychainAccount) {
return uuid
}
// 2. UUID
let newUUID = generatorUserId()
// 3. Keychain
let data = newUUID.data(using: .utf8)!
if !save(key: keychainAccount, data: data) {
NSLog("save uuid to keychain error")
}
return newUUID
}
/// Keychain
private static func load(key: String) -> String? {
if let data = loadFromSecurity(key: key) {
return String(data: data, encoding: .utf8)
}
return nil
}
/// Keychain
static func delete(key: String) -> Bool {
let query = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key
] as [String: Any]
let status = SecItemDelete(query as CFDictionary)
return status == errSecSuccess || status == errSecItemNotFound
}
// MARK: -
private static func save(key: String, data: Data) -> Bool {
let query = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
kSecValueData as String: data
] as [String: Any]
//
SecItemDelete(query as CFDictionary)
//
let status = SecItemAdd(query as CFDictionary, nil)
return status == errSecSuccess
}
private static func loadFromSecurity(key: String) -> Data? {
let query = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecReturnData as String: kCFBooleanTrue!,
kSecMatchLimit as String: kSecMatchLimitOne
] as [String: Any]
var dataTypeRef: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
if status == errSecSuccess {
return dataTypeRef as? Data
}
return nil
}
// uuid
private static func generatorUserId() -> String {
if let uuid = UIDevice.current.identifierForVendor?.uuidString {
return uuid.lowercased()
} else {
return UUID().uuidString.lowercased()
}
}
}