2013-06-10 10 views
5

Wir haben einen WebSocket-Sicherheitsserver, der mit SSL arbeitet. Wir hoffen, ein Client-SSL-Zertifikat in unseren iOS-Client zu legen, um die Sicherheit bei der Kommunikation mit dem Server zu gewährleisten.Wie kann ich ein Client-SSL-Zertifikat an einen Server senden, indem ich CFStream in meiner iOS-App verwende?

Da wir WebSocket verwenden, verwenden wir im iOS-Client SocketRocket (Objective-C WebSocket-Clientbibliothek), um die WebSocket-Kommunikation zu implementieren.

Das Problem ist, ich habe keine Ahnung, wie ich mein Client-SSL-Zertifikat an den Server senden.

Ich kann die Eigenschaften von CFStream wie kCFStreamPropertySocketSecurityLevel festlegen. Aber ich weiß nicht, wie es funktioniert. Und ich kann keine Dokumente über Zertifikat in CFStream finden.

Ich weiß, dass wenn wir eine Verbindung zu einem HTTPS-Server herstellen müssen, können wir didReceiveAuthenticationChallenge in NSURLConnection verwenden. Aber wie ich weiß, gab es in CFStream kein Gegenstück.

Könnte jemand Ideen haben?

Antwort

12

Nach viel lernen und ausprobieren, kann ich mich jetzt selbst beantworten. Hoffe auch, dass es für dich nützlich sein wird.

Eigentlich, was ich brauche, ist Client-SSL-Authentifizierung mit CFStream implementieren. Also muss ich diese tun:

  1. Put PKCS # 12-Datei in meiner app Bundle
  2. Lesen Sie diese Datei als NSData-pkcsData
  3. Verwenden Sie die Methode SecPKCS12Import importieren pkcsData
  4. Get Identität und cert aus der Daten, die Sie oben importiert haben, und ein Zertifikat-Array generieren
  5. Setzen Sie das Array auf Schlüssel kCFStreamSSLCertificates in kCFStreamPropertySSLSettings von Ihrem CFWriteStreamRef

Beispielcode unten:

// Read .p12 file 
    NSString *path = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"]; 
    NSData *pkcs12data = [[NSData alloc] initWithContentsOfFile:path]; 

    // Import .p12 data 
    CFArrayRef keyref = NULL; 
    OSStatus sanityChesk = SecPKCS12Import((__bridge CFDataRef)pkcs12data, 
             (__bridge CFDictionaryRef)[NSDictionary 
                    dictionaryWithObject:@"123456" 
                    forKey:(__bridge id)kSecImportExportPassphrase], 
             &keyref); 
    if (sanityChesk != noErr) { 
    NSLog(@"Error while importing pkcs12 [%ld]", sanityChesk); 
    } else 
    NSLog(@"Success opening p12 certificate."); 

    // Identity 
    CFDictionaryRef identityDict = CFArrayGetValueAtIndex(keyref, 0); 
    SecIdentityRef identityRef = (SecIdentityRef)CFDictionaryGetValue(identityDict, 
                    kSecImportItemIdentity); 

    // Cert 
    SecCertificateRef cert = NULL; 
    OSStatus status = SecIdentityCopyCertificate(identityRef, &cert); 
    if (status) 
    NSLog(@"SecIdentityCopyCertificate failed."); 

    // the certificates array, containing the identity then the root certificate 
    NSArray *myCerts = [[NSArray alloc] initWithObjects:(__bridge id)identityRef, (__bridge id)cert, nil]; 

    // 
    [SSLOptions setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredRoots]; 
    [SSLOptions setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates]; 
    [SSLOptions setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot]; 
    [SSLOptions setObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCFStreamSSLValidatesCertificateChain]; 
    [SSLOptions setObject:@"test.domain.com:443" forKey:(NSString *)kCFStreamSSLPeerName]; 
    [SSLOptions setObject:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString*)kCFStreamSSLLevel]; 
    [SSLOptions setObject:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString*)kCFStreamPropertySocketSecurityLevel]; 
    [SSLOptions setObject:myCerts forKey:(NSString *)kCFStreamSSLCertificates]; 
    [SSLOptions setObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCFStreamSSLIsServer]; 

    [_outputStream setProperty:SSLOptions 
         forKey:(__bridge id)kCFStreamPropertySSLSettings]; 

Weil ich SocketRocket verwenden, habe ich diesen Code in meiner eigenen Gabel hinzugefügt: https://github.com/nickcheng/SocketRocket

+0

Genau das, was ich für ein schnelles Turn-around-Projekt benötigt! Vielen Dank für das Posten des Codes. –

+0

danke für die Freigabe! – thamster

+0

Omg, vielen Dank! Ich habe so viel Zeit damit verschwendet. Gut gemacht –

Verwandte Themen