如果源代码可以进行逆向工程,那么对 Android(或 Java)中的任何内容进行加密还有什么意义呢?
Android 和 Java 提供了加密 API,对于加密非加密货币来说相对容易使用专家。
但既然我们知道没有任何代码可以真正免受逆向工程的影响,尤其是用作种子或共享秘密的字符串常量,我想知道:在 Android 应用程序中经历加密和解密的考验有什么意义?
我错过了什么吗?
试图让我的问题更清晰、更具体:假设我有一个应用程序,其中某些字符串在代码中和代码中使用(即不是用户数据)需要保密:一种方法是将它们以加密形式存储在已编译的 .apk
中,并在以下地址解密(使用模糊的硬编码密码):运行时。另一种方法是以加密形式将它们存储在远程服务器中,(通过互联网)获取它们并在运行时解密(使用共享密码)它们。
我认为两者之间没有太大区别,因为两者都需要(可逆向工程的)代码中存在“密钥”。
这个问题有解决办法吗?
如果没有解决方案,为什么还要加密呢?
Android and Java provide a crypto API that is relatively easy to use for crypto non-experts.
But since we know that no code can really be protected from reverse engineering, especially string constants used as seeds or shared secrets, I am wondering: What is the point of going through the ordeal of encrypting and decrypting in Android applications?
Am I missing something?
Trying to make my question clearer and more concrete: Suppose I have an application in which certain strings used by the code and in the code (i.e. not user data) need to be secret: One approach is to store them in encrypted form in the compiled .apk
and decrypt them (using an obfuscated hard-coded password) at runtime. Another approach would be to store them in encrypted form in a remote server, fetch them (over the Internet) and decrypt (using a shared password) them at runtime.
I don't see much difference between the two, since both require the "secret key" being present in the (reverse-engineer-able) code.
Is there a solution to this problem?
If there isn't a solution, why encrypt at all?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
严格来说,这并不是 Android 或 Java 的问题。任何事情都可以逆转,只是如果是本机代码就更难了。请记住,他们甚至不必反转它:您必须最终解密内存中的数据才能操作它。此时,攻击者只需进行内存转储即可获取您的数据。如果他们可以物理访问设备,并且您正在软件中操作数据,那么您实际上无法阻止他们。解决方案是使用防篡改或至少防篡改的专用硬件模块 (HSM)(如果有人弄乱它,它要么删除所有数据,要么至少保留一些数据)事件的日志)。它们有不同的形状和大小,从智能卡到成本高昂的网络连接设备。目前不适用于 Android,但也许它将获得类似于 TPM 的功能,因此您可以安全地存储密钥并在硬件中执行加密操作。
因此,请考虑您的数据需要保密到什么程度,并决定适当的保护级别。
您可能希望通过 SSL 下载数据(这将在传输过程中保护数据),确保您对服务器(这样您就知道您正在从受信任的位置获取正确的数据)和服务器进行身份验证。客户(这样您就可以确定您只将数据提供给正确的人)。为此,您可以使用 SSL 客户端身份验证,它将比您(或任何非加密专家)可能使用的任何自定义加密/密钥交换方案安全得多。
This is not strictly a problem with Android or Java. Anything can be reversed, it's just harder if it's native code. And bear in mind that they don't even have to reverse it: you have to eventually decrypt the data on memory to manipulate it. At this point, the attacker can just take a memory dump and they will get your data. If they have physical access to the device, and you are manipulating the data in software, there is really nothing you can do to stop them. The solution for this is to use a dedicated hardware module (HSM) that is tamper-resistant or at least tamper-evident (if some one messes with it, it either deletes all data or at least keeps some logs of the event). Those come in different shapes and sizes ranging from smart cards to network connected devices that cost a lot. Currently not available for Android, but maybe it will get something similar to a TPM, so you can store your keys securely and do crypto operations in hardware.
So consider just how secret your data needs to be and decide on an adequate protection level.
You might want to have it downloaded it over SSL (that would protect it in transit), making sure you authenticate both the server (so you know you re getting the right data from a trusted place) and the client (so you can be sure you are only giving the data to the right person). You can use SSL client authentication for this, and it will be much more secure than any custom encryption/key exchange scheme you (or anyone who is not a cryptography expert) might come with.
加密 API 中的共享秘密不是您要存储在应用程序中的内容(正如您所说,会容易受到逆向工程的攻击 - 尽管可能不像您预期的那么容易受到攻击;混淆)非常简单)。
想象一下,您想在手机上创建/读取加密文件(用于您的秘密购物清单)。
创建后,您可以使用主密码保存它(该密码会立即被程序丢弃)。然后当你想阅读它时,你必须重新输入你的主密码。这是 API 所指的共享秘密,它与逆向工程完全无关。
The shared secret in the crypto API is not something that you would store in the app (as you say, that would be vulnerable to reverse-engineering -- though perhaps not as vulnerable as you would expect; obfuscation is pretty easy).
Imagine instead you wanted to create/read encrypted files on your phone (for your secret grocery list).
After creating one, you save it using a master password (that is immediately discarded by the program). Then when you want to read it, you have to re-enter your master password. That's the shared secret the API refers to, and it is completely tangential to reverse-engineering.
您描述的问题有点类似于密码管理器问题的存储主密码。
在这种情况下,提供的解决方案是使用盐作为密码哈希。
The problem you are describing is somewhat similar to storing a master password for a password manager problem.
In that case the solution offered is using salt for password hashes.
ateiob 每当您将主密码存储在应用程序中时,实际上都会使未经授权的用户访问加密数据变得更加困难。
首先,我们可以同意,使用嵌入应用程序中的“主密钥”加密数据并将该数据存储在手机上,可以对“主密钥”进行逆向工程并解密数据。
其次,我认为我们可以同意,使用强加密、256 位密钥和强密码,使用秘密密码加密数据然后删除秘密密码应该相当安全。这两种技术都适用于移动设备上的编程。事实上,iOS 开箱即用地支持这两种需求。
也许一个现实世界的例子可能会有所帮助。
假设如果在低内存上必须保留和保护临时数据字段,则可以使用主密码对其进行加密,并在用户清除临时数据字段时将其清除。临时数据字段永远不会以纯文本形式存储。
因此,有两个密码,一个是嵌入应用程序中的主密码,用于临时短期加密;另一个是秘密密码,通常必须由用户输入,以实现长期持久的加密数据。
最后,如果您要加密文件,请考虑添加另一个间接级别。这样当前的秘密密码将用于加密随机密钥,该随机密钥用于加密所有用户的文件。这允许用户更改秘密密码而无需解密、加密所有加密文件。
ateiob Any time you store the master password in the app you are really just making it a bit harder for unauthorized users to access the encrypted data.
First we can agree that encrypting data with a "master key" embedded in an application and storing that data on the phone is open to having the "master key" reverse engineered and the data decrypted.
Second I think we can agree that encrypting data with a secret password and then deleting the secret password should be reasonably safe using strong encryption, 256 bit keys and strong passwords. Both techniques apply to programming on mobile devices. In fact, iOS, supports BOTH needs out of the box.
Perhaps a real world example may help.
Say if on low memory a temporary data field must be persisted and protected, it can be encrypted with a master password and cleared when the user clears the temporary data field. The temporary data field is never stored as plain text.
So there are two passwords, a master password, embedded in the app for temporary short term encryption and a secret password, that usually must be entered by the user, for longer term persisted encrypted data.
Finally, if you are encrypting files, consider adding another level of indirection. So that the current secret password is used to encrypt a random key which is used to encrypt all the user's files. This allows the user to change the secret password without any need to decrypt, encrypt all the encrypted files.
假定攻击者拥有您的代码的副本。您的数据的保密性应完全取决于密钥。请参阅Kerckhoffs 原理。
为了保密您的密钥,您必须将其与代码分开。记住它。将其记在钱包里的一张纸上。将其存储在通常放在保险箱中的 USB 记忆棒上。使用诸如 PasswordSafe 之类的程序。有很多可能性。
当然,任何攻击者都有可能通过多层密钥来获取她真正需要的密钥。 PasswordSafe 和类似的就是这样的选项之一。您会注意到,此类程序不会为您提供“记住您的密码”的选项。
The attacker is assumed to have a copy of your code. The secrecy of your data should depend entirely on the key. See Kerckhoffs's Principle.
To keep your key secret you must separate it from your code. Remember it. Keep it on a piece of paper in your wallet. Store it on a USB stick that you usually keep in a safe. Use a program like PasswordSafe. There are many possibilities.
It is of course possible to make any attacker work her way through many layers of keys to get to the key she actually needs. PasswordSafe and similar are one such option. You will notice that such programs do not give you an option to "remember your password" for you.