iOS Swift 5 Keychain Status -50 错误 SecItemAdd
iOS Swift 5 Keychain Status -50 with error SecItemAdd
我正在尝试编写一个包装器,按照教程进入 Security
模块和 Keychain
api。包装器似乎没问题,但是当我尝试将密码设置到钥匙串中时,出现状态编号为 -50 的错误。
import Security
class SecureStore {
private func setupQueryDictionary(forKey key: String) throws -> [CFString: Any] {
guard let keyData = key.data(using: .utf8) else {
print("Error! Cannot convert the key to the expected format")
throw SecureStoreError.invalidContent
}
let query: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
kSecAttrAccount: keyData]
return query
}
func set(entry: String, forKey key: String) throws {
guard !entry.isEmpty && !key.isEmpty else {
print("Cant add an empty string to the keychain")
throw SecureStoreError.queryEmptyWhenSet
}
try removeEntry(forKey: key)
var queryDictionary = try setupQueryDictionary(forKey: key)
queryDictionary[kSecClass] = entry.data(using: .utf8)
let status = SecItemAdd(queryDictionary as CFDictionary, nil)
guard status == errSecSuccess else {
print("status ==> ", status.description)
throw SecureStoreError.failureOnWrite(status)
}
}
func removeEntry(forKey key: String) throws {
guard !key.isEmpty else {
print("key must be valid")
throw SecureStoreError.queryEmptyWhenDelete
}
let queryDictionary = try setupQueryDictionary(forKey: key)
SecItemDelete(queryDictionary as CFDictionary)
}
func entry(forKey key: String) throws -> String? {
guard !key.isEmpty else {
print("key must be valid")
throw SecureStoreError.invalidContent
}
var queryDictionary = try setupQueryDictionary(forKey: key)
queryDictionary[kSecReturnData] = kCFBooleanTrue
queryDictionary[kSecMatchLimit] = kSecMatchLimitOne
var data: AnyObject?
let status = SecItemCopyMatching(queryDictionary as CFDictionary, &data)
guard status == errSecSuccess else {
print("status ==> ", status)
throw SecureStoreError.failureOnRead(status)
}
guard let itemData = data as? Data, let result = String(data: itemData, encoding: .utf8) else {
return nil
}
return result
}
}
enum SecureStoreError: Error {
case invalidContent
case queryEmptyWhenSet
case queryEmptyWhenDelete
case failureOnWrite(OSStatus)
case failureOnRead(OSStatus)
}
extension SecureStoreError: LocalizedError {
public var errorDescription: String? {
switch self {
case .invalidContent:
return NSLocalizedString("Cannot convert to the .utf8 format", comment: "")
case .queryEmptyWhenSet:
return NSLocalizedString("for set(:,:), parameters cannot be empty ", comment: "")
case .queryEmptyWhenDelete:
return NSLocalizedString("for removeEntry(:,:), parameters cannot be empty ", comment: "")
case .failureOnWrite(let status):
return NSLocalizedString("Error when write to keychain item \(status.description)", comment: "")
case .failureOnRead(let status):
return NSLocalizedString("Error when read to keychain item \(status.description)", comment: "")
}
}
}
Wrapper 对我来说似乎没问题,但我无法理解错误背后的真正问题。
我已经完成了这些:
1- 在 Xcode 目标中添加功能并设置一个组。
2- 在模拟器中试过,得到同样的错误
3-我在主线程试过了,没效果。
这是我的来电者:
let security = SecureStore.init()
do {
try security.set(entry: "myPassword12345.12345", forKey: "_passwordForFacebook")
let password = try security.entry(forKey: "_passwordForFacebook")
print("password > ", password )
} catch {
print("error > ", error.localizedDescription)
}
提前致谢。
这可能是由于创建查询错误所致。对于通用密码,该项目应如下所示:
let query = [
kSecClass: kSecClassGenericPasswor,
kSecAttrAccount: "_passwordForFacebook",
kSecAttrValueData: Data("myPassword12345.12345".utf8)
] as CFDictionary
目前,您正在将 kSecClass
设置为密码值。
queryDictionary[kSecClass] = entry.data(using: .utf8) // <-- this is invalid
这应该可以解决您的问题:
queryDictionary[kSecValueData] = entry.data(using: .utf8)
我正在尝试编写一个包装器,按照教程进入 Security
模块和 Keychain
api。包装器似乎没问题,但是当我尝试将密码设置到钥匙串中时,出现状态编号为 -50 的错误。
import Security
class SecureStore {
private func setupQueryDictionary(forKey key: String) throws -> [CFString: Any] {
guard let keyData = key.data(using: .utf8) else {
print("Error! Cannot convert the key to the expected format")
throw SecureStoreError.invalidContent
}
let query: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
kSecAttrAccount: keyData]
return query
}
func set(entry: String, forKey key: String) throws {
guard !entry.isEmpty && !key.isEmpty else {
print("Cant add an empty string to the keychain")
throw SecureStoreError.queryEmptyWhenSet
}
try removeEntry(forKey: key)
var queryDictionary = try setupQueryDictionary(forKey: key)
queryDictionary[kSecClass] = entry.data(using: .utf8)
let status = SecItemAdd(queryDictionary as CFDictionary, nil)
guard status == errSecSuccess else {
print("status ==> ", status.description)
throw SecureStoreError.failureOnWrite(status)
}
}
func removeEntry(forKey key: String) throws {
guard !key.isEmpty else {
print("key must be valid")
throw SecureStoreError.queryEmptyWhenDelete
}
let queryDictionary = try setupQueryDictionary(forKey: key)
SecItemDelete(queryDictionary as CFDictionary)
}
func entry(forKey key: String) throws -> String? {
guard !key.isEmpty else {
print("key must be valid")
throw SecureStoreError.invalidContent
}
var queryDictionary = try setupQueryDictionary(forKey: key)
queryDictionary[kSecReturnData] = kCFBooleanTrue
queryDictionary[kSecMatchLimit] = kSecMatchLimitOne
var data: AnyObject?
let status = SecItemCopyMatching(queryDictionary as CFDictionary, &data)
guard status == errSecSuccess else {
print("status ==> ", status)
throw SecureStoreError.failureOnRead(status)
}
guard let itemData = data as? Data, let result = String(data: itemData, encoding: .utf8) else {
return nil
}
return result
}
}
enum SecureStoreError: Error {
case invalidContent
case queryEmptyWhenSet
case queryEmptyWhenDelete
case failureOnWrite(OSStatus)
case failureOnRead(OSStatus)
}
extension SecureStoreError: LocalizedError {
public var errorDescription: String? {
switch self {
case .invalidContent:
return NSLocalizedString("Cannot convert to the .utf8 format", comment: "")
case .queryEmptyWhenSet:
return NSLocalizedString("for set(:,:), parameters cannot be empty ", comment: "")
case .queryEmptyWhenDelete:
return NSLocalizedString("for removeEntry(:,:), parameters cannot be empty ", comment: "")
case .failureOnWrite(let status):
return NSLocalizedString("Error when write to keychain item \(status.description)", comment: "")
case .failureOnRead(let status):
return NSLocalizedString("Error when read to keychain item \(status.description)", comment: "")
}
}
}
Wrapper 对我来说似乎没问题,但我无法理解错误背后的真正问题。
我已经完成了这些:
1- 在 Xcode 目标中添加功能并设置一个组。
2- 在模拟器中试过,得到同样的错误
3-我在主线程试过了,没效果。
这是我的来电者:
let security = SecureStore.init()
do {
try security.set(entry: "myPassword12345.12345", forKey: "_passwordForFacebook")
let password = try security.entry(forKey: "_passwordForFacebook")
print("password > ", password )
} catch {
print("error > ", error.localizedDescription)
}
提前致谢。
这可能是由于创建查询错误所致。对于通用密码,该项目应如下所示:
let query = [
kSecClass: kSecClassGenericPasswor,
kSecAttrAccount: "_passwordForFacebook",
kSecAttrValueData: Data("myPassword12345.12345".utf8)
] as CFDictionary
目前,您正在将 kSecClass
设置为密码值。
queryDictionary[kSecClass] = entry.data(using: .utf8) // <-- this is invalid
这应该可以解决您的问题:
queryDictionary[kSecValueData] = entry.data(using: .utf8)