GCDAsyncSocket two way authentication

1.2k views Asked by At

I'm using GCD AsyncSocket to create client application to connect to server java create by SSLServer Socket with self-sign certificate. With one way authentication, I can init SSL socket and communication well. But with two way authentication, I don't know how to implement it. At iOS client, I will have a client's certificate and server will trust client base on this certificate. I can read certificate from .p12 file well too. Many thanks to any advice.

1

There are 1 answers

1
duong dang On BEST ANSWER

After many lucky process. It was resolved. With server andoird and client android follow in this tutorial : http://www.herongyang.com/JDK/SSL-Client-Authentication.html With 2 way authentication. Server will require client's certificate. You can call this at didConnectToHost delegate. NSMutableDictionary *sslSettings = [[NSMutableDictionary alloc] init];

    SecIdentityRef identityout; // You can get SecIdentityRef object from *.p12 keystore file. SSL Socket Server will authentication client base on this certificate. At server side, we will add client's certificate to trust manager.

    [sslSettings setObject:@0 forKey:GCDAsyncSocketSSLProtocolVersionMax];
    [sslSettings setObject:@YES forKey:GCDAsyncSocketManuallyEvaluateTrust]; // This will call a delegate method socket:(GCDAsyncSocket *)sock didReceiveTrust: ...
    [sslSettings setObject:[[NSArray alloc] initWithObjects:(__bridge id)(identityout), nil] forKey:GCDAsyncSocketSSLCertificates];        
    [self.asyncSocket startTLS:sslSettings];

At didReceiveTrust:(SecTrustRef)trust completionHandler:(void (^)(BOOL))completionHandler. Client will authenticate Server's certificate manual. You can get server's certificate with this code: SecCertificateRef serverCertificate = SecTrustGetCertificateAtIndex(trust, 0);

With self-sign certificate, you must add Server's certificate to keychain and check the Server's certificate with SecTrustEvaluate method. Or you can Compare server certificate and saved in this way:

SecCertificateRef serverCertificate = SecTrustGetCertificateAtIndex(trust, 0); SecCertificateRef savedCertificate = SecTrustGetCertificateAtIndex(self.saveServerTrust, 0);
    NSLog(@"Server's certificate subject: %@",summaryString);
    NSLog(@"Saved certificate subject: %@",summaryString1);


    if(nil == serverCertificate || nil == savedCertificate)
        NSLog(@"Faile");

CFDataRef serverCertificateData = SecCertificateCopyData(serverCertificate);
CFDataRef saveCertificateData = SecCertificateCopyData(savedCertificate);

const UInt8* const serverData = CFDataGetBytePtr(serverCertificateData);
const CFIndex serverDataSize = CFDataGetLength(serverCertificateData);
NSData* cert1 = [NSData dataWithBytes:serverData length:(NSUInteger)serverDataSize];

const UInt8* const SaveCertificateData = CFDataGetBytePtr(saveCertificateData);
const CFIndex SaveCertificateDataSize = CFDataGetLength(serverCertificateData);
NSData* cert2= [NSData dataWithBytes:SaveCertificateData length:(NSUInteger)SaveCertificateDataSize];

if (cert1 == nil || cert2 == nil) {
    NSLog(@"Certificate NULL");
    completionHandler(NO);
    return;
}

const BOOL equal = [cert1 isEqualToData:cert2];

if (equal) {

    NSLog(@"Certificate match");
    completionHandler(YES);
}
else{
    NSLog(@"Certificate not match");
    completionHandler(NO);
}`