我正在使用NSURLSessionDelegate的(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
来挑战服务器身份验证,如下所示:
BOOL trusted = NO;
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
if (!cert) {
NSURL* certURL = [[NSBundle mainBundle] URLForResource: @"cert_new" withExtension: @"der"];
NSData* certData = [NSData dataWithContentsOfURL: certURL];
cert = SecCertificateCreateWithData(kCFAllocatorDefault, CFBridgingRetain(certData));
}
SecPolicyRef policyRef = SecPolicyCreateBasicX509();
SecCertificateRef certArray[1] = { cert };
CFArrayRef certArrayRef = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
// Create a policy that ignores the host name…
OSStatus err = SecTrustCreateWithCertificates(CFBridgingRetain((__bridge id _Nullable)(certArrayRef)), policyRef, &serverTrust);
CFRelease(policyRef);
if (err != noErr)
{
XLog(@"Error creating trust: %d", (int)err);
[challenge.sender cancelAuthenticationChallenge: challenge];
return;
}
err = SecTrustSetAnchorCertificates(serverTrust, certArrayRef);
if (err == noErr)
{
SecTrustResultType trustResult;
err = SecTrustEvaluate(serverTrust, &trustResult);
trusted = (err == noErr && (trustResult == kSecTrustResultProceed || trustResult == kSecTrustResultUnspecified));
}
CFRelease(certArrayRef);
CFRelease(policyRef);
CFRelease(cert);
}
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
if (trusted) {
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
return;
} else {
[challenge.sender cancelAuthenticationChallenge: challenge];
}
我必须使用的证书是PEM格式。所以我通过openssl将它转换为DER格式,如下所示:
openssl x509 -in pem_file.pem -out cert_new.der -outform DER
现在似乎接受了某个比特长度的每个证书(无论是否有效):trusted
将被评估为YES
。由于trusted = NO
,具有较低位长的有效证书将被评估为kSecTrustResultRecoverableTrustFailure
。奇怪的行为......有人可以向我解释如何正确行事吗?
谢谢!
答案 0 :(得分:0)
现在我有一个工作版本:
// Build a new trust based on the supplied trust, so that we can set the policy…
NSURLProtectionSpace* protectionSpace = challenge.protectionSpace;
SecTrustRef trust = protectionSpace.serverTrust;
CFIndex numCerts = SecTrustGetCertificateCount(trust);
NSMutableArray* certs = [NSMutableArray arrayWithCapacity: numCerts];
for (CFIndex idx = 0; idx < numCerts; ++idx)
{
SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, idx);
[certs addObject: CFBridgingRelease(cert)];
}
// Create a policy that ignores the host name…
SecPolicyRef policy = SecPolicyCreateSSL(true, NULL); // SecPolicyCreateBasicX509();
OSStatus err = SecTrustCreateWithCertificates(CFBridgingRetain(certs), policy, &trust);
CFRelease(policy);
if (err != noErr)
{
//NSLogDebug(@"Error creating trust: %d", err);
[challenge.sender cancelAuthenticationChallenge: challenge];
return;
}
// Set the root cert and evaluate the trust…
NSURL* certURL = [[NSBundle mainBundle] URLForResource: @"doorbird_certificate" withExtension: @"der"];
NSData* certData = [NSData dataWithContentsOfURL: certURL];
SecCertificateRef rootCert = SecCertificateCreateWithData(kCFAllocatorDefault, CFBridgingRetain(certData));
NSArray* rootCerts = @[ CFBridgingRelease(rootCert) ];
err = SecTrustSetAnchorCertificates(trust, CFBridgingRetain(rootCerts));
if (err == noErr)
{
SecTrustResultType trustResult;
err = SecTrustEvaluate(trust, &trustResult);
SecTrustSetAnchorCertificatesOnly(trust, YES);
NSURLCredential* credential = [NSURLCredential credentialForTrust: trust];
CFRelease(trust);
bool trusted = err == noErr;
trusted = trusted && (trustResult == kSecTrustResultProceed || trustResult == kSecTrustResultUnspecified);
if (trusted)
{
[challenge.sender useCredential: credential forAuthenticationChallenge: challenge];
return;
}
}
// An error occurred, or we don't trust the cert, so disallow it…
[challenge.sender cancelAuthenticationChallenge: challenge];
但只有最低1024位的证书才有效。 512位证书没有。有人可以证实吗?
由于
编辑:
我创建了如下所述的证书: