34

当我们谈论保护 iOS 应用程序时,我们经常忘记保护最关键的敏感信息,例如秘密、密钥、令牌、加密密钥。此信息存储在 iOS 二进制文件中。因此,您的服务器端安全协议都不会为您提供帮助。

有很多建议我们不应该将此类信息存储在应用程序中,而是存储在服务器中并通过 SSL 安全 Web 服务调用获取。但这并非适用于所有应用程序。例如,如果我的应用程序根本不需要 Web 服务。

在 iOS 应用程序中,我们有以下选项来存储信息。

  1. UserDefault:不适合这种情况
  2. 字符串常量:不适合这种情况。可以是逆向工程来检索或只使用字符串命令
  3. 安全数据库:存储在安全和加密的数据库中。但同样有责任保护数据库用户名和密码。
  4. KeyChain:最好存储关键信息。但我们无法在安装应用程序之前保存信息。要存储在钥匙串中,我们首先需要打开应用程序,从某个源读取并存储在钥匙串中。也不适合我们的情况。
  5. 自定义哈希字符串常量:不直接使用来自服务提供商(mixpanel、paypal)的秘密、令牌、密钥,而是使用自定义密钥中该信息的哈希版本。这也不是完美的解决方案。但是在黑客攻击过程中增加了复杂性。

请发送一些很棒的解决方案来解决这个问题。

4

6 回答 6

30

如果您不想使用自己的后端,请使用 Apple。您可以配置 On Demand Resources 并使用您的密钥、令牌和 Apple 服务器上的任何机密保存数据文件。首次下载后,您可以将此数据写入足够安全的 Keychain。我猜 iOS 和 Apple 服务器之间的网络也足够安全。

按需资源要点

访问和下载按需资源

于 2017-04-11T07:24:01.253 回答
5

在我看来,最好的方法是使用内置的CloudKit。您可以将您的秘密保存在CloudKit 仪表板中,然后在启动时获取它们。由于 CloudKit 只是一个传输层,您必须将应用程序机密存储在 KeyChain 中。

我知道您提到 KeyChain 不适合您的用例(不知道为什么),但这是在您的应用程序中不包含秘密的好方法。您无法绕过从其他来源获取您的应用程序机密。

CloudKit 访问是使用系统 iCloud 帐户保护的,如果没有 iCloud 帐户,您仍然可以安全地访问 iCloud 服务器。另一个额外的好处是您可以随时更改您的应用程序机密,因此如果您想更加安全,您可以实施轮换计划。

了解有关 CloudKit 的更多信息

于 2018-02-08T02:32:39.930 回答
5

1) 需要互联网连接

1.1) 推送通知 进行安全数据交换的好方法可能是使用 Apple 的(静默)推送服务,这些服务使用 apns 并通过 https 发送数据 - 更多详细信息 3.1

1.2) 在向已部署的应用程序分发新用户证书时,也使用或多或少类似的方法,如果没有机会重新安装应用程序并且应用程序无论如何都需要有效的互联网连接。

缺点:需要有效的网络连接,并且基本上信息正在进入应用程序,当它已经被执行时 => 似乎不适合您的情况。(见第 4 步)

2)静态数据(因为没有网络连接/通信伙伴就没有交换)

使用捆绑包本身提供的私钥加密数据。无论现在是字符串还是哈希,都可以使用嵌入在应用程序中的函数进行逆向工程。由于 iOS9,反编译 iOS 应用程序非常困难,基本上您将主要查看提供的头文件。因此,如果您有这样的函数、字符串、散列值或其他任何内容,请确保将其保存在 .m 文件中!

但同样:如果信息不是设备或用户特定的,只是您自己的微环境中的一个秘密,在所有设备上都有效,如果没有更新过程,您必须在同一个包中提供加密数据和解密方法/信息交流什么的,你可以想到的。

适合加密:iOS System.Security https://developer.apple.com/reference/security 或简单的 openssl

您所描述的钥匙串方法之间的区别在于:您获得了一个值,该值将被加密并安全存储。(2) 描述了具有加密和存储(捆绑)半安全值的方法,该值将被解密

