你将如何保密秘密数据在iPhone应用程序的秘密?
假设我需要从iPhone应用程序访问Web服务。 这个Web服务需要客户端对HTTP请求进行数字签名,以certificate应用程序“知道”共享密钥; 一个客户端密钥。 请求签名存储在HTTP标头中,并且只通过HTTP(而不是HTTPS)发送请求。
此密钥必须始终保密,但需要由iPhone应用程序使用。
那么,如果您一直被告知不要在客户端存储任何敏感信息,您将如何安全地存储这个密钥?
普通用户(99%的用户)会很高兴地使用这个应用程序。 会有人(敌人?)想要这个秘密的客户端密钥,以通过冒充的方式对服务或客户端密钥所有者造成伤害。 这样的人可能会越狱他们的电话,访问二进制文件,运行“string”或hex编辑器,并捅四周。 因此,将密钥存储在源代码中是一个可怕的想法。
另一个想法是将密钥存储在代码中,而不是string文字,而是存储在由字节文字创build的NSMutableArray中。
人们可以使用钥匙串,但由于iPhone应用程序永远不需要提供密码来存储钥匙串中的东西,我很谨慎,有人可以访问应用程序的沙箱可以并且能够简单地查看或简单地解码其中的项目。
编辑 – 所以我读了关于钥匙串的这个:“在iPhone OS中,应用程序总是可以访问自己的钥匙串项目,并且不能访问任何其他应用程序的项目。系统为钥匙串生成自己的密码,并存储密钥在设备上,这样的方式,任何应用程序都无法访问。“
所以也许这是存储密钥的最好的地方….如果是这样的话,我应该如何使用预先input到应用程序密钥链中的密钥? 那可能吗? 否则,你怎么能在第一次启动的时候添encryption钥,而不是密钥在源代码中? 嗯..
编辑 – 提交错误报告#6584858在http://bugreport.apple.com
谢谢。
简单的答案是,就目前情况来看,只能在iPhone上保密。 越狱的iPhone只是一个通用的电脑,可以放在你的手中。 没有可以访问的可信平台硬件。 用户可以欺骗任何你可以想象用来唯一标识给定的设备。 用户可以将代码注入到stream程中来执行诸如检查钥匙串的操作。 (searchMobileSubstrate看看我的意思。)对不起,你搞砸了。
这种情况下的一缕光线就在应用购买收据中。 如果您在应用程序中使用应用程序购买应用程序中的某个商品,则会得到一个encryption签名的收据,并且可以通过Apple的需求进行validation。 即使你不能保证收据的秘密,它可以追溯到(通过苹果,而不是你)到一个特定的购买,这可能会阻止海盗分享他们。 您也可以在每个收据的基础上限制对服务器的访问,以防止服务器资源被盗版耗尽。
目标是最终限制Web服务访问授权用户,对吧? 如果您控制Web服务(如果您不 – 将其包装在您所控制的Web服务中)非常容易。
1)创build一个公钥/私钥对。 私钥放在Web服务服务器上,放在地牢中,由龙守卫。 公共密钥在电话上。 如果有人能够读取公钥, 这不是问题 。
2)让应用程序的每个副本生成一个唯一的标识符。 你如何做到这一点取决于你。 例如,你可以在下载时将其构build到可执行文件中(对于iPhone应用程序,这是可能的)? 你可以使用手机的GUID,假设他们有一个计算方法。 如果你真的想要的话,你也可以重做每个会话。
3)使用公钥encryption“我的唯一标识符是$ FOO,我批准了这条消息”。 提交到Web服务的每个请求。
4)Web服务解密每个请求,反弹任何不包含有效的标识符。 您可以按照您的要求做任何事情:保持白名单/黑名单,根据每个标识符监控使用情况,并调查可疑行为等。
5)由于唯一的标识符现在不会通过线路发送,所以唯一的方法是对手机进行物理访问。 如果他们能够物理访问电话,则无法控制电话上的任何数据 。 总是。 不能帮助。 这就是为什么我们build立这样的系统,妥协一个电话绝不妥协多个帐户。
6)构build业务stream程以满足以下需求:a)删除正在滥用的用户的访问权限; b)恢复对电话遭到身体威胁的用户的访问权限(除非用户是对手)。
UAObfuscatedString可以解决您的问题。 从文档:
当你编写有一个string常量的代码时,这个string以明文forms保存在二进制文件中。 黑客可能会发现漏洞或更改string以影响您的应用的行为。 UAObfuscatedString只在二进制文件中存储单个字符,然后在运行时将它们组合起来以产生你的string。 这些单个字母不太可能在二进制文件中被发现,因为它们会在编译后的代码中随机插入。 因此,他们似乎是随机的代码给任何人试图提取string。
如果你可以忍受只有iPhone OS 3.0,你可能想看看推送通知。 我不能详细说明,但是您可以将通知本身的有效负载传递给Apple的服务器。 当他们接受警报(或者如果你的应用程序正在运行),那么你的代码的一部分被调用并且钥匙串项目被存储。 在这一点上,这是我能想到的在iPhone上安全地存储秘密的唯一途径。
我有同样的问题,花了很多时间来寻找答案。 问题是鸡和蛋:如何预先使用您的应用程序所需的数据对钥匙串进行检测。
无论如何,我发现一种技术至less会让越狱者难以发现信息 – 他们至less不得不反汇编你的代码来找出你做了什么来掩盖信息:
string混淆 (如果链接中断search“混淆/encryptionstring(NSString)”)
本质上,string在放入应用程序之前被模糊处理,然后使用代码对其进行无法处理。
它比无所事事好。
大卫
编辑:我实际上在一个应用程序中使用这个。 我把一个基本的编码string放到info.plist中,然后在代码中做了几个操作 – rot13,rotate / invert bytes等。最后处理的string被用来解码混淆的string。 现在,三信机构可以肯定地打破这一点 – 但花费了很多时间来解码二进制文件。
我会说,这是我遇到的最好的技术,但我只是阅读Kiran的UAObfuscatedString (不同的答案)的post,这是一个完全不同的方式混淆。 它有没有保存在应用程序的任何地方的string的好处 – 每个字母变成一个方法调用。 select器将显示为string,所以黑客可以很快地告诉你的class级使用该技术。
我认为这个类似的问题和我的回答也可能与你的情况有关。 简而言之,iPhone中有一个值得信赖的平台模块。 这将允许您的服务信任iPhone,即使在攻击者的手中。 但是,看起来像使用钥匙串是你最好的select。
你有没有考虑/尝试推送通知的build议,最初将秘密传输到应用程序和钥匙串? 或者最终find其他方法来实现这一目标?
我要让我的iPhone应用程序上传图片到Amazon S3。 而不是将AWS凭证放在应用程序中,我将把应用程序电话置于我的服务器中,以获取在S3上载请求中使用的URI和标头。 我的服务器将生成S3 URI,正确的签名等。然后,我可以在自己的应用程序的webservice上实现比AWS自身提供的更紧密,更具体的安全模型,而不会将我的AWS密钥泄露给使用越狱iphone的任何人。
但是仍然需要一些信任(证书或其他)给予应用程序,并且信任可能会被盗用。 所有你能做的就是限制如果有人越狱iPhone和窃取任何凭证在应用程序造成的损害。 这些证书越强大,最糟糕的事情是。 如何限制凭证的权力包括:
- 避免全局凭据。 使他们每个用户/应用程序
- 避免永久凭据。 如果可能的话,让他们临时
- 避免全局权限。 给他们只有他们需要的权限。 例如,写入权限可能被分解为插入,覆盖,删除,写入资源组A或B等,读取可能被分解为读取命名资源,读取所有现有资源的列表,读取资源组A或B等等
如果可能,我build议在运行时创build一个密钥。 这样,如果关键是在特定的会话期间得到逮捕,一旦会话结束,密钥将是毫无价值的。 如果他们足够聪明的话,他们仍然可以从记忆中领悟到关键,但是关键在一段时间之后会失效,这并不重要。
听起来不可思议。 将使用HTTPS和可能的encryption包来处理密钥。
我认为CommonCrypto适用于iPhone。
编辑:仍然听起来不可思议。 为什么有人会通过一个HTTP头的密钥? 任何追踪你的networkingstream量的人(例如通过一个logging无线路由器)都会看到它。
对于消息stream量的encryption,有完善的安全方法…为什么不使用它们,而不是发明基本上是一个普通的有缺陷的系统?
编辑二:啊,我明白了。 我会继续使用钥匙串…我认为它只适用于这种情况。 我错过了使用密钥生成请求。 如果可以的话,仍然会使用HTTPS,因为这样你就不会冒险通过检查足够的签名来推断你的密钥生成scheme。