2012-03-26 11 views
6

Ich versuche, einen HTTPS-Server in einer iOS-App zu erstellen, um als Proxy zwischen meiner Web-App und meinem externen Server zu fungieren.SSL-Identitätszertifikat zum Ausführen eines HTTPS-Servers unter iOS

Ich habe es geschafft, einen HTTP-Server durch Abhören eines Sockets zu erstellen, entweder dank CFSocketRef oder mithilfe der GCDAsyncSocket-Bibliothek. Ich habe auch einen Mac App einen HTTPS-Server ausgeführt wird, mit der GCDAsyncSocket Bibliothek und dank meiner Methode „Secure:“ make erfolgreich zu sein, unter dem sichert die Verbindung:

- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket 
{ 
    // (...) 
    // secure the connection 
    [self secureSocket:newSocket]; 
    // (...) 
} 

- (void)secureSocket:(GCDAsyncSocket *)sock 
{ 
    // The root self-signed certificate I have created 
    NSString *certificatePath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"cer"]; 
    NSData *certData = [[NSData alloc] initWithContentsOfFile:certificatePath]; 
    CFDataRef certDataRef = (CFDataRef)certData; 
    SecCertificateRef cert = SecCertificateCreateWithData(NULL, certDataRef); 
    [certData release]; 

    // the "identity" certificate 
    SecIdentityRef identityRef; 
    SecIdentityCreateWithCertificate(NULL, cert, &identityRef); 

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

    // the SSL configuration 
    NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithCapacity:3]; 
    [settings setObject:[NSNull null] forKey:(NSString *)kCFStreamSSLPeerName]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredRoots]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates]; 
    [settings setObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCFStreamSSLValidatesCertificateChain]; 
    [settings setObject:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString*)kCFStreamSSLLevel]; 
    [settings setObject:certs forKey:(NSString *)kCFStreamSSLCertificates]; 
    [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLIsServer]; 

    [sock startTLS:settings]; 
    [certs release]; 
} 

Das Zertifikat ich benutze ist ein Selbst -signiertes Server-SSL-Zertifikat, das ich mit Keychain Access erstellt habe. Also verstehe ich, dass ich dem System eine Konfiguration mit einem Array geben muss, das eine Identität und ein Zertifikat enthält. Und es funktioniert gut auf meiner Mac-App.

Das Problem besteht darin, das SSL auf dem HTTP-Server meiner iOS-App zu aktivieren. Die Methode "SecIdentityCreateWithCertificate()", die die Identität erstellt, existiert nicht auf iOS und ich weiß nicht, wie man eine Identität auf andere Weise erstellt.

Wie erstellt man eine SecIdentityRef auf iOS (um die SSL-Server-Seite zu aktivieren)? Habe ich etwas vermisst gerne den öffentlichen/privaten Schlüssel in meiner App oder etwas anderes zu speichern? Ich danke dir sehr.

+0

Es wurde in CocoaAsyncSocket v7.4 geändert, einige alte Optionsschlüssel sind jetzt nicht verfügbar und werden Ausnahme auslösen. Verwenden Sie GCDAsyncSocketManuallyEvaluateTrust und evaluieren Sie stattdessen in -socket: didReceiveTrust: delegate. Sehen Sie mein Beispiel in https://gist.github.com/hlung/6432966 – Hlung

Antwort

4

Ich werde eine separate Antwort posten, da Kommentare nicht für Code-Sharing geeignet sind.
Hier ist, was ich pflege meine PKCS12 importieren:

CFArrayRef keyref = NULL; 
OSStatus sanityChesk = SecPKCS12Import((__bridge CFDataRef)p12Data, 
             (__bridge CFDictionaryRef)[NSDictionary 
                    dictionaryWithObject:password 
                    forKey:(__bridge id)kSecImportExportPassphrase], 
             &keyref); 

if (sanityChesk != noErr) { 
    NSLog(@"Error while importing pkcs12 [%d]", sanityChesk); 
    return nil; 
} 

NSArray *keystore = (__bridge_transfer NSArray *)keyref; 

Das komplette p12-Gehalt in dem Schlüsselspeicher Array sein.

+0

mein Code hier verwendet die ARC, daher die Notwendigkeit der kryptischen __bridge Schlüsselwörter;) – pmilosev

+0

Ich tat das gleiche.Ich bekomme das gleiche Ergebnis mit Ihrem Code: _keystore_ array ist leer. Wenn Sie ein besseres Ergebnis mit dem gleichen Code haben, bedeutet das, dass ich meine Zertifikate nicht richtig generiere oder speichere? Was ich getan habe, ist ein selbstsigniertes Stammzertifikat von Keychain Access zu erstellen, dann speichere ich beide .cer und .p12 Dateien in meinem Projektpaket und ich versuche, sie ohne Erfolg zu verwenden, wie Sie sehen können. Vielen Dank für Ihre Zeit, ich schätze Ihre Hilfe. – Laurent

+0

nur um es funktionieren zu lassen ... warum versuchst du nicht, einige deiner Arbeitsschlüssel/Zertifikatspaare zu exportieren (z. B. von Apple signierte Entwicklungszertifikate). – pmilosev

0
+0

Ich habe das tatsächlich schon versucht, aber ich kann es nicht funktionieren lassen - es könnte die richtige Frage hier sein. Ich habe meinen privaten Schlüssel (P12-Datei) importiert und die Funktion extractIdentityAndTrust() von Apple in Ihrem Link verwendet, aber ich bekomme immer ein leeres _items_ -Array, das diese Funktion abstürzt, während ich versuche, auf das erste Element des Arrays zuzugreifen. Irgendeine Idee dazu? – Laurent

+0

Wenn Sie die Methode 'SecPKCS12Import' verwendet haben, wird ein NSArray mit NSDictionaries zurückgegeben. Die Identität im Wörterbuch wird unter dem Schlüssel 'kSecImportItemIdentity' gespeichert, während die Zertifikatskette (erneut NSArray) unter dem Schlüssel 'kSecImportItemCertChain' gespeichert wird. In der Zwischenzeit suche ich auch nach einer Möglichkeit, die Identität in Runtime zu erstellen, da es sich nicht um vorgeladene Zertifikate handelt. Wird das Ergebnis hier posten, wenn ich etwas finde;) – pmilosev

+0

Danke @pmilosev. Mein Problem ist, dass ich die Funktion _extractIdentityAndTrust_ verwende, wie von Apple im obigen Link gezeigt, aber das Array _items_ I get ist immer leer: 'NSDictionary * optionsDictionary = [NSDictionaryWörterbuchWithObject: @" myPrivateKeyPassword "forKey: (id) kSecImportExportPassphrase]; CFArrayRef Elemente = CFArrayCreate (NULL, 0, 0, NULL); securityError = SecPKCS12Import (inPKCS12Data, optionsDictionary, & Elemente); ' – Laurent

Verwandte Themen