2017-03-13 3 views
3

Ich habe CocoaAsyncSocket verwendet, um Daten an unseren Server ohne SSL zu senden. Jetzt hat die Serverseite SSL/TLS mit Client-Authentifizierung implementiert. dies in unserer App zu implementieren ich die folgenden drei Dateien gegeben wurde:GCDAsyncSocket mit Client-Authentifizierung

  1. ca-chain.cert.pem
  2. Client-test.cert.pem
  3. Client-test.key.pem

konvertiert ich die Dateien auf iOS lesbare Formate wie folgt:

  1. ca-chain.cert.pem bis ca-cert.cer
  2. Client-test.cert.pem
  3. Client-test.key.pem client_cert.cer

ich es bis SSL arbeiten gelernt haben client_key.p12. Aber Probleme mit der Client-Authentifizierung.

Hier ist mein Code:

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; 
} 

Ich habe seit zwei Tagen mit Client-Authentifizierung gekämpft. Ich erhalte diesen Fehler jetzt:

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} 

ich, dass die CocoaAyncSocket Bibliothek gelesen habe Problem mit Client-Authentifizierung mit manualy Vertrauen Auswertung mit. Ich habe den Workaround wie hier erwähnt versucht: Support for client side authentication with manual trust evaluation Immer noch kein Glück. Ich konnte nicht finden, was ich vermisse.

Vielen Dank im Voraus! -Uma

Antwort

1

Alles ist gut mit dem Code. Ich hoffe, das hilft jemandem auf der Suche nach einer Antwort. Das Problem war jedoch mit der Dateikonvertierung. Wenn ich konvertierte Dateien von einer anderen Person verwendete, funktionierte es.

Verwandte Themen