2016-08-12 5 views
1

Ich erstelle eine iOS-Anwendung, die über TLS mit einem Webserver kommuniziert. Wenn ich auf den Webserver zugreife, stellt er meinem Gerät ein Zertifikat vor, und ich möchte bestätigen, dass ich ihm vertrauen kann.TLS-Zertifikat manuell validieren (ios objective-c)

Ich habe das Stammzertifikat in meinem xcode-Projekt als eine Datei eingebettet. Der Code, den ich bisher habe, ruft NSString-Versionen beider Zertifikate in der NSURLConnection-Delegatfunktion für Authentifizierungsherausforderung ab.

Irgendwelche Ideen zur manuellen Validierung?

Hier ist mein aktueller Code:

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 
NSLog(@"Certificate challenge"); 
if (self.stageNum==0) { 
    id <NSURLAuthenticationChallengeSender> sender=challenge.sender; 
    NSURLProtectionSpace *protectionSpace=challenge.protectionSpace; 
    SecTrustRef trust=[protectionSpace serverTrust]; 

    //Get server certificate 
    SecCertificateRef certificate=SecTrustGetCertificateAtIndex(trust, 0); 
    NSData *serverCertificateData=(__bridge NSData *)SecCertificateCopyData(certificate); 
    NSString *serverBase64Certificate=[serverCertificateData base64EncodedStringWithOptions:0]; 

    //Get our certificate 
    NSData *certData1 = [[NSData alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"SUMOSRoot" ofType:@"der"]]; 
    NSString *certBase64=[certData1 base64EncodedStringWithOptions:0]; 

    //Heres where I need to compare the certificates 
    // 
    // 

    [sender useCredential:[NSURLCredential credentialForTrust:protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; 
} 
} 

Antwort

1

Ich denke, dieser Beitrag Ihren Zweck löst. Schön geschrieben/erklärt.

http://www.techrepublic.com/blog/software-engineer/use-https-certificate-handling-to-protect-your-ios-app/

Leute, die zu faul sind, die Links zu öffnen, werde ich eine Beschreibung hier von der Post hinzufügen.

enter image description here

+1

Das wird funktionieren, aber es ist weniger als ideal, weil das CERT schließlich ablaufen und neu generiert werden wird, und damit nicht mehr den erwarteten Hash übereinstimmen. Es ist besser, den öffentlichen Schlüssel vom Trust-Objekt zu nehmen und diesen mit dem erwarteten Schlüssel zu vergleichen. Auf diese Weise wird der Server weiterhin vertrauenswürdig sein, auch nachdem der Administrator das Zertifikat neu generiert hat (vorausgesetzt, der Administrator ändert den Schlüssel nicht). – dgatwood

+0

Danke für den Link! Ich werde einen Blick werfen –

+0

Hat dieser Link funktioniert? – Harsh

1

Ich bin nicht sicher, warum Sie eine NSString Darstellung bekommen würde. Sobald Sie eine SecTrustRef haben, können Sie SecTrustCopyPublicKey aufrufen, um den öffentlichen Schlüssel zu einem SecKeyRef zu kopieren und dann das mit den ursprünglichen Schlüsseldaten (Rohbytes) zu vergleichen. Wenn die öffentlichen Schlüssel übereinstimmen, sollten Sie das Zertifikat akzeptieren.

Diese Technik wird "Zertifikatsfixierung" genannt, und ich bin mir sicher, dass es hier einige Antworten auf Stack Overflow gibt, die vollständige Codebeispiele bereitstellen können, wenn Sie nach diesem Begriff suchen.

Offenbar können Sie die Zertifikate auch vergleichen, aber das ist wahrscheinlich nicht das, was Sie tun möchten, da die Zertifikate in regelmäßigen Abständen ablaufen und aktualisiert werden müssen. Wenn Sie den Schlüssel vergleichen, wird er auch dann funktionieren, wenn er das Zertifikat neu generiert (vorausgesetzt, dass es mit demselben privaten/öffentlichen Schlüsselpaar neu generiert wird).

Oder wenn Sie bereit sind, es an ein bestimmtes langlebiges privates Root-Zertifikat zu binden, können Sie es einfach zur Liste der vertrauenswürdigen Anker hinzufügen und das Trust-Objekt neu bewerten, mit dem Vorbehalt, dass es bei diesem privaten Root bricht Zertifikat läuft ab. Auf der anderen Seite, wenn Sie den Schlüssel anheften, wird es brechen, wenn Sie den privaten Schlüssel aus irgendeinem Grund ändern müssen ... so ist es ein Kompromiss.

Natürlich ist die beste Wahl im Allgemeinen, wenn es möglich ist, ein echtes CA-Zertifikat zu erhalten und nicht mit irgendeiner der Kettenvalidierung zu verwirren, aber ich gehe davon aus, dass dies nicht möglich ist (z weil sich der Server in einer .local-Domäne auf einem physischen Gerät befindet, das sein eigenes Zertifikat ohne Internetzugriff oder aus einem anderen ähnlichen Grund generiert). Für Dinge wie die sichere Kommunikation mit einer beliebigen Hardware in einem .local-Netzwerk ist Key Pinning der beste Ansatz. Wenn der Schlüssel nicht übereinstimmt, müssen Sie den Benutzer als neues Gerät hinzufügen oder was auch immer.

+0

Danke für die Antwort. Ich werde mehr über das Pinning von Zertifikaten erfahren. Und Sie haben Recht, es ist nicht möglich, ein echtes CA-Zertifikat für diese Situation zu verwenden –

Verwandte Themen