我想使用iOS中的代碼附帶的自簽名證書來創建與我的服務器的SSL連接。這樣我就不用擔心有人可以訪問高級「可信」證書頒發機構的更復雜的中間人攻擊。我在使用我認爲是Apple的標準方式的問題時遇到了問題。如何驗證(並要求)iOS中的自簽名證書
生成證書,通過程序中發現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
和iOS的代碼:
- (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];
}
}
我一直都想與kSecTrustResultRecoverableTrustFailure作爲結果。我不認爲這是本地主機問題,因爲我試圖使用Apple的代碼來改變它。該怎麼辦?
謝謝!
您需要覆蓋'canAuthenticateAgainstProtectionSpace'和'didReceiveAuthenticationChallenge'。 'TrustResultRecoverableTrustFailure'意味着你可以改變服務器驗證的結果。另請參閱OWASP的iOS公共密鑰固定示例(http://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#iOS)。 – jww