在 iOS 中,如何存储允许我与服务器通信的秘密 "key"?

In iOS, how can I store a secret "key" that will allow me to communicate with my server?

我想存储一个密钥 ("abc123"),我将在我的 REST API 请求的 header 中使用它。我的服务器将检查这个密钥。如果匹配 "abc123",则允许​​发出请求。

我正在考虑一个简单的解决方案,例如:

let secret = "abc123" 

但是这会有任何失败吗?

通过在您的应用程序中对字符串进行硬编码,攻击者可以解密您的二进制文件(通过 dumpdecrypt 等工具)并轻松获取您的字符串(一个简单的 hexdump 将包含您应用程序中的任何字符串) .

对此有一些解决方法。您可以在您的 REST API 上实现一个端点,其中 returns 您的凭据,然后您可以在启动时调用它。当然,这有其自身重要的安全问题,并且需要额外的 HTTP 调用。我通常不会这样做。

另一种选择是以某种方式混淆密钥。通过这样做,攻击者将无法在解密后立即识别您的密钥。 cocoapods-keys 是使用此方法的一个选项。

这里没有完美的解决方案——您能做的最好的事情就是让攻击者尽可能难以获得您的密钥。

(此外,请务必在发送请求时使用 HTTPS,否则这是泄露密钥的另一种好方法。)

听起来很疯狂,但这可能是最好的解决方案。其他一切都更复杂,但也没有更安全。您使用的任何奇特的混淆技术几乎都会在找到此密钥的同时进行逆向工程。但是这种静态密钥解决方案虽然非常不安全,但几乎与其他解决方案一样安全,而且几乎没有增加额外的复杂性。我喜欢它。

它几乎会立即被破解,但所有其他解决方案也会被破解。所以保持简单。

您真正想做的一件事是使用 HTTPS 和 pin your certificates。我会选择一个不是单词的长而随机的密钥。理想情况下,它应该是一个完全随机的字节串,存储为原始值(而不是字符),这样它在二进制文件中就不会那么明显。如果您想变得疯狂,请在发送之前对其应用 SHA256(因此实际密钥永远不会出现在您的二进制文件中)。同样,这很容易破解,但很容易,不会浪费很多时间进行开发。

任何超过一个小时的努力都不太可能值得为实现此功能所付出的努力。如果您想了解有关该主题的更多信息,请参阅 及其链接。

虽然带内令牌通常用于某些方案,但您最终可能会实施 TLS 来保护网络流量和令牌。 .

在此处使用您自己的证书链允许使用现有的 TLS 安全和身份验证机制以及 iOS 钥匙串,并且如果(何时?)有必要,您还可以选择撤销 TLS 凭证,并且还允许客户端将其连接固定到您的服务器,并在必要时检测服务器欺骗。

您自己的证书颁发机构和您自己的证书链是免费的,并且您自己的证书——一旦您将根证书加载到客户端中——就和商业购买的证书一样安全。

简而言之,这种基于证书的方法结合了加密和身份验证,使用现有的 TLS 机制。

您似乎在使用访问令牌。我会使用钥匙串作为访问令牌。对于客户端 ID,我只是将它们保留为变量,因为客户端 ID 不会更改,而访问令牌会因用户而异,甚至每个刷新令牌都会更改,而钥匙串是存储用户凭据的安全位置。

我使用了 PFConfig 对象(字典),它允许您在应用程序中检索存储为服务器环境参数的变量值。
类似于可以在网站服务器端编程中使用 ENV 检索的环境变量,如 Ruby 或 PHP。 在我看来,这与在 Ruby 或类似环境中使用环境变量一样安全。

PFConfig.getConfigInBackgroundWithBlock{
      (config: PFConfig?, error: NSError?) -> Void in
      if error == nil {
        if let mySecret = config["mySecret"] as? String {
          // myFunction(mySecret)
        }

    }