【问题标题】:SSL pinning not working (Objective-C, using NSURLSession)SSL pinning 不起作用(Objective-C,使用 NSURLSession)
【发布时间】:2020-04-06 04:58:51
【问题描述】:

注意:在 Android 对应应用程序上使用相同的 SSL 固定。那么 iOS 是否改变了一些东西?我的网址在服务器上是否有很多证书并且它们每天都在轮换?

问题是:

  1. SSL Pinning 只能通过证书 pinning 来实现,那为什么不起作用呢?

  2. 如果有人清楚地解释了如何使用公钥来做到这一点?请解释一下。

首先我想解释一下我是如何获得本地证书的。我认为这很直接。我刚刚输入了https://ez-pay.io,然后我点击了锁图标并下载了证书。如果你明白我的意思。现在我认为这也可能是问题所在。我的问题是:下载证书的方法是否正确?

好吧,让我们假设这是正确的。我将证书嵌入或复制粘贴到我的 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

我一直在尝试许多不同的方法,在 google 上检查了 5-6 个链接,都具有相同的方法。这个项目有点老了,3-4年,用Objective-C写的。

我尝试了 3 种方法:

  1. 将证书转换为 NSData 并进行比较 -- 无效。

  2. 将证书转换为 NSData,然后转换为 Base64String - 无效..

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

请指出这里有什么问题?

【问题讨论】:

  • “这种方法只适用于一天和第二天服务器的证书数据更改”服务器证书可以在每次连接时更改。你真正想做什么,你想比较什么,为什么?
  • @PatrickMevzek 我想在我的 iOS 应用程序中启用 SSL 固定。而且我很难固定证书。为什么证书会改变?如果你去 htps://ez-pay.io 下载证书并检查它的到期日期,你会发现它只会在一年左右之后才会改变..简而言之,我尝试了大多数可能的方法来在 iOS、ObjC 中进行 SSL 固定,10 天以来没有运气。
  • "还有为什么证书会改变?"因为它们过期了,一个。因为在单个网站名称后面,您可以拥有一组服务器,并且绝对不需要所有服务器都拥有完全相同的证书,它只需要是该名称的有效证书即可。希望证书永远保持不变是行不通的。
  • "你会看到一年左右才会改" False。它可以随时更改。到期日期意味着它必须在此日期之前更改,因为在该日期之后它不再有效。它没有说明什么时候可以在到期前更改。可以随时更改,次数不限。
  • 好的。如果我假设域名后面有一个证书链,即 ez-pay.io 仍然,上面的代码应该可以工作。到目前为止,我已经在 google 上搜索了近 10 个链接,并且都给出了相同的答案。您认为我在 ios 应用中使用 SSL Pinning 的方法是正确的吗?

标签: ios objective-c ssl ssl-certificate


【解决方案1】:
  • 我发现了这个问题。

    • 当您不在本地办公网络或 wifi 时,您必须始终下载 ssl 证书。因为如果你下载你的 vpn / office LAN / office wifi中的证书,您的证书 将被调和/覆盖。
    • 因此,当您将下载的证书固定在安全的私人办公网络中时,它将永远不会匹配 远程证书作为远程证书始终是公开的。

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

【讨论】:

  • 嗨@Rakesh,你能在这里添加SSL pinning authdelegate方法的最终代码吗,即使我面临同样的问题,无法弄清楚。
  • 你能分享你的会话代表 didRecieveAuth 的最终代码吗?好像你没有调用完成处理程序。即使我面临同样的问题,请帮助我弄清楚。请分享您的最终会话委托方法。
猜你喜欢
  • 1970-01-01
  • 2022-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-26
  • 1970-01-01
  • 2021-02-20
  • 1970-01-01
相关资源
最近更新 更多