38

假设我需要从 iPhone 应用程序访问 Web 服务。此 Web 服务要求客户​​端对 HTTP 请求进行数字签名,以证明应用程序“知道”共享密钥;客户端密钥。请求签名存储在 HTTP 标头中,请求只是通过 HTTP(不是 HTTPS)发送。

此密钥必须始终保密,但需要由 iPhone 应用程序使用。

那么,鉴于您一直被告知永远不要在客户端存储任何敏感信息,您将如何安全地存储此密钥?

普通用户(99% 的用户)会很乐意使用该应用程序。会有人(敌人?)想要该秘密客户端密钥,以便通过冒充的方式对服务或客户端密钥所有者造成伤害。这样的人可能会越狱他们的手机,访问二进制文件,运行“字符串”或十六进制编辑器并四处寻找。因此,仅将密钥存储在源代码中是一个糟糕的主意。

另一个想法是将密钥存储在代码中,而不是字符串文字,而是存储在从字节文字创建的 NSMutableArray 中。

一个人可以使用钥匙串,但由于 iPhone 应用程序永远不必提供密码来存储钥匙串中的东西,我担心有权访问应用程序沙箱的人可以并且将能够简单地查看或简单地解码其中的项目。

编辑 - 所以我读到了关于钥匙串的内容:“在 iPhone OS 中,应用程序始终可以访问自己的钥匙串项目,而无法访问任何其他应用程序的项目。系统为钥匙串生成自己的密码,并存储密钥以任何应用程序都无法访问的方式在设备上。”

所以也许这是存储密钥的最佳位置......如果是这样,我如何将预先输入到应用程序钥匙串中的密钥发送?那可能吗?否则,如果密钥不在源代码中,您如何在首次启动时添加密钥?唔..

编辑 - 在http://bugreport.apple.com提交错误报告 # 6584858

谢谢。

4

10 回答 10

9

最终目标是限制授权用户访问 Web 服务,对吗?如果您控制 Web 服务(如果您不控制 - 将其包装在您可以控制的 Web 服务中),则非常容易。

1) 创建一个公钥/私钥对。私钥放在网络服务服务器上,该服务器被放置在地牢中并由一条龙守卫。公钥在电话上。如果有人能够读取公钥,这不是问题

2) 让应用程序的每个副本生成一个唯一标识符。你如何做到这一点取决于你。例如,您可以在下载时将其构建到可执行文件中(这对于 iPhone 应用程序是否可行)?您可以使用手机的 GUID,假设他们有一种计算方法。如果你真的想要,你也可以在每个会话中重做这个。

3)使用公钥加密“我的唯一标识符是$FOO,我批准了这个消息”。将其与对 Web 服务的每个请求一起提交。

4) Web 服务解密每个请求,反弹任何不包含有效标识符的请求。您可以在这里做尽可能多或尽可能少的工作:保留白名单/黑名单、监控每个标识符的使用情况以及调查可疑行为等。

5) 由于唯一标识符现在永远不会通过线路发送,因此破坏它的唯一方法是对电话进行物理访问。 如果他们可以物理访问手机,您将无法控制手机上任何位置的任何数据。总是。没办法。这就是为什么我们构建了这样一个系统,即损害一部手机永远不会损害一个以上的帐户。

6) 构建业务流程以满足以下需求:a) 删除滥用它的用户的访问权限,以及 b) 恢复对电话受到物理损害的用户的访问权限(这将非常非常罕见,除非用户是对手)。

于 2009-02-13T03:25:28.243 回答
7

简单的答案是,就目前的情况而言,在 iPhone 上保守秘密是不可能的。越狱的 iPhone 只是一台适合您手中的通用计算机。没有您可以访问的可信平台硬件。用户可以欺骗任何你能想象到的用来唯一标识给定设备的东西。用户可以将代码注入您的进程以执行检查钥匙串等操作。(搜索 MobileSubstrate 以了解我的意思。)对不起,你搞砸了。

在这种情况下,应用程序购买收据是一道曙光。如果您使用应用内购买在您的应用中销售商品,您将获得一张经过加密签名的收据,并且可以根据需要通过 Apple 进行验证。即使您无法对收据保密,它可以(由 Apple,而不是您)追踪到特定购买,这可能会阻止盗版者分享它们。您还可以根据每个收据限制对服务器的访问,以防止您的服务器资源被盗版者耗尽。

于 2009-11-05T20:13:55.963 回答
4

UAObfuscatedString可以解决您的问题。从文档:

当您编写包含字符串常量的代码时,该字符串以明文形式保存在二进制文件中。黑客可能会发现漏洞或更改字符串以影响您的应用程序的行为。UAObfuscatedString 只在二进制文件中存储单个字符,然后在运行时将它们组合起来生成你的字符串。这些单个字母不太可能在二进制文件中被发现,因为它们会在编译代码中的随机位置插入。因此,对于任何试图提取字符串的人来说,它们似乎都是随机代码。

