带有客户端身份验证的GCDAsyncSocket [英] GCDAsyncSocket with Client Authentication

查看:637
本文介绍了带有客户端身份验证的GCDAsyncSocket的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用 CocoaAsyncSocket 在没有SSL的情况下将数据发送到我们的服务器。现在服务器端已经实现了带有客户端身份验证的SSL / TLS。为了在我们的应用程序中实现这一点,我获得了以下三个文件:

I have been using CocoaAsyncSocket to send data to our server without SSL. Now the server side has implemented SSL/TLS with client authentication. TO implement this in our app I was given the following three files:


  1. ca-chain.cert.pem

  2. client-test.cert.pem

  3. client-test.key.pem



<我将文件转换为iOS可读格式,如下所示:

I converted the files to iOS readable formats as below:


  1. ca-chain.cert.pem to ca-cert.cer

  2. client-test.cert.pem到client_cert.cer

  3. client-test.key.pem到client_key.p12

我的工作直到SSL。但是客户端身份验证有问题。

I have got it working till SSL. But having trouble with Client Authentication.

这是我的代码:

didConnectToHost:

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port;
{
    // Configure SSL/TLS settings

    NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithCapacity:3];

    // Allow self-signed certificates
    CFArrayRef certsArray = [self loadCertificates];
    [settings setObject:@0 forKey:GCDAsyncSocketSSLProtocolVersionMax];
    [settings setObject:[NSNumber numberWithBool:YES] forKey:GCDAsyncSocketManuallyEvaluateTrust];
    [settings setObject:(id)CFBridgingRelease(certsArray) forKey:GCDAsyncSocketSSLCertificates];
    [sock startTLS:settings];
}

didReceiveTrust:

- (void)socket:(GCDAsyncSocket *)sock didReceiveTrust:(SecTrustRef)trust completionHandler:(void (^)(BOOL shouldTrustPeer))completionHandler {
    NSString *caCertPath = [[NSBundle mainBundle] pathForResource:@"ca-cert" ofType:@"cer"];
    NSData *caCertData = [NSData dataWithContentsOfFile:caCertPath];

    NSString *clientCertPath = [[NSBundle mainBundle] pathForResource:@"client_cert" ofType:@"cer"];
    NSData *clientCertData = [NSData dataWithContentsOfFile:clientCertPath];

    OSStatus status = -1;
    SecTrustResultType result = kSecTrustResultDeny;

    if(caCertData && clientCertData)
    {
    SecCertificateRef   cert1;
    cert1 = SecCertificateCreateWithData(NULL, (__bridge CFDataRef) caCertData);

    SecCertificateRef   cert2;
    cert2 = SecCertificateCreateWithData(NULL, (__bridge CFDataRef) clientCertData);

    const void *ref[] = {cert1,cert2};
    CFArrayRef ary = CFArrayCreate(NULL, ref, 2, NULL);

    SecTrustSetAnchorCertificates(trust, ary);

    status = SecTrustEvaluate(trust, &result);
}
else
{
    NSLog(@"local certificates could not be loaded");
    completionHandler(NO);
}

if ((status == noErr && (result == kSecTrustResultProceed || result == kSecTrustResultUnspecified)))
{
    completionHandler(YES);
}
else
{
    CFArrayRef arrayRefTrust = SecTrustCopyProperties(trust);
    NSLog(@"error in connection occured\n%@", arrayRefTrust);

    completionHandler(NO);
}
}  

loadCertificates:

-(CFArrayRef) loadCertificates
{
NSString *clientKeyPath = [[NSBundle mainBundle] pathForResource:@"client_key" ofType:@"p12"];
NSData* clientKeyData = [NSData dataWithContentsOfFile:clientKeyPath];
NSLog(@"key : %@",[[NSString alloc] initWithData:clientKeyData encoding:NSASCIIStringEncoding]);

CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain(clientKeyData);
CFStringRef password = CFSTR("_mypassword_");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);

CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items);
CFRelease(options);
CFRelease(password);

if(securityError == errSecSuccess)
    NSLog(@"Success opening p12 certificate.");

CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
SecIdentityRef myIdent = (SecIdentityRef)CFDictionaryGetValue(identityDict,
                                                              kSecImportItemIdentity);


NSString *clientCertPath = [[NSBundle mainBundle] pathForResource:@"client_cert" ofType:@"cer"];
NSData *clientCertData = [NSData dataWithContentsOfFile:clientCertPath];

SecCertificateRef clientCert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef) clientCertData);

//SecIdentityRef certArray[1] = { myIdent };

const void *ref[] = {myIdent, clientCert};
CFArrayRef myCerts = CFArrayCreate(NULL, ref, 2, NULL);



//    NSString *caCertPath = [[NSBundle mainBundle] pathForResource:@"ca-cert" ofType:@"cer"];
//    NSData *caCertData = [NSData dataWithContentsOfFile:caCertPath];
//
//    SecCertificateRef caCert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef) caCertData);
//
//    const void *ref[] = {clientCert, myIdent, caCert};
//    CFArrayRef myCerts = CFArrayCreate(NULL, ref, 3, NULL);


return myCerts;
}

我一直在努力进行客户身份验证两天。我现在收到此错误:

I have been struggling with client authentication for two days. I get this error for now:

2017-03-13 15:35:40.777 MPS[79612:1478858] GCDAsyncSocket socketDidDisconnect Error - Error Domain=kCFStreamErrorDomainSSL Code=-9806 "(null)" UserInfo={NSLocalizedRecoverySuggestion=Error code definition can be found in Apple's SecureTransport.h}

我确实读过CocoaAyncSocket库与manualy信任评估的客户端身份验证有问题。我尝试了这里提到的解决方法:通过手动信任评估支持客户端身份验证没有运气。我找不到我错过的东西。

I did read that the CocoaAyncSocket library is having issue with client authentication with manualy trust evaluation. I tried the workaround as mentioned here: Support for client side authentication with manual trust evaluation Still no luck. I could not find what I'm missing.

提前致谢!
-Uma

Thanks In Advance! -Uma

推荐答案

代码一切都很好。我希望这有助于寻找答案的人。然而问题是文件转换。当我使用来自其他人的转换文件时,它可以工作。

Everything is good with the code. I hope this helps someone looking for answer. The problem however was with file conversion. When I used converted files from another person, it worked.

这篇关于带有客户端身份验证的GCDAsyncSocket的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