保护Android应用程序敏感数据的最佳方法?


74

是的,这是一个非常普遍的问题,但是我正在尝试一种最佳方式来处理与基础服务器/向敏感应用程序分发敏感数据的网络服务器相关的应用程序。任何链接,一般信息建议等。

由于该应用程序将存储从数据库中检索到的持久性数据达一定时间,所以一切都变得有些棘手。


数据库不是存储敏感信息的好选择吗?

保护谁?您应用的合法用户,电话窃贼,病毒...
CodesInChaos 2011年

Answers:


104

在设备上存储敏感数据

这在很大程度上取决于您的听众。通常,Android OS禁止应用程序通过经过验证的Linux文件权限来访问彼此的文件(即数据库,首选项文件,存储在应用程序私有目录中的常规文件)。但是,在具有root用户权限的设备上,应用程序可以获取root用户访问权限并读取所有内容。需要考虑的几件事:

  1. 如果您知道您的用户没有root用户(例如,如果您不是通过Android Market分发应用程序,而是仅在您的公司或类似机构中进行分发),则可以仅依靠Android基于文件系统的安全性。
  2. 如果用户确实具有root用户访问权限,则他将非常小心他赋予特权的应用程序
  3. 如果应用程序确实具有root用户访问权限,则可能造成很多破坏。您的应用中的信息可能是用户的后顾之忧。
  4. 生根导致零保修。包括在应用程序中。您不对在已扎根电话上泄漏信息负责。

总而言之,如果您的信息不是超级敏锐的信息(例如信用卡信息),我建议您坚持使用Android提供的默认安全性(即,将所有内容保存为纯文本格式,因为其他应用程序无法访问它)。

否则,加密是必经之路。它不是100%安全的(黑客可以反编译您的应用程序并弄清楚如何解密数据),但这是破解的主要难题,它将阻止大多数黑客。特别是如果您使用ProGuard之类的代码来混淆您的代码。


将敏感数据从服务器传输到设备

您在这里有一些选择。首先,始终使用HTTPS。启用HTTPS之后,我将建议以下两项额外的安全措施:

  1. 使用API​​密钥系统。在所有请求中都包含此API密钥,并在发回任何响应之前在服务器端进行检查。请记住,由于您使用的是HTTPS,因此攻击者将无法仅使用网络嗅探器来查找您的API密钥。但是,这很容易弄清楚是否有人对您的应用程序进行反编译,这就是为什么您可以进一步对其进行混淆(除了使用ProGuard之外)的原因。例如,您可以将API密钥在您的代码中分成多个部分(例如,作为两个或三个类中的静态成员)。然后,当您发送请求时,只需将所有这些片段连接在一起。您甚至可以应用其他类型的转换(例如,移位),以使其更难于从反编译的代码中找出。
  2. 您可以在每次发送请求时生成密钥。该密钥将通过使用仅您知道的一些逻辑来生成,以便您也可以在客户端和服务器端实现它。例如,请求可以包括以下参数:
    time=1321802432&key=[generated-key]
    其中generated-key是从所生成的time参数。例如:md5(time + salt)。服务器收到此请求后,可以执行以下两项操作:
    1. 检查key是否确实等于md5(time + salt)(请注意,只有客户端和服务器才知道盐,并且可以像上面的API密钥一样对其进行混淆),并且
    2. 检查time过去是否太远(例如,如果过去超过1-2分钟,则认为请求无效)。

如果您也在执行普通的HTTP请求,每个人都可以看到正在发送的参数,则第二种方法会更有用。而且,从反编译的代码中找出要困难得多。特别是如果您将密钥计算逻辑分布在多个类中。

但是,请注意,没有什么可以破解您的应用程序的。您可以根据自己的意愿进行任意程度的混淆,如果黑客真的下定决心要获取您的数据,那么他可以通过反编译您的应用程序并花费许多不眠之夜来遍历您的代码并弄清楚请求的形成方式来做到这一点。保护数据的唯一真正方法是,除了完成我上面写的所有工作之外,还要求用户提供密码。您无法从反编译代码中获得仅存在于某人(用户)头中的密码:)。


好吧,我知道我对不同的移动系统使用令牌,身份验证与服务器等的想法非常复杂。现在,使用存储在服务器端的API密钥,为Android提出的建议要简单得多。您对使用静态API密钥的安全性有何看法?(至少这是我听过第二手的一般想法)。
DJPlayer11年

有关proguard的信息对definatley有利。.definatley必须查阅文档。
DJPlayer11年

