Ios SSL固定不起作用(Objective-C,使用NSURLSession)

Ios SSL固定不起作用(Objective-C,使用NSURLSession),ios,objective-c,ssl,ssl-certificate,Ios,Objective C,Ssl,Ssl Certificate,注意:在Android应用程序上使用相同的SSL固定。那么iOS有什么改变吗?我的url服务器上有很多证书,并且它们每天都在轮换吗 问题是: SSL固定只能通过证书固定来实现,那么为什么它不起作用呢 如果有人对如何使用公钥有明确的解释?请解释一下 首先,我想解释一下我是如何获得本地证书的。我觉得很直。我只需输入,然后单击锁图标并下载证书。如果你知道我的意思。现在我想这也可能是问题所在。我的问题是:这是下载证书的正确方式吗 好吧,我们假设这是对的。我将证书嵌入或复制粘贴到我的Xcode项目中 下面

注意:在Android应用程序上使用相同的SSL固定。那么iOS有什么改变吗?我的url服务器上有很多证书,并且它们每天都在轮换吗

问题是:

  • SSL固定只能通过证书固定来实现,那么为什么它不起作用呢

  • 如果有人对如何使用公钥有明确的解释?请解释一下

  • 首先,我想解释一下我是如何获得本地证书的。我觉得很直。我只需输入,然后单击锁图标并下载证书。如果你知道我的意思。现在我想这也可能是问题所在。我的问题是:这是下载证书的正确方式吗

    好吧,我们假设这是对的。我将证书嵌入或复制粘贴到我的Xcode项目中

    下面是获取远程(服务器)证书并将其与本地证书进行比较的代码:

    - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
     completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler
    {
        NSLog(@"SECURITY : didReceiveChallenge");
    
        // REMOTE CERTIFICATE
        SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
    
        // Evaluate server certificate [Whether the certificate is valid or not] --
        SecTrustResultType result;
        SecTrustEvaluate(serverTrust, &result);
        BOOL isRemoteCertValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
    
        // Remote certificate object --
        SecCertificateRef certificateRemote = SecTrustGetCertificateAtIndex(serverTrust, 0);
        // Returns a DER representation of a certificate --
        NSData *remoteCertData = CFBridgingRelease(SecCertificateCopyData(certificateRemote));
    
        NSData *localCerData = [self GetLocalCertificateData];
    
        // base 64 encoding of remote certificate --
        NSString* strRemote = [remoteCertData base64EncodedStringWithOptions:0]; // get string from certificate --
    
        NSString *strLocal = [self  GetLocalCertificateStringForPublicKey];
    
        // The pinning check -- compare the remote and local certificate data / string --
    //    if (isRemoteCertValid && [strLocal isEqualToString:strRemote] )
        if (isRemoteCertValid && [localCerData isEqualToData:remoteCertData] )
        {
            NSLog(@"SECURITY : OK ");
        }
        else
        {
            NSLog(@"SECURITY : FAILS");
            isCertificateValid = false;
        }
    }
    
    - (NSData *)GetLocalCertificateData
    {
        if ( MODE == PROD_US)
        {
            NSString *pathToCert = [[NSBundle mainBundle]pathForResource:@"prod_ezpay" ofType:@"cer"];
            NSData *localCertificate = [NSData dataWithContentsOfFile:pathToCert];
            return localCertificate;
        }
        else if (MODE == PREP_US)
        {
            NSString *pathToCert = [[NSBundle mainBundle]pathForResource:@"prepEZPAY" ofType:@"cer"];
            NSData *localCertificate = [NSData dataWithContentsOfFile:pathToCert];
            return localCertificate;
        }
    
        return nil;
    }
    
    现在的问题是,证书数据的比较总是失败:

    [localCerData isEqualToData:remoteCertData] // Always false
    
    我一直在尝试许多不同的方法检查谷歌上的5-6个链接,都有相同的方法。这个项目有点老,3-4年,用Objective-C编写

    我尝试了3种方法:

  • 将证书转换为NSData并进行比较--不起作用

  • 将证书转换为NSData然后再转换为Base64String--不起作用


  • 还有一个黑客——我打印数据并以字符串格式保存,然后在应用程序中硬编码,然后下次继续将其与服务器的证书数据进行比较。这种方法只适用于一天和第二天服务器的证书数据更改。不知道发生了什么事

  • 请说明这里有什么问题?

    • 我解决了这个问题

      • 当您离开本地办公网络或wifi时,必须始终下载ssl证书。因为如果你下载你的 vpn/办公室局域网/办公室wifi内的证书,您的证书 将被调整/覆盖
      • 因此,当您将您下载的证书锁定在您的安全专用办公室网络中时,它将永远不会匹配 作为远程证书的远程证书始终是公共的

        因此,请从open wifi或您自己的数据计划下载证书:),然后将此证书固定在您的代码中,我确信 然后它将匹配远程证书


    “此方法仅适用于一天,第二天服务器的证书数据更改”服务器证书可以在每次连接时更改。你到底想做什么?你想比较什么?为什么?@PatrickMevzek我想在我的iOS应用程序中启用SSL固定。我很难固定证书。为什么证书会更改?如果你去htps://ez-pay.io 下载证书并检查其到期日期,您将看到它只会在一年左右后更改。很快,我尝试了在iOS、ObjC中执行SSL固定的大多数可能方法,但10天后就没有了运气。“为什么证书会更改?”因为它们会到期,例如。因为在一个网站名称后面,您可以有一个服务器群,并且完全不需要所有服务器都具有完全相同的证书,它只需要是名称的有效证书。希望证书永远保持不变是行不通的,“你会发现它只会在一年左右的时间后才会改变”错。它可以随时更改。到期日期意味着它必须在该日期之前更改,因为在该日期之后它不再有效。它没有说明在到期前什么时候可以更改。它可以在任何时间、任何次数进行更改。好的。如果我假设域名后面还有一个证书链,即ez-pay.io,那么上面的代码应该可以工作。到目前为止,我在谷歌上搜索了近10个链接,都给出了相同的答案。你认为我在ios应用程序中的SSL固定方法是正确的吗?嗨@Rakesh,你能在这里添加SSL固定authdelegate方法的最终代码吗?即使我面临同样的问题,也无法解决。你能分享你的会话委托DidReceiveAuth的最终代码吗?好像你没有给完成处理程序打电话。即使我面临同样的问题,请帮我弄清楚。请分享最后一次会议的委托方法。