如果可以对源代码进行逆向工程,那么在 Android(或 Java)中加密任何东西有啥意义?

Posted

技术标签:

【中文标题】如果可以对源代码进行逆向工程,那么在 Android(或 Java)中加密任何东西有啥意义?【英文标题】:What is the point of encrypting anything in Android (or Java) if source code can be reverse engineered?如果可以对源代码进行逆向工程,那么在 Android(或 Java)中加密任何东西有什么意义? 【发布时间】:2011-10-30 03:17:40 【问题描述】:

android 和 Java 提供了一个crypto API,对于非加密专家来说相对容易使用。

但既然我们知道没有代码可以真正免受逆向工程的影响,尤其是用作种子或共享机密的字符串常量,我想知道:在 Android 应用程序中经历加密和解密的考验有什么意义?

我错过了什么吗?

试图让我的问题更清楚、更具体:假设我有一个应用程序,其中某些字符串代码使用,而 in代码(即用户数据)需要保密:一种方法是以加密形式将它们存储在编译后的.apk 中,并在运行时对其进行解密(使用模糊的硬编码密码)。另一种方法是将它们以加密形式存储在远程服务器中,(通过 Internet)获取它们并在运行时解密(使用共享密码)。

我认为两者之间没有太大区别,因为两者都需要在(可逆向工程的)代码中存在“密钥”。

这个问题有解决办法吗?

如果没有解决方案,为什么还要加密?

【问题讨论】:

锁你的房子或你的车的原因是一样的。它不会阻止真正想进入的人,但会鼓励他们中的一些人转向未锁定的事物。 你说的是加密用户数据,还是加密应用程序代码? 您错过了一个事实,即您不应在代码中存储密钥 @dlev 好的,但是您如何解决我的帖子更新中描述的问题? @Nayuki Minase 不,我不是在谈论加密用户数据。我主要对加密 application 数据感兴趣。我刚刚更新了我的问题以使这一点更清楚。 【参考方案1】:

严格来说,这不是 Android 或 Java 的问题。任何事情都可以逆转,如果它是本机代码,那就更难了。请记住,他们甚至不必反转它:您最终必须解密内存中的数据来操作它。此时,攻击者只需进行内存转储即可获取您的数据。如果他们可以物理访问设备,并且您正在软件中操纵数据,那么您实际上无法阻止他们。解决方案是使用专用的硬件模块 (HSM),该模块具有防篡改或至少防篡改功能(如果有人弄乱了它,它要么删除所有数据,要么至少保留一些事件记录)。它们有不同的形状和大小,从智能卡到成本很多的网络连接设备。目前不适用于 Android,但可能会获得类似于 TPM 的功能,因此您可以安全地存储您的密钥并在硬件中进行加密操作。

因此,请考虑您的数据需要多么保密,并决定适当的保护级别。

您可能希望通过 SSL 下载它(这将在传输过程中保护它),确保您对服务器进行身份验证(这样您就知道您从受信任的地方获取了正确的数据)和 em> 客户(因此您可以确定您只将数据提供给正确的人)。您可以为此使用 SSL 客户端身份验证,它比您(或任何不是密码学专家)可能附带的任何自定义加密/密钥交换方案更安全。

【讨论】:

出色的分析和答案。我同意这不是严格意义上的 Android 或 Java 问题,但例如,Java 比 x86 机器代码更容易反编译成 Java。【参考方案2】:

加密 API 中的共享密钥不是您将存储在应用程序中的东西(正如您所说,容易受到逆向工程的影响——尽管可能不像您想的那样容易受到攻击期望;混淆很容易)。

想象一下,您想在手机上创建/读取加密文件(用于您的秘密购物清单)。

创建后,您使用主密码保存它(该密码会立即被程序丢弃)。然后当你想阅读它时,你必须重新输入你的主密码。这就是 API 所指的共享秘密,它与逆向工程完全无关。

【讨论】:

