在 Swift 中使用 SecKeychainCreate

Hen*_*mak 1 security macos keychain swift

我正在编写一个应该维护自定义钥匙串的 OS X 应用程序,我正在尝试使用安全框架的 API 来创建钥匙串,但是,我似乎无法让它在 Swift 下编译。

这是我所拥有的,假设它path包含一个可能存在的钥匙串的路径:

let pathName = (path as NSString).UTF8String
var keychain: Unmanaged<SecKeychain>?

var status = withUnsafeMutablePointer(&keychain) { pointer in
    SecKeychainOpen(pathName, pointer)
}

if status != errSecSuccess {
    status = withUnsafeMutablePointer(&keychain) { pointer in
        SecKeychainCreate(pathName, UInt32(0), nil, false, nil, pointer)
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨 SecKeychainCreate 调用中的类型,但是,我不明白我做错了什么。

Cannot invoke 'withUnsafeMutablePointer' with an argument list of type '(inout Unmanaged<SecKeychain>?, (_) -> _)'
Run Code Online (Sandbox Code Playgroud)

如果我稍微修改第二个闭包,我会收到这个编译器错误:

Cannot invoke 'SecKeychainCreate' with an argument list of type '(UnsafePointer<Int8>, UInt32, nil, Bool, nil, (UnsafeMutablePointer<Unmanaged<SecKeychain>?>))'
Run Code Online (Sandbox Code Playgroud)

我感谢所有的建议。

Mar*_*n R 5

promptUser参数SecKeychainCreate()有 type Boolean,它是一个“Mac OS 历史类型”和一个别名UInt8,所以它与Swift 1.2Bool中的Swift不同。(比较类型 'Boolean' 不符合类似问题的协议 'BooleanType'。)这意味着您必须通过Boolean(0)而不是false

SecKeychainCreate(pathName, UInt32(0), nil, Boolean(0), nil, pointer)
Run Code Online (Sandbox Code Playgroud)

补充说明:

  • withUnsafeMutablePointer()不需要,您可以传递&keychain 给钥匙串功能。
  • (path as NSString).UTF8String不需要,您可以将 Swift 字符串传递给需要const char *参数的 C 函数,将字符串值与 UnsafePointer<UInt8> 函数参数行为进行比较
  • 通过nil如密码SecKeychainCreate(),如果只允许promptUserTRUE,否则它会导致“参数错误(-50)”。
  • SecKeychainOpen()即使钥匙串文件不存在也会成功。根据文档,您必须检查 SecKeychainGetStatus(). 或者,您可以尝试先创建钥匙串文件,例如在Open Local Items Keychain? .

一起:

let path = "/path/to/my.keychain"
var keychain: Unmanaged<SecKeychain>?

var status = SecKeychainCreate(path, 0, "", Boolean(0), nil, &keychain)
if status == OSStatus(errSecDuplicateKeychain) {
    status = SecKeychainOpen(path, &keychain)
}
Run Code Online (Sandbox Code Playgroud)

Swift 2 / Xcode 7 beta 5 开始, Mac 类型Boolean被映射到 Swift as Bool,并且钥匙链函数不再返回非托管对象:

let path = "/path/to/my.keychain"
var keychain: SecKeychain?

var status = SecKeychainCreate(path, 0, "", false, nil, &keychain)
if status == OSStatus(errSecDuplicateKeychain) {
    status = SecKeychainOpen(path, &keychain)
}
Run Code Online (Sandbox Code Playgroud)