从 osx 钥匙串中检索钥匙

Retrieve key from osx keychain

我正在尝试从钥匙串中检索我的应用程序的密钥,以便它可以用于对服务器进行身份验证。我已成功将它存储在那里,但无法取回它。

func getClientKey(){
    let keyValptr:UnsafeMutablePointer<UnsafeMutableRawPointer?>?
    let lenPtr:UnsafeMutablePointer<UInt32>? = UInt32(13) //how do i do this?
    _ = SecKeychainFindGenericPassword(nil,
        UInt32(serviceName.characters.count), serviceName, 
        UInt32(accountName.characters.count), accountName, 
        lenPtr, keyValptr, nil)

    print(keyValptr)
 }

我已经评论了我遇到问题的行。我如何获得传递给函数的正确指针?它想要一个 UnsafeMutablePointer<UInt32>?(我会在其中选择实际值)

一般来说,当你想传递UnsafeMutablePoiner<T>?(或UnsafeMutablePoiner<T>)时,声明一个T类型的变量(不是指向T的指针)然后传递它作为输入参数(前缀 &)。

所以,具体到你的问题,你的传递方式keyValPtr也是错误的。

对于参数passwordLength: UnsafeMutablePointer<UInt32>?,需要声明一个UInt32类型的变量。 而对于passwordData: UnsafeMutablePointer<UnsafeMutableRawPointer?>?,你需要声明一个UnsafeMutableRawPointer?.

类型的变量

而且,不幸的是,在很多情况下这可能不是一个关键问题,当将 Swift String 直接传递给 UnsafePointer<Int8>? 时,您需要根据 UTF-8 表示来计算长度.

你可能需要这样写:

func getClientKey() {
    var keyVal: UnsafeMutableRawPointer? = nil
    var len: UInt32 = 13 //<- this value is ignored though...
    let status = SecKeychainFindGenericPassword(
        nil,
        UInt32(serviceName.utf8.count), serviceName, //### Use `utf8.count`
        UInt32(accountName.utf8.count), accountName, //### Use `utf8.count`
        &len,       //### to pass `UnsafeMutablePointer<UInt32>?`, declare a variable of `UInt32`.
        &keyVal,    //### to pass `UnsafeMutablePointer<UnsafeMutableRawPointer?>?`, declare a variable of `UnsafeMutableRawPointer?`.
        nil
    )

    if status == noErr {
        let keyData = Data(bytes: keyVal!, count: Int(len))
        //### As noted in the API reference of `SecKeychainFindGenericPassword`,
        // "You should use the SecKeychainItemFreeContent function to free the memory pointed to by this parameter."
        SecKeychainItemFreeContent(nil, keyVal)

        print(keyData as NSData)
        print(String(data: keyData, encoding: .utf8) ?? "?")
    } else {
        //You should not silently ignore erros...
        print("Error: \(status)")
    }
}