感谢 +1 的回答,但在某些情况下手动重新输入主密码不太实用。有没有办法自动做到这一点? 当然;只要密码没有存储在代码中,一切都很好。例如,如果我想在服务器上安全地存储加密数据(例如,可能使用 Dropbox API),我可以输入我的主密码并将其保存为首选项,然后每次上传时,它都会进入磁盘,看起来对于密码(如果找不到它会提示我),加密并上传。下载也是如此。他们的关键是你不应该在你的代码中存储任何秘密(你的代码应该同样安全,即使它是开源的)。 不要忘记您可以使用文件系统权限将密钥存储在设备上,这是从互联网上提取密钥或让用户输入主密码的下一个最佳选择。使用 MODE_PRIVATE 将其存储在平面文件中。您无法以这种方式保护用户免受他们自己(或其他窃取手机的人)的伤害,但至少其他应用程序无法读取它。 @alex c 将密码存储在首选项中不是一种选择,因为它不是用户的密码,而是应用程序的密码。我希望这更清楚。我如何摆脱这个第 22 条问题的难题? :) 编辑:根据你的新帖子,我想说手动加密来做你想做的事是不可能的。因为字符串必须在某个时候解密,所以它必须是可逆向工程的(如果没有别的,通过在正确的时间检查内存)。也许我误解了你在问什么。我会考虑一下的。【参考方案3】:

您描述的问题有点类似于storing a master password 的密码管理器问题。

在这种情况下,提供的解决方案是使用salt for password hashes。

【讨论】:

【参考方案4】:

ateiob 每当您将主密码存储在应用程序中时,您实际上只是让未经授权的用户更难访问加密数据。

首先,我们可以同意,使用嵌入在应用程序中的“主密钥”加密数据并将该数据存储在手机上对“主密钥”进行逆向工程和解密数据是开放的。

其次,我认为我们可以同意,使用密码加密数据然后删除密码应该是相当安全的,使用强加密、256 位密钥和强密码。这两种技术都适用于移动设备上的编程。事实上,ios 开箱即用地支持 BOTH 需求。

[keychainData setObject:@"password" forKey:(id)kSecValueData]; 

也许一个真实的例子可能会有所帮助。

假设如果在内存不足的情况下必须保留和保护临时数据字段,则可以使用主密码对其进行加密,并在 用户 清除临时数据字段时将其清除。临时数据字段永远不会存储为纯文本。

所以有两个密码,一个主密码,嵌入在应用程序中用于临时短期加密和一个秘密密码,通常必须由用户输入,用于长期持久的加密数据。

最后,如果您正在加密文件,请考虑添加另一层间接性。因此,当前的秘密密码用于加密一个随机密钥,该密钥用于加密所有用户的文件。这允许用户更改秘密密码而无需解密,加密所有加密文件。

【讨论】:

【参考方案5】:

假定攻击者拥有您的代码副本。您的数据的保密性应完全取决于密钥。见Kerckhoffs's Principle。

要保密您的密钥,您必须将其与您的代码分开。记住它。把它放在钱包里的一张纸上。将其存储在您通常保存在保险箱中的 U 盘上。使用像PasswordSafe 这样的程序。有很多可能性。

当然可以让任何攻击者通过多层密钥来获得她真正需要的密钥。 PasswordSafe 和类似的就是这样一种选择。您会注意到,此类程序不会为您提供“记住密码”的选项。

【讨论】:

他正在谈论将密钥嵌入代码中。不是隐藏密码。 引用这个问题,“我认为两者之间没有太大区别,因为两者都需要(可反向工程的)代码中存在“密钥”。”我建议了密钥出现在代码中的方式。 @alexanderblom 正确理解了我的问题。我不是在询问用户数据的加密。我专门询问加密 代码 本身使用的某些数据。 “两者”是指将加密字符串存储在本地与远程服务器中。 我提供了第三种选择。你说得对,把钥匙放在代码里很危险。例如,每天早上将 USB 插入几秒钟,让服务器从 USB 上的主密钥导出当天的密钥。这可以在服务器与网络断开连接的情况下完成。然后最多可以泄露一天的密钥。

以上是关于如果可以对源代码进行逆向工程,那么在 Android(或 Java)中加密任何东西有啥意义?的主要内容,如果未能解决你的问题,请参考以下文章

使用 .exe 制作谜语

对现代软件工程开发看法

逆向libbaiduprotect

特征工程之特征选择

获取日期和货币格式

在 iOS 代码中嵌入 API 凭据