我正在使用mac app中的证书身份验证访问https网络服务器,因此我需要处理身份验证并提供我的证书(URLSession - > NSURLAuthenticationMethodClientCertificate - >调用SecPKCS12Import并从导入的证书中提取身份 - >从中创建NSURLCredential身份并在completionHandler中将其提供给服务器。)
但是在每次https请求之后,会显示“MYAPP想要在你的钥匙串中使用”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标志,但是我可以在没有控制台命令的情况下以编程方式执行吗?
答案 0 :(得分:1)
您可能需要多次构建和运行应用程序,这意味着第一次将证书添加到密钥链中,并且执行该证书的可执行文件被授权使用私钥。但是,当您进行一些更改并重建项目时,可执行文件已被替换,新的可执行文件无法访问私钥(当用户必须更新软件或因任何原因重新安装时,这也是一个问题)
我发现我必须做的是在使用后从钥匙链中删除证书,并在每次使用前重新添加。但是,我已经知道您可以授予应用程序标识符权限,以便在您的情况下也可以使用。
我在问题的答案中有一个代码示例:How do I kill the popup?