最初,我仅谈论如何在设备上安全地存储数据。我现在编辑了答案,以讨论如何将数据也安全地从服务器传输到设备。看看:)
Felix

一般而言,这看起来几乎是我正在考虑的..一定要使用一种哈希算法的md5。最终,我们要访问许多内部基于Web的应用程序,并使用相同的凭据进行身份验证。令牌的使用将非常好..这将使用户一旦登录即可访问众多区域,并允许良好的默认超时。不幸的是,开始时,我们可能不得不稍微简化一些。这可能是一个不错的开始,我们不希望用户每次平板电脑暂停时都必须输入密码。thnx。
DJPlayer11年

@Felix为什么不使用Oauth已经发明的东西呢?
GoRoS 2014年

14

(感谢Google搜索,请点击此处)

最近,我一直在对此进行大量研究,由于有了Google和Bing搜索,该页面的内容也很多。安全地在设备上存储数据的广泛接受的过程是使用诸如AES之类的强大加密算法。较难的问题是“ AES需要安全密钥。您如何使用密钥?”

Google最近宣布了针对应用程序的基于云的存储解决方案,因此,在情况允许的情况下,您可以考虑在其中存储密钥。否则,将密钥移到设备外部(例如在服务器上)似乎更好。如果您可以让用户输入PIN码,那实际上将是最好的。您可以进行密码派生以便存储密码,也可以重做派生以验证密码

如果没有“用户输入PIN码”部分,那么我就找不到很多很好的答案。但是,如果必须在应用程序中存储一个密钥,请不要对密钥进行硬编码。至少要使用安全密码生成器和/或派生功能(如PBKDF2)(基于密码的派生功能2)来生成密钥。

如果我没看错文章,Google确实说过一种方法是在应用程序首次启动后生成密钥,然后通过MODE_PRIVATE标志将密钥存储到许多文件I / O操作中,并将其用作密钥。您还可以基于该主密钥派生其他密钥,而NIST实际上会建议一些类似的东西。

无论您是否信任主密钥方法,我都会交给您。该密钥将在有根设备上公开。我也承认我仍在研究这个问题


现在有进展吗?
Mike Yang


0

如果您想确保用户只能通过查看您的应用程序看到其他数据,那么加密实际上是唯一的方法。如果设备已植根,则用户甚至也可以访问“受保护”的存储。甚至加密也不是完全安全的,因为您需要在某个时候解密数据才能显示它。您将劝说随意的浏览器,但不会劝诱坚定的黑客。


这些设备是公司所有的。因此我们可以通过移动设备管理器在一定程度上控制这些设备。在其他设备上,我们的计划是在通过siteminer之类的东西之后,使用在主动服务器上完成身份验证的令牌。不幸的是,钥匙串API只是4.0的一部分。可能使用1种方式的hasing算法来验证用户。
DJPlayer11年

0

在HTTPS上使用SSL而不是HTTP来传输数据,您需要在Web服务器上设置证书,但不确定其工作方式。

如果您真的很担心数据,请在发送数据并到达应用程序之前对其进行解密,然后再使用独特的算法对其进行加密。我想就是这样。除非您需要真正强大的功能,否则请基于TCP开发自己的协议和/或使用其他端口。

http://en.wikipedia.org/wiki/Secure_Sockets_Layer http://developer.android.com/reference/javax/net/ssl/package-summary.html http://blog.synyx.de/2010/06/ android-and-self-signed-ssl-certificates /

至于在应用程序中存储数据,您可以在存储之前对数据进行加密,或者可以使用SQLite以外的其他格式来提高安全性,因为您可以使用浏览器轻松查看sqlite数据库。

除非手机扎根,否则应该没有办法从手机中提取数据。


2
我不同意“编写自己的安全协议”的理念。您可能会不经意地引入旧的漏洞,我们会知道任何社区都不支持的安全漏洞(因为它必须是秘密的)。另外,在Android的官方文档中也明确指出这不是一个好方法:“如果您需要安全的隧道,请考虑使用HttpsURLConnection或SSLSocket,而不要编写自己的协议。” Src:developer.android.com/training/articles/security-tips.html
Thecave3 '18年

我指的是仍使用TCP在其之上开发自己的协议,并使用已知的加密算法来加密有效负载。许多具有持久连接的游戏都这样做是为了减少http / https中引入的有效负载,并使用户更难猜测所使用的加密算法。我并不是要用户在原始套接字上开发一个全新的协议。
Rejinderi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.