2013-01-01 10 views
8

Ich mag eine SSL-Verbindung zu meinem Server mit selbst signierten Zertifikaten erstellen, die mit dem Code in iOS ausgeliefert werden. Auf diese Weise muss ich über anspruchsvollere Man-in-the-Middle-Angriffe keine Sorge, wenn jemand Zugriff auf ein hohes Niveau hat „trusted“ cert Behörde. Ich habe Probleme mit dem, was ich glaube, dass Apple Standard ist.Wie überprüfen (und erfordern) selbst signiertes Zertifikat in iOS

das Zertifikat generieren, fand über das Verfahren here

# Create root CA & private key 
openssl req -newkey rsa:4096 -sha512 -days 9999 -x509 -nodes -out root.pem.cer 
# Create a certificate signing request 
openssl req -newkey rsa:4096 -sha512 -nodes -out ssl.csr -keyout ssl.key 
# Create an OpenSSL Configuration file from http://svasey.org/projects/software-usage-notes/ssl_en.html 
vim openssl.conf 
# Create the indexes 
touch certindex 
echo 000a > certserial 
echo 000a > crlnumber 
# Generate SSL certificate 
openssl ca -batch -config openssl.conf -notext -in ssl.csr -out ssl.pem.cer 
# Create Certificate Revocation List 
openssl ca -config openssl.conf -gencrl -keyfile privkey.pem -cert root.pem.cer -out root.crl.pem 
openssl crl -inform PEM -in root.crl.pem -outform DER -out root.crl && rm root.crl.pem 

Und das iOS-Code:

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 
    NSURLProtectionSpace *protectionSpace = [challenge protectionSpace]; 
    if ([protectionSpace authenticationMethod] == NSURLAuthenticationMethodServerTrust) { 
    // Load anchor cert.. also tried this with both certs and it doesn't seem to matter 
    NSString *path = [[NSBundle mainBundle] pathForResource:@"root.der" ofType:@"crt"]; 
    NSData *data = [[NSData alloc] initWithContentsOfFile:path]; 
    SecCertificateRef anchorCert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)data); 
    CFMutableArrayRef anchorCerts = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 
    CFArrayAppendValue(anchorCerts, anchorCert); 

    // Set anchor cert 
    SecTrustRef trust = [protectionSpace serverTrust]; 
    SecTrustSetAnchorCertificates(trust, anchorCerts); 
    SecTrustSetAnchorCertificatesOnly(trust, YES); // only use that certificate 
    CFRelease(anchorCert); 
    CFRelease(anchorCerts); 

    // Validate cert 
    SecTrustResultType secresult = kSecTrustResultInvalid; 
    if (SecTrustEvaluate(trust, &secresult) != errSecSuccess) { 
     [challenge.sender cancelAuthenticationChallenge:challenge]; 
     return; 
    } 

    switch (secresult) { 
     case kSecTrustResultInvalid: 
     case kSecTrustResultDeny: 
     case kSecTrustResultFatalTrustFailure: 
     case kSecTrustResultOtherError: 
     case kSecTrustResultRecoverableTrustFailure: { 
     // !!! It's always kSecTrustResultRecoverableTrustFailure, aka 5 
     NSLog(@"Failing due to result: %lu", secresult); 
     [challenge.sender cancelAuthenticationChallenge:challenge]; 
     return; 
     } 

     case kSecTrustResultUnspecified: // The OS trusts this certificate implicitly. 
     case kSecTrustResultProceed: { // The user explicitly told the OS to trust it. 
     NSURLCredential *credential = [NSURLCredential credentialForTrust:trust]; 
     [challenge.sender useCredential:credential forAuthenticationChallenge:challenge]; 
     return; 
     } 
     default: ; 
     /* It's somebody else's key. Fall through. */ 
    } 
    /* The server sent a key other than the trusted key. */ 
    [connection cancel]; 

    // Perform other cleanup here, as needed. 
    } else { 
    NSLog(@"In weird space... not handling authentication method: %@", [protectionSpace authenticationMethod]); 
    [connection cancel]; 
    } 
} 

Ich bin immer kSecTrustResultRecoverableTrustFailure als Ergebnis zu bekommen. Ich glaube nicht, dass dies ein Problem mit dem lokalen Host ist, da ich versucht habe, auch den Code von Apple zu ändern. Was ist zu tun?

Danke!

+0

Sie benötigen beide 'canAuthenticateAgainstProtectionSpace' und' didReceiveAuthenticationChallenge' außer Kraft zu setzen. 'TrustResultRecoverableTrustFailure' bedeutet, dass Sie das Ergebnis der Servervalidierung ändern können. Siehe auch OWASP iOS Public-Key-Pinning Beispiel bei [Public Key Pinning] (http://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#iOS). – jww

Antwort

0

Bitte achten Sie darauf, dass Ihr Zertifikat gültig ist. Ich denke, dass sein Name nicht root.der.crt sein sollte. Sie können nach Zertifikattypen von here suchen. Der folgende Code ist für p12 Zertifikat, ich hoffe es wird helfen.

NSData *PKCS12DataQA = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"CERTIFICATE NAME" ofType:@"CERTIFICATE TYPE"]]; 

BOOL result = [self extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12DataQA]; 


- (BOOL)extractIdentity:(SecIdentityRef *)outIdentity andTrust:(SecTrustRef*)outTrust fromPKCS12Data:(NSData *)inPKCS12Data 
{ 
    OSStatus securityError = errSecSuccess; 
    //testtest is the passsword for the certificate. 
    NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:@"testtest" forKey:(id)CFBridgingRelease(kSecImportExportPassphrase)]; 

    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); 
    securityError = SecPKCS12Import((__bridge CFDataRef)(inPKCS12Data),(CFDictionaryRef)CFBridgingRetain(optionsDictionary),&items); 

    if (securityError == 0) { 
     CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0); 
     const void *tempIdentity = NULL; 
     tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity); 
     *outIdentity = (SecIdentityRef)tempIdentity; 
     const void *tempTrust = NULL; 
     tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust); 
     *outTrust = (SecTrustRef)tempTrust; 

    } else { 
     NSLog(@"Failed with error code %d",(int)securityError); 
     return NO; 
    } 

    return YES; 
} 
Verwandte Themen