Я использую NSURLSessionDelegate-х (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
для сложной проверки подлинности сервера, как это:IOS не принимает действующий самостоятельно подписанный сертификат и не принимает недопустимые
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
. Странное поведение ... Может кто-нибудь объяснить мне, как это сделать правильно?
Спасибо!