iOS没有';不接受有效的自签名证书,但接受无效证书

iOS没有';不接受有效的自签名证书,但接受无效证书,ios,https,certificate,nsurlsession,self-signed,Ios,Https,Certificate,Nsurlsession,Self Signed,我正在使用NSURLSessionDelegate的(void)URLSession:(NSURLSession*)session didReceiveChallenge:(NSURAuthenticationChallenge*)challenge completionHandler:(void(^)(NSURLSessionAuthChallengeDisposition,NSURLCredential*Nullable))completionHandler来挑战这样的服务器身份验证: BO

我正在使用NSURLSessionDelegate的
(void)URLSession:(NSURLSession*)session didReceiveChallenge:(NSURAuthenticationChallenge*)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];
}
openssl x509 -in pem_file.pem -out cert_new.der -outform DER
我必须使用的证书是PEM格式的。因此,我通过openssl将其转换为DER格式,如下所示:

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];
}
openssl x509 -in pem_file.pem -out cert_new.der -outform DER
现在,似乎每个具有特定位长度的证书(无论是否有效)都将被接受:
trusted
将计算为
YES
。并且位长度较低的有效证书将被评估为
trusted=NO
,因为
ksectrustsresultrecoverabletrustfailure
。奇怪的行为。。。有人能给我解释一下怎么做对吗


谢谢

现在我有了一个工作版本:

//  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];
//基于提供的信任建立新的信任,以便我们可以设置策略…
NSURLProtectionSpace*protectionSpace=challenge.protectionSpace;
SecTrustRef trust=protectionSpace.serverTrust;
CFIndex numCerts=SecTrustGetCertificateCount(信任);
NSMutableArray*certs=[NSMutableArray阵列容量:numCerts];
对于(CFIndex idx=0;idx
但只有最小1024位的证书才能工作。具有512位的证书不支持。有人能证实吗

谢谢

编辑:

我创建了如下所述的证书: