iOS 9 app download from Amazon S3 SSL error: TLS 1.2 support

iOS 9 app download from Amazon S3 SSL error: TLS 1.2 support

我明白了

An SSL error has occurred and a secure connection to the server cannot be made.

on iOS 9 如果我尝试从 amazon s3 下载文件: https://s3.amazonaws.com/xyz/qer/IMG_0001.JPG

据我了解,Amazon s3 支持 TLS 1.2 参见:https://forums.aws.amazon.com/thread.jspa?threadID=192512

S3 和 Kinesis 目前支持 TLS 1.2。

"S3 and Kinesis support TLS 1.2 at this time." 2015 年 8 月 23 日 9:19 下午

不确定为什么会出现此 SSL 错误。该帐户应配置为利用 TLS 1.2? 我猜这应该是默认的'on'。

我不想把这个域放在信息 plist 上。

编辑: 我最终使用了

<key>NSAppTransportSecurity</key> 
<dict> 
  <key>NSExceptionDomains</key> 
  <dict> 
    <key>s3.amazonaws.com</key> 
    <dict> 
      <key>NSExceptionRequiresForwardSecrecy</key> 
        <false/> 
      <key>NSIncludesSubdomains</key> 
        <true/> 
    </dict> 
  </dict> 
</dict>

编辑 2016-01-03: s3.amazonaws.com 的更新证书使用 SHA256 算法并符合 ATS 要求。

原回答:s3.amazonaws.com使用了不符合ATS要求的SHA1证书,导致硬故障。根据 App Transport Security Technote,iOS9 中的 ATS 具有以下要求:

  1. The server must support at least Transport Layer Security (TLS) protocol version 1.2.

  2. Connection ciphers are limited to those that provide forward secrecy, namely,

    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

  3. 证书必须使用 SHA256 或更好的签名哈希算法签名,使用 2048 位或更高的 RSA 密钥或 256 位或更高的椭圆曲线 (ECC) 密钥.

无效的证书会导致硬故障和无连接。

SSL Labs 的 SSL 服务器测试 (https://www.ssllabs.com/ssltest/analyze.html?d=s3.amazonaws.com) 包括 iOS 9 中 ATS 的握手模拟,表明 s3.amazonaws.com.

失败

要让 iOS 9 个应用程序成功到达 SSL 端点(S3 只是一个示例),您需要做两件事:

  • 在服务器上启用了前向保密(https://www.wikiwand.com/en/Forward_secrecy)。

    AWS S3目前不支持此功能。解决方法是您可以在 S3 存储桶前配置 AWS CloudFront 服务(支持 FS)。 设置相当简单。如果您使用的是 CORS,请记住需要通过 CloudFront 代理传递正确的 headers。

  • 服务器上的 SHA-256 保护 SSL 证书。

    通过 Cloudfront 获得文件后,点击 URL (https://somethinghashed1234wasdfawer421.cloudfront.net) 您会注意到那里的 SSL 证书使用 SHA-1。多么糟糕... 解决方案是使用您的私有 SHA-256 SSL 证书来保护它。为此,您需要为域中的 Cloudfront 端点指定 CNAME。这将允许您使用自己的 SSL 证书保护存储桶。只需将您的 DNS 配置为将 cloudfront-bucket.mydomain.com 的入口指向那个丑陋的 somethinghashed1234wasdfawer421.cloudfront.net。将您的 SSL 证书上传到亚马逊并在 Cloudfront 分发设置中设置 SSL 保护。瞧!

提到的所有内容都可以从 AWS 控制台轻松点击(上传 SSL 证书除外,这需要通过 AWS CLI 完成)。

由于 S3 目前不完全兼容,根据 AWS 博客 this post,他们的官方建议是通过将这组密钥添加到您的 Info.plist 来将 S3 从 App Transport Security 中排除:

<key>NSAppTransportSecurity</key>
<dict>
      <key>NSExceptionDomains</key>
      <dict>
            <key>amazonaws.com</key>
            <dict>
                  <key>NSThirdPartyExceptionMinimumTLSVersion</key>
                  <string>TLSv1.0</string>
                  <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
                  <false/>
                  <key>NSIncludesSubdomains</key>
                  <true/>
            </dict>
            <key>amazonaws.com.cn</key>
            <dict>
                  <key>NSThirdPartyExceptionMinimumTLSVersion</key>
                  <string>TLSv1.0</string>
                  <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
                  <false/>
                  <key>NSIncludesSubdomains</key>
                  <true/>
            </dict>
      </dict>
</dict>

15 年 10 月 27 日更新: 正如 Pol 在评论中指出的那样,即使这是 AWS 的官方回答,the support forums 中的一位 Apple 工程师说这实际上是一个错误:

It turns out that the fact that NSExceptionRequiresForwardSecrecy relaxes the SHA-2/256 requirement is a bug; the intended behaviour of NSExceptionRequiresForwardSecrecy is the behaviour documented in the App Transport Security Technote, namely that it should just enable specific cypher suites.

Our plan is to fix this bug at some point in the future. We expect to fix this in some compatible fashion, so folks who’ve mistakenly used NSExceptionRequiresForwardSecrecy to disable the SHA-2/256 requirement won’t break. However, predicting the future is always a challenge. Which brings us to what you should do right now. [A previous version of this post gave less concrete advice. The following is an update that tightens things up.] After discussing this with ATS Engineering our recommendations are:

If you're using a specific hosting service, you should consult your hosting service to get the latest advice.

In situations like this, where the server is fully compatible with ATS except for the SHA-2/256 certificate signing requirement, we recommend that you accurately document that state of affairs by using NSExceptionAllowsInsecureHTTPLoads.

You should attempt to make your server fully compatible with ATS as soon as possible.

When that happens, you should update your app with the more secure ATS settings.

I should stress that NSExceptionAllowsInsecureHTTPLoads isn't actually insecure. It's just as secure as your app currently is when it's running on iOS 8. Rather, it means that your app doesn't benefit from the extra security provided by ATS. Share and Enjoy

强调我的。请注意,目前的计划是以 不会破坏 使用 NSExceptionRequiresForwardSecrecy 解决此问题的人的行为的方式修复错误,因此以上内容仍然是可行的答案。

只是发帖指出亚马逊证书的问题是他们使用 SHA-1 并且应用程序传输安全需要 SHA-2/256。

NSExceptionRequiresForwardSecrecy 起作用的事实是在 apple dev forums 上记录的错误。根据链接线程中的文档和 Apple 工程师,"better" 解决方案是

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>s3.amazonaws.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict> 
    </dict> 
</dict>

我对 "better" 一词的使用非常宽松,仅表示不会出现 Apple 最终会修复的错误的解决方案。现在这只是针对证书问题的修复:)

直到亚马逊在这个问题上摆脱他们的*ss,正如@Zsolt 建议的那样,在您的 plist 文件中插入以下键和值。

但请务必将 NSExceptionDomain 设置为 amazonaws.com 而不是 s3。amazonaws.com, 取决于您的资产的服务方式和亚马逊所在的区域可能会像这样 s3-us-west-1.amazonaws.com 为它们提供服务,因此不明确设置子域将允许从任何 AWS 区域标识符正确地提供资产。

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>amazonaws.com</key>
        <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
    </dict>
</dict>