ios - SecItemUpdate() 不断返回 errSecParam,我不明白为什么

标签 ios swift ios8 keychain

这是负责将值添加到加密存储中的整个函数。这是在 XCode 6 中的 iPhone6 模拟器上运行的。

func addOrUpdateGenericPassword(password: String, withService service: String, andAccount account: String, withAccessibility accessibility: SecurityAccessibility) -> ReturnStatus
{
    var sacObject: SecAccessControlRef
    var accessFlag: CFStringRef = kSecAttrAccessibleWhenUnlocked

    switch accessibility
    {
    case SecurityAccessibility.AccessibleAfterFirstUnlock:
        accessFlag = kSecAttrAccessibleAfterFirstUnlock
    case SecurityAccessibility.AccessibleAfterFirstUnlockThisDeviceOnly:
        accessFlag = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
    case SecurityAccessibility.AccessibleWhenUnlocked:
        accessFlag = kSecAttrAccessibleWhenUnlocked
    case SecurityAccessibility.AccessibleWhenUnlockedThisDeviceOnly:
        accessFlag = kSecAttrAccessibleWhenUnlockedThisDeviceOnly
    }

    if touchIDEnabled
    {
        sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessFlag, .USerPresence, nil).takeRetainedValue()
    }
    else
    {
        sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessFlag, nil, nil).takeRetainedValue()
    }

    var dataFromString: NSData = password.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
    var secKeys: [AnyObject] = [kSecClass, kSecAttrService, kSecAttrAccount, kSecValueData, kSecAttrAccessControl]
    var secValues: [AnyObject] = [kSecClassGenericPassword, service, account, dataFromString, sacObject]
    var update = NSDictionary(objects: secValues, forKeys: secKeys)

    // attempt to get the value first to determine if it exists
    let (currentValue, rStatus) = getGenericPasswordWith(service, andAccount: account)
    if rStatus == ReturnStatus.errSecSuccess
    {
        // Item already exists, so do an Update
        // We need to build a query for the existing value here instead of using the one we built for updating
        var query = buildQueryValueForLookupWith(service, andAccount: account)
        var status = SecItemUpdate(query, update)
        return getReturnStatusCodeForOSStatusCode(status)
    }
    else if rStatus == ReturnStatus.errSecItemNotFound
    {
        // Item does not exist so add it
        var status = SecItemAdd(update, nil)
        return getReturnStatusCodeForOSStatusCode(status)
    }
    else
    {
        // some other error occured and we dont know what is going on!
        println("Unknown errr occured when checking if item already exists.  Status = \(returnStatusCodeToString(rStatus))")
        return ReturnStatus.errSecUnknownError
    }
}
func buildQueryValueForLookupWith(service: String, andAccount account: String) -> NSDictionary
{
    var secKeys: NSArray = [kSecClass, kSecAttrService, kSecAttrAccount, kSecReturnData]
    var secValues: [AnyObject] = [kSecClassGenericPassword, service, account, true]
    var query = NSDictionary(objects: secValues, forKeys: secKeys)

    return query
}

该代码在我编写的 KeychainToolkit 类中。这是我在收到错误时如何调用它的示例:

var status = keychain.addOrUpdateGenericPassword(value!, withService: "healthBIT.lastSync", andAccount: key, withAccessibility: KeychainToolkit.SecurityAccessibility.AccessibleWhenUnlocked)

在这种情况下,值已经在钥匙串(keychain)中,上面的代码正确地检测到并使用 SecItemUpdate() 来更新它的值。但是,无论我做什么,它总是返回 errSecParam,而且我无法弄清楚我的参数在哪里出错。

我也尝试过完全删除新的 iOS8 kSecAttrAccessControl 部分,结果相同。

最佳答案

我猜您不希望 kSecReturnData 出现在 SecItemUpdate 的查询字典中。无法使用该 API 将数据返回给您。

关于ios - SecItemUpdate() 不断返回 errSecParam,我不明白为什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26332351/

相关文章:

ios - Swift Dictionary 的自定义序列

ios - showViewController 方法只显示模态视图

swift - NSURLUnsupportedURL -1002 看似有效的 URL

ios - animateWithDuration setFrame 不工作

ios - 实现 tableView :heightForFooterInSection: 时,UITableView 的页脚未随表格一起滚动

ios - Swift:从 EKEventStore 获取到 tableView 数据后对 EKEvents 进行日期排序

ios - iOS 中的手电筒闪光灯

ios 8 addSubview 导致后台黑屏

ios - 为什么 'present as popover' segue 覆盖了整个屏幕?

ios - 如何将包含\u转义字符的JSON解码为UTF8 NSString?