iOS App场景中的安全密钥,安全吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14778429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Secure keys in iOS App scenario, is it safe?
提问by shannoga
I am trying to hide 2 secrets that I am using in one of my apps.
我试图隐藏我在我的一个应用程序中使用的 2 个秘密。
As I understand the keychain is a good place but I can not add them before I submit the app.
据我所知,钥匙串是个好地方,但在提交应用程序之前我无法添加它们。
I thought about this scenario -
我想到了这个场景——
- Pre seed the secrets in my app's CoreData Database by spreading them in other entities to obscure them. (I already have a seed DB in that app).
- As the app launches for the first time, generate and move the keys to the keychain.
- Delete the records from CoreData.
- 通过将秘密传播到其他实体中以隐藏它们,在我的应用程序的 CoreData 数据库中预先播种秘密。(我已经在该应用程序中有一个种子数据库)。
- 当应用程序首次启动时,生成密钥并将其移动到钥匙串。
- 从 CoreData 中删除记录。
Is that safe or can the hacker see this happening and get those keys?
这是安全的还是黑客可以看到这种情况并获得这些密钥?
*THIRD EDIT** Sorry for not explaining this scenario from the beginning - The App has many levels, each level contains files (audio, video, images). The user can purchase a level (IAP) and after the purchase is completed I need to download the files to his device.
*第三次编辑** 抱歉没有从一开始就解释这个场景 - 该应用程序有很多级别,每个级别都包含文件(音频、视频、图像)。用户可以购买一个级别 (IAP),购买完成后我需要将文件下载到他的设备上。
For iOS6 the files are stored with Apple new "Hosted Content" feature. For iOS5 the files are stored in amazon S3.
对于 iOS6,文件使用 Apple 新的“托管内容”功能存储。对于 iOS5,文件存储在 amazon S3 中。
So in all this process I have 2 keys: 1. IAP key, for verifying the purchase at Apple IAP. 2. S3 keys, for getting the files from S3 for iOS5 users:
所以在整个过程中,我有 2 个密钥: 1. IAP 密钥,用于验证在 Apple IAP 上的购买。2. S3 密钥,用于 iOS5 用户从 S3 获取文件:
NSString *secretAccessKey = @"xxxxxxxxx";
NSString *accessKey = @"xxxxxxxxx";
Do I need to protect those keys at all? I am afraid that people will be able to get the files from S3 with out purchasing the levels. Or that hackers will be able to build a hacked version with all the levels pre-downloaded inside.
我需要保护这些密钥吗?恐怕人们无需购买关卡就可以从 S3 获取文件。或者黑客将能够构建一个预先下载所有级别的黑客版本。
回答by Victor Ronin
Let me try to break down your question to multiple subquestions/assumption:
让我尝试将您的问题分解为多个子问题/假设:
Assumptions:
假设:
a) Keychain is safe place
a) 钥匙扣是安全的地方
Actually, it's not that safe. If your application is installed on jailbroked device, a hacker will be able to get your keys from the keychain
事实上,它并不那么安全。如果您的应用程序安装在越狱设备上,黑客将能够从钥匙串中获取您的密钥
Questions:
问题:
a) Is there a way to put some key into an app (binary which is delivered form AppStore) and be completely secure?
a) 有没有办法将一些密钥放入应用程序(从 AppStore 交付的二进制文件)中并完全安全?
Short answer is NO. As soon as there is something in your binary, it could be reverse engineered.
简短的回答是否定的。只要你的二进制文件中有东西,它就可以被逆向工程。
b) Will obfuscation help?
b) 混淆有帮助吗?
Yes. It will increase time for a hacker to figure it out. If the keys which you have in app will "cost" less than a time spend on reverse engineering - generally speaking, you are good.
是的。这将增加黑客弄清楚的时间。如果您在应用程序中拥有的密钥的“成本”低于在逆向工程上花费的时间 - 一般来说,您很好。
However, in most cases, security through obscurity is bad practice, It gives you a feeling that you are secure, but you aren't.
然而,在大多数情况下,通过默默无闻来确保安全是不好的做法,它让您感觉自己很安全,但实际上并非如此。
So, this could be one of security measures, but you need to have other security measures in place too.
因此,这可能是一种安全措施,但您还需要采取其他安全措施。
c) What should I do in such case?*
c) 在这种情况下我应该怎么做?*
It's hard to give you a good solution without knowing background what you are trying to do.
如果不了解您正在尝试做什么的背景,很难为您提供一个好的解决方案。
As example, why everybody should have access to the same Amazon S3? Do they need to read-only or write (as pointed out by Kendall Helmstetter Gein).
例如,为什么每个人都应该访问同一个 Amazon S3?他们需要只读还是写(如 Kendall Helmstetter Gein 所指出的)。
I believe one of the most secure scenarios would be something like that:
我相信最安全的场景之一是这样的:
- Your application should be passcode protected
- First time you enter your application it requests a user to authenticate (enter his username, password) to the server
- This authenticates against your server or other authentication provider (e.g. Google)
- The server sends some authentication token to a device (quite often it's some type of cookie).
- You encrypt this token based on hash of your application passcode and save it in keychain in this form
- And now you can do one of two things:
- hand over specific keys from the server to the client (so each client will have their own keys) and encrypt them with the hash of your application passcode
- handle all operation with S3 on the server (and require client to send)
- 您的应用程序应该受密码保护
- 第一次进入应用程序时,它会请求用户向服务器进行身份验证(输入用户名、密码)
- 这会针对您的服务器或其他身份验证提供商(例如 Google)进行身份验证
- 服务器向设备发送一些身份验证令牌(通常是某种类型的 cookie)。
- 您根据应用程序密码的哈希值加密此令牌,并以这种形式将其保存在钥匙串中
- 现在你可以做两件事之一:
- 将特定密钥从服务器移交给客户端(因此每个客户端都有自己的密钥)并使用您的应用程序密码的散列对其进行加密
- 在服务器上使用 S3 处理所有操作(并要求客户端发送)
This way your protect from multiple possible attacks.
这样您就可以免受多种可能的攻击。
c) Whoooa.... I don't plan to implement all of this stuff which you just wrote, because it will take me months. Is there anything simpler?
c) Whoooa.... 我不打算实施你刚刚写的所有这些东西,因为这将花费我几个月的时间。有没有更简单的?
I think it would be useful, if you have one set of keys per client.
如果每个客户端有一组密钥,我认为这会很有用。
If even this is too much then download encrypted keys from the server and save them in encrypted form on the device and have decryption key hardcoded into your app. I would say it's minimally invasive and at least your binary doesn't have keys in it.
如果这太多了,那么从服务器下载加密密钥并将它们以加密形式保存在设备上,并将解密密钥硬编码到您的应用程序中。我会说它是微创的,至少您的二进制文件中没有密钥。
P.S. Both Kendall and Rob are right.
PS 肯德尔和罗布都是对的。
Update 1 (based on new info)
更新 1(基于新信息)
First of all, have you seen in app purchase programming guide.
首先,您是否在应用购买编程指南中看到过。
There is very good drawing under Server Product Model. This model protects against somebody who didn't buy new levels. There will be no amazon keys embedded in your application and your server side will hand over levels when it will receive receipt of purchase.
Server Product Model下有很好的绘图。此模型可防止未购买新关卡的人。您的应用程序中不会嵌入亚马逊密钥,您的服务器端将在收到购买收据时移交级别。
There is no perfect solution to protect against somebody who purchased the content (and decided to rip it off from your application), because at the end of days your application will have the content downloaded to a device and will need it in plain (unencrypted form) at some point of time.
没有完美的解决方案可以防止有人购买了内容(并决定从您的应用程序中窃取它),因为最终您的应用程序会将内容下载到设备上,并且需要以明文形式(未加密形式) ) 在某个时间点。
If you are really concerned about this case, I would recommend to encrypt all your assets and hand over it in encrypted form from the server together with encryption key. Encryption key should be generated per client and asset should be encrypted using it.
如果您真的很担心这种情况,我建议您将所有资产加密,并以加密形式从服务器与加密密钥一起移交。应为每个客户端生成加密密钥,并应使用它对资产进行加密。
This won't stop any advanced hacker, but at least it will protect from somebody using iExplorer and just copying files (since they will be encrypted).
这不会阻止任何高级黑客,但至少可以防止有人使用 iExplorer 并且只是复制文件(因为它们将被加密)。
Update 2
更新 2
One more thing regarding update 1. You should store files unencrypted and store encryption key somewhere (e.g. in keychain).
关于更新 1 的另一件事。您应该存储未加密的文件并将加密密钥存储在某处(例如在钥匙串中)。
In case your game requires internet connection, the best idea is to not store encryption key on the device at all. You can get it from the server each time when your app is started.
如果您的游戏需要互联网连接,最好不要在设备上存储加密密钥。每次启动应用程序时,您都可以从服务器获取它。
回答by Kendall Helmstetter Gelner
DO NOTstore an S3 key used for write in your app! In short order someone sniffing traffic will see the write call to S3, in shorter order they will find that key and do whatever they like.
不要在您的应用程序中存储用于写入的 S3 密钥!很快,嗅探流量的人会看到对 S3 的写调用,更短的时间,他们会找到那个密钥并做任何他们喜欢的事情。
The ONLY way an application can write content to S3 with any degree of security is by going through a server you control.
应用程序可以以任何安全级别将内容写入 S3 的唯一方法是通过您控制的服务器。
If it's a key used for read-only use, meaning your S3 cannot be read publicly but the key can be used for read-only access with no ability to write, then you could embed it in the application but anyone wanting to can pull it out.
如果它是用于只读用途的密钥,这意味着您的 S3 不能被公开读取,但该密钥可用于只读访问而不能写入,那么您可以将其嵌入到应用程序中,但任何人都可以提取它出去。
To lightly obscure pre-loaded sensitive data you could encrypt it in a file and the app can read it in to memory and decrypt before storing in the keychain. Again, someone will be able to get to these keys so it better not matter much if they can.
要稍微隐藏预加载的敏感数据,您可以将其加密到文件中,应用程序可以将其读入内存并在存储到钥匙串之前解密。同样,有人将能够获得这些密钥,因此最好不要有太大关系。
Edit:
编辑:
Based on new information you are probably better off just embedding the secrets in code. Using a tool like iExplorer a causal user can easily get to a core data database or anything else in your application bundle, but object files are somewhat encrypted. If they have a jailbroken device they can easily get the un-encrypted versions but it still can be hard to find meaningful strings, perhaps store them in two parts and re-assemble in code.
根据新信息,您最好将秘密嵌入代码中。使用 iExplorer 之类的工具,因果用户可以轻松访问核心数据数据库或应用程序包中的任何其他内容,但目标文件在某种程度上是加密的。如果他们有一个越狱的设备,他们可以很容易地获得未加密的版本,但仍然很难找到有意义的字符串,也许将它们存储在两部分并重新组合成代码。
Again it will not stop a determined hacker but it's enough to keep most people out.
同样,它不会阻止坚定的黑客,但足以将大多数人拒之门外。
You might want to also add some code that would attempt to ask your server if there's any override secrets it can download. That way if the secrets are leaked you could quickly react to it by changing the secrets used for your app, while shutting out anyone using a copied secret. To start with there would be no override to download. You don't want to have to wait for an application update to be able to use new keys.
您可能还想添加一些代码来尝试询问您的服务器是否有任何可以下载的覆盖机密。这样,如果机密被泄露,您可以通过更改用于您的应用程序的机密快速做出反应,同时将任何使用复制机密的人拒之门外。首先将没有覆盖下载。您不想等待应用程序更新才能使用新密钥。
回答by Rob Napier
There is no good way to hide a secret in a piece of code you send your attacker. As with most things of this type, you need to focus more on how to mitigate the problem when the key does leak rather than spend unbounded time trying to protect it. For instance, generating different keys for each user allows you to disable a key if it is being used abusively. Or working through a intermediary server allows you to control the protocol (i.e. the server has the key and is only willing to do certain things with it).
没有什么好方法可以在您发送给攻击者的一段代码中隐藏秘密。与大多数此类事情一样,您需要更多地关注如何在密钥泄漏时缓解问题,而不是花费无限的时间来尝试保护它。例如,为每个用户生成不同的密钥允许您禁用滥用的密钥。或者通过中间服务器工作允许您控制协议(即服务器拥有密钥并且只愿意用它做某些事情)。
It is not a waste of time to do a little obfuscating. That's fine. But don't spend a lot of time on it. If it's in the program and it's highly valuable, then it will be hacked out. Focus on how to detect when that happens, and how to recover when it does. And as much as possible, move that kind of sensitive data into some other server that you control.
做一点混淆不是浪费时间。没关系。但是不要花太多时间在上面。如果它在程序中并且非常有价值,那么它就会被黑掉。专注于如何检测何时发生,以及如何恢复。并尽可能将此类敏感数据移动到您控制的其他服务器中。