于 2014-08-14T03:52:10.403 回答
2

如果您可以忍受只使用 iPhone OS 3.0,您可能需要查看推送通知。我无法详细说明,但您可以将有效负载与通知本身一起发送到 Apple 的服务器。当他们接受警报时(或者如果您的应用程序正在运行),则会调用您的代码的某些部分并存储钥匙串项。在这一点上,这是我能想到的在 iPhone 上安全存储秘密的唯一途径。

于 2009-06-17T00:25:57.703 回答
2

我有同样的问题,并花了很多时间四处寻找答案。问题是先有鸡还是先有蛋:如何使用您的应用所需的数据预先填充钥匙串。

无论如何,我发现了一种技术,至少会让越狱者更难发现信息——他们至少必须反汇编你的代码才能找出你做了什么来掩盖信息:

字符串混淆(如果链接中断搜索“混淆/加密字符串(NSString)”)

本质上,该字符串在放入应用程序之前已被混淆,然后您使用代码对其进行解混淆。

总比什么都不做要好。

大卫

编辑:我实际上在应用程序中使用了它。我将一个基本编码字符串放入 info.plist,然后在代码中对其进行了几项操作 - rot13、旋转/反转字节等。最终处理的字符串用于解码混淆字符串。现在,这三个字母机构肯定可以打破这一点——但要花费数小时解码二进制文件的巨大成本。

我想说这是我遇到的最好的技术,但我刚刚阅读了 Kiran 关于UAObfuscatedString的帖子(不同的答案),这是一种完全不同的混淆方式。它的好处是在应用程序的任何地方都没有保存字符串——每个字母都变成了一个方法调用。选择器将显示为字符串,因此黑客可以快速判断您的类使用了该技术。

于 2011-10-13T14:33:21.343 回答
0

我认为这个类似的问题以及我的回答也可能与您的情况有关。简而言之,有一些关于 iPhone 中存在可信平台模块的讨论。这将允许您的服务信任 iPhone,即使在攻击者手中。但是,看起来使用钥匙串是您最好的选择。

于 2009-02-18T00:08:39.520 回答
0

您是否考虑过/尝试过推送通知建议,以便最初将秘密传输到应用程序和钥匙串?还是最终找到其他方法来实现这一目标?

于 2009-09-24T07:41:35.560 回答
0

我要让我的 iphone 应用程序将图像上传到 Amazon S3。我不会将 AWS 凭证放在应用程序中,而是将应用程序电话放在我的服务器上,以便在 S3 上传请求中使用 URI 和标头。我的服务器将生成 S3 URI、正确的签名等。然后我可以在我的应用程序的 Web 服务上实施比 AWS 本身提供的更严格、更具体的安全模型,并且不会将我的 AWS 密钥泄露给任何拥有越狱 iPhone 的人。

但是仍然必须给应用程序一些信任(证书或其他),并且这种信任可能会被窃取。如果有人越狱 iPhone 并窃取应用程序中的任何凭据,您所能做的就是限制造成的损害。这些凭据越强大,情况就越糟糕。限制凭证权力的方法包括:

  • 避免全局凭据。使它们按用户/应用程序
  • 避免永久凭证。如果可能的话,让它们成为临时的
  • 避免全局权限。只给他们他们需要的权限。例如,写入权限可以分解为插入、覆盖、删除、写入资源组 A 或 B 等,而读取可以分解为读取命名资源、读取所有现有资源的列表、读取资源组 A 或 B , ETC。
于 2010-05-13T00:21:29.463 回答
-1

听起来很奇怪。将使用 HTTPS 和加密包来处理密钥。

我认为 CommonCrypto 可用于 iPhone。

编辑:听起来还是很奇怪。为什么有人会在 HTTP 标头中传递密钥?任何跟踪您的网络流量(例如通过记录 wifi 路由器)的人都会看到它。

有用于加密消息流量的完善的安全方法......为什么不使用它们而不是发明基本上是一个有微不足道的系统?

编辑二:啊,我明白了。我会继续使用钥匙串......我认为它仅适用于这类情况。我错过了您正在使用密钥生成请求。如果可以的话,我仍然会使用 HTTPS,因为这样你就不会冒险让人们通过检查足够的签名来推断你的密钥生成方案。

于 2009-02-13T02:09:15.617 回答
-1

如果可能,我建议在运行时创建一个密钥。这样,如果密钥在特定会话期间被抓获,一旦会话结束,密钥将一文不值。如果他们足够聪明,他们仍然可以从记忆中理解密钥,但没关系,因为密钥会在一段时间后失效。

于 2009-02-13T02:12:30.417 回答