3) 信息交流

您描述了由另一个实例散列的关键数据。伟大的!- 确保,请确保您正在与之交谈的实例确实是您期望的实例(使用 ssl 证书固定等防止网络挂钩,但即使在这里您也可能有入侵者(中间人))。并且您将(可能)在您的应用程序包中提供一个证书,以确保通信服务器的真实性 - 再来一次,数据应该确保您的微环境的某些实例之间的安全过程。不过,这些数据是在您的应用程序包中提供的。

3.1 安全信息交换扩展 - 无声推送 为此目的,请使用 Apple 的服务器交换您的秘密。如果您只需要交换小数据块。我建议对用户使用静默推送通知,这些通知甚至可以在没有用户明确许可的情况下工作。巨大的优势:如果您的秘密或密钥发生变化,您可以尽快通知用户有关更改。他们可能只需要在收到新数据时进行更改,这在大多数情况下应该可靠地工作。例外:在本地网络或通过蓝牙进行数据交换,在这种情况下,我建议向用户提供通知以要求更新本地解密密钥。或者也以这种格式交换密钥。再一次:我泄露了一些关于你的环境架构的详细信息。缺点:你不知道, https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW1

3.1 扩展的安全信息交换 - 应用内购买 使用免费的应用内购买让用户将数据发送到您的手机。这里的要点:您可以轻松地提供更大的数据块,因为这应该是用户的主动请求,用户确实期望一定的处理时间,并且还应该意识到需要有效的互联网连接这一事实。缺点:用户必须故意选择它。在那之前,该应用程序将无法正常工作。 https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Introduction.html#//apple_ref/doc/uid/TP40008267

因此,它与方法(2)的基本思想略有不同。

简而言之:您能否提供其他信息,您需要加密/想要安全存储的数据类型以及您是否将进行网络交换?

这里需要更多信息:-)

我想再次强调,iOS 上的应用程序不再那么容易解密,即使反编译也不会得到所有内容,你希望它得到。例如,dumpdecrypt 等解密工具只能在 iOS 8.4 之前正常工作

于 2017-03-30T09:28:31.247 回答
2

我同意@Lobsterman 的观点,并相信最好的方法是结合使用这些方法。

  • 最初不要在应用程序中包含机密信息。
  • 将密钥作为应用内购买内容、按需资源或通过推送通知发送。如果您愿意,这将增加定期更改密钥的好处,并且更改无需任何额外努力即可生效。
  • 交付内容后,将条目添加到钥匙串访问。
于 2017-04-11T06:51:09.977 回答
2

Cocoapods-keys可能是最好的选择。

cocoapods-keys文档的

键名存储在 ~/.cocoapods/keys/ 中,键值存储在 OS X 钥匙串中。当您运行 pod install 或 pod update 时,会使用加密版本的密钥创建一个 Objective-C 类,这使得仅转储解密二进制文件的内容并提取密钥变得困难。在运行时,密钥会被解密以便在您的应用程序中使用。

生成的 Objective-C 类存储在 Pods/CocoaPodsKeys 目录中,因此如果您要检查 Pods 文件夹,只需将 Pods/CocoaPodsKeys 添加到 .gitignore 文件中。CocoaPods-Keys 支持在 Swift 或 Objective-C 项目中的集成。

查看此链接以了解安装、使用和更多信息:https ://github.com/orta/cocoapods-keys

于 2017-04-13T06:43:43.683 回答
0

如果数据非常敏感,则永远不应将其离线存储在设备上,因为所有设备都是可破解的。如果您仍想在设备上存储,那么钥匙串是安全存储数据的一种选择,但它的加密基于设备的 PIN 码。用户没有强制设置密码,因此在某些情况下,数据甚至可能没有被加密。此外,用户的密码可能很容易被黑客入侵。

更好的解决方案是使用SQLCipher 之类的东西,它是一个完全加密的 SQLite 数据库。加密密钥可以由应用程序强制执行,并与用户的密码分开。

于 2017-04-11T07:22:07.393 回答