使用Swift的SecKeychainCreate

时间:2015-08-08 17:35:29

标签: macos swift security keychain

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

以下是我所拥有的,假设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)
    }
}

编译器抱怨SecKeychainCreate调用中的类型,但是,我无法理解我做错了什么。

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

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

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

我感谢所有建议。

1 个答案:

答案 0 :(得分:4)

promptUser的{​​{1}}参数具有类型 SecKeychainCreate(),这是&#34; Mac OS的历史类型&#34;和Boolean的别名, 所以它与 Swift 1.2 中的Swift UInt8不同。 (比较Type 'Boolean' does not conform to protocol 'BooleanType'是否存在类似问题。)  这意味着你必须这样做 通过Bool代替Boolean(0)

false

补充说明:

  • SecKeychainCreate(pathName, UInt32(0), nil, Boolean(0), nil, pointer) 不需要,您可以通过withUnsafeMutablePointer() 到钥匙串的功能。
  • 不需要
  • &keychain,你可以传递一个Swift 字符串到期望(path as NSString).UTF8String参数的C函数, 比较String value to UnsafePointer<UInt8> function parameter behavior
  • 仅允许将const char *作为密码传递给nil 如果SecKeychainCreate()promptUser,否则会导致TRUE &#34;参数错误(-50)&#34;。
  • 即使密钥链文件没有,
  • 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)
}

Swift 2 / Xcode 7 beta 5 开始,映射了Mac类型Boolean 将Swift改为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)
}