该网站的服务,我想消费,需要一个客户端证书。我怎样才能把我的证书呢?
要进一步阐述我不明白如何创建 SecIdentityRef 。
在我的 NSURLConnection的 didReceiveAuthenticationChallenge 我在 ServerTrust :
如果挑战别的吗?.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate { VAR secIdent:SecIdentityRef = ????????? VAR certCred = NSURLCredential(身份:secIdent,证书:[getClientCertificate()],持久性:NSURLCredentialPersistence.Permanent) 挑战.sender.useCredential?(certCred,forAuthenticationChallenge:挑战!) }的 getClientCertificate 方法:
FUNC getClientCertificate() - GT; SecCertificateRef{ 让mainBundle:一个NSBundle = NSBundle.mainBundle() VAR mainBund = mainBundle.pathForResource(iosClientCert,ofType:CER)//导出的证书DER格式。 VAR键:NSData的NSData的=(contentsOfFile:mainBund)! VAR turnToCert:SecCertificateRef = SecCertificateCreateWithData(kCFAllocatorDefault,键).takeRetainedValue() 返回turnToCert;}解决方案
从技术上讲,如果有人知道我需要实施斯威夫特,他使用,以获得NSURLCredential对象的连接下面的Objective-C的实施;基于包含在一个PKCS12密钥库私钥和X509证书对。
对不起,我没有获得与斯威夫特的解决方案的来源。我所知道的是,NSURLCredential返回到斯威夫特,并直接在HTTP URL连接有使用。这是与此类似,虽然。
我不是一个iOS的开发,所以我不能帮你解决了桥接雨燕的一部分。
- (无效)getMessageWithURL:(* NSString的)网址{ NSURL * URL = [NSURL URLWithString:URL] NSMutableURLRequest *请求= [[NSMutableURLRequest的alloc]初始化]; [要求setURL:URL] [要求setHTTPMethod:@GET]; NSURLConnection的*连接= [[NSURLConnection的页头] initWithRequest:要求委托:自我]; [连接个体经营];} - (无效)postMessageWithURL:(* NSString的)网址withContent:(* NSString的)含量{ NSData的* POSTDATA = [内容dataUsingEncoding:NSUTF8StringEncoding]; * NSString的postLength = [的NSString stringWithFormat:@%D,[POSTDATA长度]]; NSURL * myURL = [NSURL URLWithString:URL] NSMutableURLRequest *请求= [NSMutableURLRequest requestWithURL:myURL的CachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60]; [要求setHTTPMethod:@POST]; [申请的setValue:postLength forHTTPHeaderField:@内容长度]; [申请的setValue:@应用程序/ JSONforHTTPHeaderField:@的Content-Type]; [要求setHTTPBody:POSTDATA]; NSURLConnection的*连接= [[NSURLConnection的页头] initWithRequest:要求委托:自我]; [连接个体经营];} - (BOOL)连接:(NSURLConnection的*)连接canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { 返回[protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];} - (无效)连接:(NSURLConnection的*)连接didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *){挑战 的NSLog(@didReceiveAuthenticationChallenge);} - (无效)连接:(NSURLConnection的*)连接didReceiveResponse:(NSURLResponse *){响应 responseData = [[NSMutableData的alloc]初始化];} - (无效)连接:(NSURLConnection的*)连接didReceiveData:(NSData的*)数据{ [responseData appendData:数据]} - (无效)连接:(NSURLConnection的*)连接didFailWithError:(NSError *)错误{ 的NSLog(@无法获取数据); 的NSLog(@%@,错误);} - (无效)connectionDidFinishLoading:(NSURLConnection的*)连接{ 的NSLog(@成功了!接收数据的%lu个字节,(无符号长)responseData 长度]); * NSString的responseString = [[NSString的页头] initWithData:responseData编码:NSUTF8StringEncoding]; 的NSLog(@%@,responseString); [桥callHandler:handlerName数据:responseString];} - (无效)连接:(NSURLConnection的*)连接willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *){挑战 / * 读出证书和创建的标识 * / NSArray的*路径= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES); 的NSString * documentsDirectory =路径[0]; //获取文件目录 NSData的* p12data = [CertificateManager getP12Data] //实际上返回一个包含一个有效的PKCS12证书的字节数组 如果(!p12data){ 返回; NSAssert(p12data,@无法加载P12文件...); } CFStringRef密码= CFSTR(密码); 常量无效*键[] = {} kSecImportExportPassphrase; 常量无效*值[] = {}密码; CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL,键,值1,NULL,NULL); CFArrayRef p12Items; OSStatus结果= SecPKCS12Import((__桥CFDataRef)p12data,optionsDictionary,&安培; p12Items); 如果(结果==诺尔){ CFDictionaryRef identityDict = CFArrayGetValueAtIndex(p12Items,0); SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity); SecCertificateRef certRef; SecIdentityCopyCertificate(identityApp,&安培; certRef); SecCertificateRef certArray [1] = {certRef}; CFArrayRef myCerts = CFArrayCreate(NULL,(无效*)certArray,1,NULL); CFRelease(certRef); NSURLCredential *证书= [NSURLCredential credentialWithIdentity:identityApp证书:无持久性:NSURLCredentialPersistenceNone]; CFRelease(myCerts); [挑战发件人] useCredential:凭证forAuthenticationChallenge:挑战] } 其他{ //证书无效或密码无效发出的证明书 的NSLog(@无效的证书或密码); NSError *错误= [NSError errorWithDomain:NSOSStatusErrorDomain code:导致用户信息:无]; 返回; }}编辑:喀拉HAR,很搞笑,downvoting我两次,当你自己没有理会,而赏金小涨。 *叽*
不管怎么说,使用上面下面,你只需要从斯威夫特访问它。
FUNC连接(连接:NSURLConnection的,willSendRequestForAuthenticationChallenge挑战:NSURLAuthenticationChallenge){ 如果让p12Data = UserManager.currentP12, 让凭证= CertificateManager.getCredentialsForP12(p12Data)作为? NSURLCredential { challenge.sender.useCredential(凭证,forAuthenticationChallenge:挑战) }其他{ UIApplication.sharedApplication()。networkActivityIndicatorVisible = FALSE }}使用此。
+(ID)getCredentialsForP12:(NSData的*){P12 NSData的* p12data = P12; 常量无效*键[] = {} kSecImportExportPassphrase; 常量无效*值[] = {CFSTR(thePassword)}; CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL,键,值1,NULL,NULL); CFArrayRef p12Items; OSStatus结果= SecPKCS12Import((__桥CFDataRef)p12data,optionsDictionary,&安培; p12Items); 如果(结果==诺尔){ CFDictionaryRef identityDict = CFArrayGetValueAtIndex(p12Items,0); SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity); SecCertificateRef certRef; SecIdentityCopyCertificate(identityApp,&安培; certRef); SecCertificateRef certArray [1] = {certRef}; CFArrayRef myCerts = CFArrayCreate(NULL,(无效*)certArray,1,NULL); CFRelease(certRef); NSURLCredential *证书= [NSURLCredential credentialWithIdentity:identityApp证书:无持久性:NSURLCredentialPersistenceNone]; CFRelease(myCerts); 返回凭证; } 其他{ //证书无效或密码无效发出的证明书 的NSLog(@无效的证书或密码); UIAlertView中* AV = [[UIAlertView中页头] initWithTitle:@错误消息:@无效的证书或通过委托:无cancelButtonTitle:@OKotherButtonTitles:无]; [AV秀] NSError *错误= [NSError errorWithDomain:NSOSStatusErrorDomain code:导致用户信息:无]; 回零; }编辑:上面的一个迅速的版本是在这里,虽然这是很混乱的,我们只是宁可不使用它
VAR p12items:非托管< CFArrayRef&GT ;? 让指数:CFIndex = 1 让密码:CFString字符串=密码 让键= kSecImportExportPassphrase.takeRetainedValue()作为字符串 变种值= [unsafeAddressOf(密码)] VAR键= [unsafeAddressOf(钥匙) VAR keyCallbacks = kCFTypeDictionaryKeyCallBacks VAR valueCallbacks = kCFTypeDictionaryValueCallBacks 让长度:CFIndex = p12Data.length 让p12CfData:CFData = CFDataCreate(kCFAllocatorDefault,UnsafePointer<&UINT8 GT;(p12Data.bytes),长度) 让选项= CFDictionaryCreate(kCFAllocatorDefault,和放大器;键,&安培;价值指数,和放大器; keyCallbacks,&安培; valueCallbacks) 让结果= SecPKCS12Import(p12CfData,期权和放大器; p12items) 如果结果== {诺尔 让idIndex:CFIndex = 0 VAR项目= p12items?.takeRetainedValue() VAR identityDict = CFArrayGetValueAtIndex(项目!idIndex) VAR键= kSecImportItemIdentity.takeRetainedValue()作为字符串 VAR keyAddress = unsafeAddressOf(键) VAR identityApp:SecIdentityRef = CFDictionaryGetValue(identityDict,keyAddress) VAR certRef:非托管< SecCertificateRef&GT ;? SecIdentityCopyCertificate(identityApp,&安培; certRef) VAR证书:SecCertificateRef = certRef .takeRetainedValue()! VAR certArray = [unsafeAddressOf(CERT) VAR arrayCallback = kCFTypeArrayCallBacks VAR myCerts:CFArrayRef = CFArrayCreate(kCFAllocatorDefault,&安培; certArray,索引和安培; arrayCallback); 让凭据:NSURLCredential = NSURLCredential(身份:identityApp,证书:[AnyObject](),持久性:NSURLCredentialPersistence.None)The web service I want to consume requires a client certificate. How can I send my certificate to it?
To further elaborate I don't understand how to create the SecIdentityRef.
In my NSURLConnection didReceiveAuthenticationChallenge I've got this conditional after ServerTrust:
else if challenge?.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate { var secIdent : SecIdentityRef = ????????? var certCred = NSURLCredential(identity: secIdent, certificates: [getClientCertificate()], persistence: NSURLCredentialPersistence.Permanent) challenge?.sender.useCredential(certCred, forAuthenticationChallenge: challenge!) }The getClientCertificate method:
func getClientCertificate() -> SecCertificateRef { let mainBundle : NSBundle = NSBundle.mainBundle() var mainBund = mainBundle.pathForResource("iosClientCert", ofType: "cer") //exported the cert in der format. var key : NSData = NSData(contentsOfFile: mainBund!)! var turnToCert : SecCertificateRef = SecCertificateCreateWithData(kCFAllocatorDefault, key).takeRetainedValue() return turnToCert; }解决方案
Technically, when someone I know needed the implementation in Swift, he used the following Objective-C implementation in order to get the NSURLCredential object to the connection; based on the private key and X509 Certificate pair contained in a PKCS12 keystore.
Sorry, I don't have access to the source with the Swift solution. All I know is that the NSURLCredential was returned to Swift, and used directly in the http url connection there. It's similar to this one, though.
I'm not an iOS dev so I won't be able to help you out with the "bridging to Swift" part.
- (void)getMessageWithURL:(NSString *)url { NSURL *URL = [NSURL URLWithString:url]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setURL:URL]; [request setHTTPMethod:@"GET"]; NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; [connection self]; } - (void)postMessageWithURL:(NSString *)url withContent:(NSString *)content { NSData *postData = [content dataUsingEncoding:NSUTF8StringEncoding]; NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]]; NSURL *myURL = [NSURL URLWithString:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60]; [request setHTTPMethod:@"POST"]; [request setValue:postLength forHTTPHeaderField:@"Content-Length"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:postData]; NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; [connection self]; } - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]; } - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { NSLog(@"didReceiveAuthenticationChallenge"); } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { responseData = [[NSMutableData alloc] init]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [responseData appendData:data]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { NSLog(@"Unable to fetch data"); NSLog(@"%@", error); } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { NSLog(@"Succeeded! Received %lu bytes of data", (unsigned long)[responseData length]); NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; NSLog(@"%@", responseString); [bridge callHandler:handlerName data:responseString]; } - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { /* Reading the certificate and creating the identity */ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = paths[0]; // Get documents directory NSData *p12data = [CertificateManager getP12Data]; //returns essentially a byte array containing a valid PKCS12 certificate if (!p12data) { return; NSAssert(p12data, @"Couldn't load p12 file..."); } CFStringRef password = CFSTR("password"); const void *keys[] = {kSecImportExportPassphrase}; const void *values[] = {password}; CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); CFArrayRef p12Items; OSStatus result = SecPKCS12Import((__bridge CFDataRef) p12data, optionsDictionary, &p12Items); if (result == noErr) { CFDictionaryRef identityDict = CFArrayGetValueAtIndex(p12Items, 0); SecIdentityRef identityApp = (SecIdentityRef) CFDictionaryGetValue(identityDict, kSecImportItemIdentity); SecCertificateRef certRef; SecIdentityCopyCertificate(identityApp, &certRef); SecCertificateRef certArray[1] = {certRef}; CFArrayRef myCerts = CFArrayCreate(NULL, (void *) certArray, 1, NULL); CFRelease(certRef); NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identityApp certificates:nil persistence:NSURLCredentialPersistenceNone]; CFRelease(myCerts); [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; } else { // Certificate is invalid or password is invalid given the certificate NSLog(@"Invalid certificate or password"); NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:result userInfo:nil]; return; } }EDIT: Har har, very funny, downvoting me twice when you yourself didn't bother while the bounty was up. *grumble *
Anyways, to use the following above, you just need to access it from Swift.
func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge) { if let p12Data = UserManager.currentP12, let credential = CertificateManager.getCredentialsForP12(p12Data) as? NSURLCredential { challenge.sender.useCredential(credential, forAuthenticationChallenge: challenge) } else { UIApplication.sharedApplication()workActivityIndicatorVisible = false } }That uses this.
+ (id)getCredentialsForP12:(NSData *)p12 { NSData* p12data = p12; const void *keys[] = {kSecImportExportPassphrase}; const void *values[] = {CFSTR("thePassword")}; CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); CFArrayRef p12Items; OSStatus result = SecPKCS12Import((__bridge CFDataRef) p12data, optionsDictionary, &p12Items); if (result == noErr) { CFDictionaryRef identityDict = CFArrayGetValueAtIndex(p12Items, 0); SecIdentityRef identityApp = (SecIdentityRef) CFDictionaryGetValue(identityDict, kSecImportItemIdentity); SecCertificateRef certRef; SecIdentityCopyCertificate(identityApp, &certRef); SecCertificateRef certArray[1] = {certRef}; CFArrayRef myCerts = CFArrayCreate(NULL, (void *) certArray, 1, NULL); CFRelease(certRef); NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identityApp certificates:nil persistence:NSURLCredentialPersistenceNone]; CFRelease(myCerts); return credential; } else { // Certificate is invalid or password is invalid given the certificate NSLog(@"Invalid certificate or password"); UIAlertView* av = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Invalid cert or pass" delegate:nil cancelButtonTitle:@"ok" otherButtonTitles: nil]; [av show]; NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:result userInfo:nil]; return nil; }EDIT: A swift version of the above is here, although it was messy enough that we rather just didn't use it.
var p12items : Unmanaged<CFArrayRef>? let index: CFIndex = 1 let password: CFString = "password" let key = kSecImportExportPassphrase.takeRetainedValue() as String var values = [unsafeAddressOf(password)] var keys = [unsafeAddressOf(key)] var keyCallbacks = kCFTypeDictionaryKeyCallBacks var valueCallbacks = kCFTypeDictionaryValueCallBacks let length: CFIndex = p12Data.length let p12CfData: CFData = CFDataCreate(kCFAllocatorDefault, UnsafePointer<UInt8>(p12Data.bytes), length) let options = CFDictionaryCreate(kCFAllocatorDefault, &keys, &values, index, &keyCallbacks, &valueCallbacks) let result = SecPKCS12Import(p12CfData, options, &p12items) if result == noErr { let idIndex: CFIndex = 0 var items = p12items?.takeRetainedValue() var identityDict = CFArrayGetValueAtIndex(items!, idIndex) var key = kSecImportItemIdentity.takeRetainedValue() as String var keyAddress = unsafeAddressOf(key) var identityApp: SecIdentityRef = CFDictionaryGetValue(identityDict, keyAddress) var certRef : Unmanaged<SecCertificateRef>? SecIdentityCopyCertificate(identityApp, &certRef) var cert: SecCertificateRef = certRef!.takeRetainedValue() var certArray = [unsafeAddressOf(cert)] var arrayCallback = kCFTypeArrayCallBacks var myCerts: CFArrayRef = CFArrayCreate(kCFAllocatorDefault, &certArray, index, &arrayCallback); let credential: NSURLCredential = NSURLCredential(identity: identityApp, certificates: [AnyObject](), persistence: NSURLCredentialPersistence.None)
更多推荐
斯威夫特的iOS客户端证书认证
发布评论