如何在iOS应用程序中存储关键敏感信息,如secret,key,token,encryptionKey

时间:2017-03-30 07:46:12

标签: ios iphone data-security app-secret

当我们谈论保护iOS应用程序时,我们经常忘记保护最关键的敏感信息,如secret,key,token,encryptionKey。此信息存储在iOS二进制文件中。因此,您的服务器端安全协议都不会对您有所帮助。

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

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

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

6 个答案:

答案 0 :(得分:19)

如果您不想使用自己的后端,请使用Apple。您可以配置随需应变资源并使用您的密钥,令牌,Apple服务器上的任何密钥保存数据文件。首次下载后,您可以将此数据写入Keychain,这足够安全。我猜测iOS和Apple服务器之间的联网也足够安全。

On-Demand Resources Essentials

Accessing and Downloading On-Demand Resources

答案 1 :(得分:4)

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安全信息交换扩展 - 在应用程序购买 使用frree In-App Purchase为用户将数据传输到手机。这里好点:您可以轻松提供更大的数据块,因为这应该是用户的主动请求,用户确实期望某些处理时间,并且还应该知道需要有效的互联网连接的事实。 缺点:用户必须故意选择此项。在此之前,应用程序无法正常工作。 https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Introduction.html#//apple_ref/doc/uid/TP40008267

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

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

这里需要更多信息: - )

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

答案 2 :(得分:2)

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

  • 最初不要在应用中包含秘密信息。
  • 将密钥作为应用内购买内容,按需资源或通过推送通知发送。如果您愿意,这将增加定期更改密钥的好处,并且更改将在不需要任何额外工作的情况下生效。
  • 在内容传递后,将条目添加到钥匙串访问。

答案 3 :(得分:2)

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

我知道您提到KeyChain不适合您的用例(不确定原因),但这是一种不在您的应用中包含秘密的好方法。您无法从其他来源获取应用程序机密。

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

Learn more about CloudKit

答案 4 :(得分:1)

Cocoapods-keys可能是最佳选择。

来自cocoapods-keys doc's

  

键名存储在〜/ .cocoapods / keys /和OS X中的键值中   钥匙扣。当您运行pod安装或pod更新时,一个Objective-C类   是使用密钥的加扰版本创建的,这很难实现   只需转储解密二进制文件的内容并解压缩密钥。   在运行时,密钥会被解读,以便在您的应用中使用。

     

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

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

答案 5 :(得分:0)

如果数据非常敏感,那么它永远不应该在设备上脱机存储,因为所有设备都是可以破解的。如果您仍想存储在设备上,那么钥匙串是一种安全存储数据的选项,但它的加密是基于设备的密码。用户不必强制设置引脚,因此在某些情况下数据甚至可能无法加密。此外,用户密码可能很容易被黑客攻击。

更好的解决方案是使用像SQLCipher这样的完全加密的SQLite数据库。加密密钥可以由应用程序强制执行,并与用户的密码完全分开。