swift 无法使用密钥链保存/检索对称字符串,错误-25306

92vpleto  于 2023-05-05  发布在  Swift
关注(0)|答案(1)|浏览(240)

在iOS上,而不是在OSX上,无法使用keychain保存/检索对称字符串,我使用此代码没有问题
kSecClassGenericPassword
但我想添加一个更安全的使用钥匙链与
kSecAttrAccessible:kSecAttrAccessibleWhenUnlocked

kSecClass:kSecAttrKeyClassSymmetric,

let query = [
            kSecValueData: data,
            kSecClass: kSecClassGenericPassword,
            kSecAttrService: service,
            kSecAttrAccount: account,
        ] as CFDictionary

也许我不清楚某些键需要什么,但无法从文档中理解它,我也得到了错误-25306,我发现与errKCNoSuchClass相关,不清楚引用的是什么类。一些同事告诉我,在iOS 15左右,钥匙链发生了一些变化,但似乎有所不同。

let stringToBeSaved = "c773c86d0e4a553349d329d6bb74e0a20dddc72f3f6b14f02258770bc879573d663d33f32167692fa1a2d1f85a9e51650956660f7398a94fce678c6c194d9ff1"

 

final class KeychainHelper_SymetricMetods {
    
    static let standard = KeychainHelper_SymetricMetods()
    private init() {}
    
    
    
    //MARK: kSecAttrKeyClassSymmetric

    func save_kSecAttrKeyClassSymmetric(_ data: Data, service: String, account: String) {

        // Create query
        let query = [
            kSecValueData: data,
            kSecClass: kSecAttrKeyClassSymmetric,
            kSecAttrService: service,
            kSecAttrAccount: account,
            kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked, //‼️ mandatory?
        ] as CFDictionary

        let status = SecItemAdd(query, nil)

        if status == errSecDuplicateItem {
            let query = [
                kSecAttrService: service,
                kSecAttrAccount: account,
                kSecClass: kSecAttrKeyClassSymmetric,
                kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked, //‼️ mandatory?
            ] as CFDictionary

            let attributesToUpdate = [kSecValueData: data] as CFDictionary
            SecItemUpdate(query, attributesToUpdate)
            print("was duplicated, we overwritten")
        } else {
            print("status: \(status)") //‼️ -25306 errKCNoSuchClass
        }
    }
    
    
    func read_kSecAttrKeyClassSymmetric(service: String, account: String) -> Data? {

        let query = [
            kSecAttrService: service,
            kSecAttrAccount: account,
            kSecClass: kSecAttrKeyClassSymmetric,
            kSecReturnData: true
        ] as CFDictionary

        var result: AnyObject?
        SecItemCopyMatching(query, &result)

        return (result as? Data)
    }
    
    
    func delete_kSecAttrKeyClassSymmetric(service: String, account: String) {

        let query = [
            kSecAttrService: service,
            kSecAttrAccount: account,
            kSecClass: kSecAttrKeyClassSymmetric,
        ] as CFDictionary

        // Delete item from keychain
        SecItemDelete(query)
        print("Deleted")
    }

    
    
    
}
dced5bon

dced5bon1#

kSecClassSymmetricKey是一个有点奇怪的常数,正如它所描述的,我引用:
用于对称密钥加密和解密的私钥。
因此,您无法将自己的SymmetricKey、密码或原始二进制密钥作为对称密钥存储在该密钥下。但是,您可以根据您的请求使用kSecClassGenericPassword上的kSecAttrAccessible属性来存储您的密钥 * 更多限制 *,因为该密钥仅适用于通用密码对象。

enum SymmetricKeyStorage {
    static func save(_ key: Data, account: String, service: String) {
        var attributes: [CFString: Any] = [
            kSecClass: kSecClassGenericPassword,
            kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked,
            kSecAttrService: service,
            kSecAttrAccount: account,
            kSecValueData: key
        ]

        var status = SecItemAdd(attributes as CFDictionary, nil)
        if status == errSecDuplicateItem {
            let updates: [CFString: Any] = [
                kSecValueData: attributes.removeValue(forKey: kSecValueData)!
            ]
            status = SecItemUpdate(attributes as CFDictionary, updates as CFDictionary)
        }

        print("Status:", status)
    }

    static func read(account: String, service: String) -> Data? {
        let query: [CFString: Any] = [
            kSecClass: kSecClassGenericPassword,
            kSecAttrService: service,
            kSecAttrAccount: account,
            kSecMatchLimit: kSecMatchLimitOne,
            kSecReturnData: true
        ]

        var result: CFTypeRef?
        let status = SecItemCopyMatching(query as CFDictionary, &result)

        switch status {
        case errSecItemNotFound:
            print("Item not found, status:", status)
            return nil
        case errSecSuccess:
            print("Item found, status:", status)
            guard let result else { return nil }
            return result as? Data
        default:
            print("Failed to query item, status:", status)
            return nil
        }
    }

    static func delete(account: String, service: String) {
        let query: [CFString: Any] = [
            kSecClass: kSecClassGenericPassword,
            kSecAttrService: service,
            kSecAttrAccount: account
        ]

        let status = SecItemDelete(query as CFDictionary)
        switch status {
        case errSecSuccess, errSecItemNotFound:
            print("Item deleted, status:", status)
        default:
            print("Status:", status)
        }
    }
}

相关问题