我正在从 mac 应用程序使用证书身份验证访问 https Web 服务器,因此我需要处理身份验证并提供我的证书(URLSession -> NSURLAuthenticationMethodClientCertificate -> 调用 SecPKCS12Import 并从导入的证书中提取身份 -> 从身份创建 NSURLCredential 并提供它在completionHandler 中发送到服务器)。
但每次 https 请求后,都会显示对话框“MYAPP 希望使用钥匙串(keychain)中的“privateKey”进行签名”:
我想避免出现此消息。我的应用程序已正确签名。我认为我需要在导入时设置证书的访问权限(我的应用程序的完全访问权限),我尝试使用 SecAccessCreate 和 SecPKCS12Import 选项来完成此操作:
func extractIdentity(certData:NSData, certPassword:String) -> IdentityAndTrust {
var identityAndTrust:IdentityAndTrust!
var securityError:OSStatus = errSecSuccess
var items:CFArray?
//let certOptions:CFDictionary = [ kSecImportExportPassphrase.takeRetainedValue() as String: certPassword ];
let index: CFIndex = 2
let passwordKey = kSecImportExportPassphrase as String;
let passwordValue: CFString = "PASSWORD";
let accessKey = kSecImportExportAccess as String;
var access:SecAccessRef? = nil;
SecAccessCreate("CERTIFICATE_NAME", nil, &access);
var keys = [unsafeAddressOf(accessKey), unsafeAddressOf(passwordKey)]
var values = [unsafeAddressOf(access!), unsafeAddressOf(passwordValue)]
var keyCallbacks = kCFTypeDictionaryKeyCallBacks
var valueCallbacks = kCFTypeDictionaryValueCallBacks
let options = CFDictionaryCreate(kCFAllocatorDefault, &keys, &values, index, &keyCallbacks, &valueCallbacks)
// import certificate to read its entries
securityError = SecPKCS12Import(certData, options, &items);
if securityError == errSecSuccess {
let certItems:CFArray = items as CFArray!;
let certItemsArray:Array = certItems as Array
let dict:AnyObject? = certItemsArray.first;
if let certEntry:Dictionary = dict as? Dictionary<String, AnyObject> {
// grab the identity
let identityPointer:AnyObject? = certEntry["identity"];
let secIdentityRef:SecIdentityRef = identityPointer as! SecIdentityRef!;
// grab the trust
let trustPointer:AnyObject? = certEntry["trust"];
let trustRef:SecTrustRef = trustPointer as! SecTrustRef;
// grab the certificate chain
var certRef:SecCertificate?
SecIdentityCopyCertificate(secIdentityRef, &certRef);
let certArray:NSMutableArray = NSMutableArray();
certArray.addObject(certRef as SecCertificateRef!);
identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certArray: certArray);
}
}
return identityAndTrust;
}
无论如何,它不起作用。如何避免出现此对话框?
此线程How do I add authorizations to code sign an app from new keychain without any human interaction与使用“security”命令导入证书有关,建议在导入证书时使用 -A 或 -T 标志,但我可以在没有控制台命令的情况下以编程方式执行此操作吗?
最佳答案
您可能多次构建和运行应用程序,这意味着证书第一次被添加到钥匙串(keychain)中,并且执行此操作的可执行文件被授权使用私钥。但是,当您进行一些更改并重建项目时,可执行文件被替换,并且新的可执行文件无权访问私钥(当您的用户因任何原因必须更新软件或重新安装时,这也是一个问题)。
我发现我必须做的是在使用后从钥匙串(keychain)中删除证书,并在每次使用前重新添加它。不过,我了解到您可以向应用程序标识符授予权限,这样这也适用于您的情况。
我的问题答案中有一个代码示例:How do I kill the popup?
关于iphone - 导入 p12 证书,可以完全访问我的应用程序的私钥 (OS X),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38126462/