从osx keychain中检索密钥

时间:2017-02-11 00:59:52

标签: swift pointers 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>?(我会选择实际值是什么)

1 个答案:

答案 0 :(得分:1)

通常,当您想要传递UnsafeMutablePoiner<T>?(或UnsafeMutablePoiner<T>)时,您声明一个T类型的变量(不是指向T的指针)并将其传递为inout参数(前缀&)。

因此,针对您的问题,您传递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)")
    }
}