secItemAdd keep return -50 error in swift

I believe the value for the kSecValueData key needs to be an NSData, not a String or NSString. Try encoding your string to data (with e.g. UTF-8 encoding). Untested snippet:

query[kSecValueData as String] = "b".dataUsingEncoding(NSUTF8StringEncoding)

For future reference, the error code -50 corresponds to errSecParam, which the SecBase.h header documents as meaning: "One or more parameters passed to a function were not valid." If you see this error again, try changing the values that you're passing in with your query dictionary.


Slightly updated Swift 5 version of add to/remove from keychain functionality:

@discardableResult
func addToKeychain(_ value: Data, tag: Data) -> Bool {
    let attributes: [String: Any] = [
        String(kSecClass): kSecClassKey,
        String(kSecAttrApplicationTag): tag,
        String(kSecValueData): value
    ]

    var result: CFTypeRef? = nil
    let status = SecItemAdd(attributes as CFDictionary, &result)
    if status == errSecSuccess {
        print("Successfully added to keychain.")
    } else {
        if let error: String = SecCopyErrorMessageString(status, nil) as String? {
            print(error)
        }

        return false
    }

    return true
}

@discardableResult
func removeFromKeychain(_ value: Data, tag: Data) -> Bool {
    let attributes: [String: Any] = [
        String(kSecClass): kSecClassKey,
        String(kSecAttrApplicationTag): tag,
        String(kSecValueData): value
    ]

    let status = SecItemDelete(attributes as CFDictionary)
    if status == errSecSuccess {
        print("Successfully removed from keychain.")
    } else {
        if let error: String = SecCopyErrorMessageString(status, nil) as String? {
            print(error)
        }

        return false
    }

    return true
}

Which can be used like this:

let value: Data = "key".data(using: .utf8)!
let tag: Data = "com.test.key".data(using: .utf8)!

removeFromKeychain(value, tag: tag)
addToKeychain(value, tag: tag)

Tags:

Ios

Keychain