iOS 11:ATS(App Transport Security)不再接受自定义锚证书吗?

时间:2017-09-20 08:07:14

标签: security ssl ios11 xcode9

我使用“NSMutableURLRequest”租用自签名证书,当使用带有“SecTrustSetAnchorCertificates”的自定义证书锚定证书时,iOS 11失败并显示以下错误消息:

refreshPreferences: HangTracerEnabled: 1
refreshPreferences: HangTracerDuration: 500
refreshPreferences: ActivationLoggingEnabled: 0 ActivationLoggingTaskedOffByDA:0
ATS failed system trust
System Trust failed for [1:0x1c417dc40]
TIC SSL Trust Error [1:0x1c417dc40]: 3:0
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
Task <721D712D-FDBD-4F52-8C9F-EEEA28104E73>.<1> HTTP load failed (error code: -1200 [3:-9802])
Task <721D712D-FDBD-4F52-8C9F-EEEA28104E73>.<1> finished with error - code: -1200

以前适用于iOS 10的内容在IO 11中不再有效。

我知道iOS 11不再支持以下内容:

  • RC4 3DES-CBC AES-CBC
  • MD5 SHA-1
  • &lt; 2048位RSA发布密钥 - 与服务器的所有TLS连接
  • http://
  • SSLv3
  • TLS 1.0
  • TLS 1.1

除了一个SHA-1指纹外,证书不使用这些,但也列出了SHA-256指纹。

通过添加以下内容,我们可以绕过ATS(App Transport Security)错误:

<key>NSAppTransportSecurity</key>
<dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>mydomain.com</key>
            <dict>
                <!--Include to allow subdomains-->
                <key>NSIncludesSubdomains</key>
                <true/>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
            </dict>
        </dict>
</dict>

通过将根/锚证书安装到手机上,无需将mydomain.com列入白名单即可运行。

这是否意味着ATS不再支持自签名证书?

这曾经在iOS 10中运行:

SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)certs);

在Mac上使用nscurl显示许多失败,并且在将根证书安装到“系统”密钥库nscurl之后成功。 这是在macOS 10.12.6上完成的。

nscurl --verbose --ats-diagnostics https://

如何使用自定义证书进行此操作,但无需安装证书或将域列入白名单?

2 个答案:

答案 0 :(得分:0)

不久前,macOS 开始强制要求 CA 证书不能也用作终端实体(例如网络服务器)证书。 iOS 有没有可能在 10 到 11 之间添加了这个要求?

如果是这样,解决方法很简单:您创建自签名 CA 证书,并使用该证书颁发网络服务器证书。 CA 证书 (basicConstraints: CA=True) 是信任库中的信任锚;最终实体证书(省略 basicConstraints;extendedKeyUsage=serverAuth)由 Web 服务器提供。您不能再为两者使用完全相同的证书。

(这应该是一个评论,但我还没有足够的点数来评论。)

答案 1 :(得分:-1)

我不知道如何轻松地做到这一点,但是下面是我每30秒执行一次setup.js的示例。 ‌‌

#!/usr/bin/env python

import simply

if __name__ == '__main__':
     import time

     def grepServer(self.systemName):
         print 'Server Running'
         if self.nextTestServer == None:    
             self.testServer.log('Server listening on ' + self.client __goto())
             print str((self.serverPort -'1000').extract())
         elif str(self.serverTime) < 9999 whatever == 'pools' expects rootTime to startServer

     def startServer(self,fileSize):
         global response
         LOG = 'str: %d' % s

     print "now"

     if self.shortName in self.buffer but not inBytes:
         raise FileNotFound('path does not exist')

         return
     Requests.get(o)

     def destroyingSharedModule(self,currentFile, count):makeFileRead(myFile,srcPath, **bigFileName)
     currentFileNumber = multipleFileLength.mapEncryptionMode(myFilePath)

     print ("Starting file \"" + currentFile than "\"")
     #if doFileSystemExit().block() (self.runningFilesInDirectory) and didFailSignedBuild()
     return False

尝试与以下文件交换单个文件:

import parallel

#Then it works to run the program on the following path
learnString()   

setupEnvironmentPath()
That is, you call directory and randomlyStringArray depending on the environment (check out uitableView)