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

时间:2022-05-02 18:17:34

Yes this is a pretty general question but I'm trying to get a feel for the best way to handle an app that touches base w/ a webserver that distributes sensitive data to the app. Any links, general information advice etc.. would be appreciated.

是的,这是一个非常普遍的问题,但是我正在尝试找到处理应用程序的最佳方式,这个应用程序涉及到基本的w/一个向应用程序分发敏感数据的web服务器。我们将不胜感激。

Since the app would store persistant data retreived from the database for a certain amount of time.. everything becomes somewhat touchy.

因为这个应用会在一定的时间内从数据库中存储可保存的数据。一切都变得有些敏感。

5 个解决方案

#1


90  

Storing sensitive data on the device

That depends very much on your audience. Normally, the Android OS prohibits apps from accessing each other's files (i.e. databases, preference files, regular files stored in the app's private directory) through proven Linux file permissions. However, on rooted devices an application can obtain root access and read everything. A few things to think about:

这在很大程度上取决于你的听众。通常,Android操作系统禁止应用程序通过经过验证的Linux文件权限访问彼此的文件(例如数据库、首选项文件、存储在应用程序私有目录中的常规文件)。但是,在有根设备上,应用程序可以获得根访问并读取所有内容。有几点需要考虑:

  1. If you know your users won't have root (e.g. if you are not distributing the app through Android Market, but only in your company, or something like that), you can simply rely on Android's filesystem-based security.
  2. 如果您知道您的用户没有根(例如,如果您没有通过Android Market分发应用程序,而是在您的公司内,或者类似的东西),您可以简单地依赖Android的基于文件系统的安全性。
  3. If a user does get root access, he will be very careful what application he gives that priviledge to
  4. 如果用户确实获得了root访问权,那么他会非常小心地将这个特权授予哪些应用程序
  5. If an app does get root access, it can wreak a lot of havoc. The information in your app could be the least of the user's worries.
  6. 如果一个应用程序获得了根访问权限,它就会造成很大的破坏。应用程序中的信息可能是用户最不担心的。
  7. Rooting leads to zero warranty. Including in apps. You can't be held responsible for leaking information on a rooted phone.
  8. 生根导致零保证。包括在应用程序。你不能为在有根的手机上泄露信息负责。

To conclude, if your information is not super-duper sensitive (e.g. credit card information), I'd suggest just sticking with the default security provided by Android (i.e. save everything in plain text, knowing other apps can't access it).

综上所述,如果你的信息不是超敏感的(比如信用卡信息),我建议你只使用Android提供的默认安全(比如,把所有的东西都保存在纯文本中,因为其他应用程序无法访问它)。

Otherwise, encryption is the way to go. It's not 100% secure (a hacker could de-compile your app and figure out how to decrypt the data), but it's a major pain to crack and will stop most hackers. Especially if you obfuscate your code with something like ProGuard.

否则,加密就是解决之道。它并不是100%的安全(黑客可以对你的应用程序进行反编译并找出如何解密数据),但破解它是一件非常痛苦的事情,而且会阻止大多数黑客。特别是如果你用ProGuard之类的东西来混淆你的代码。


Transferring sensitive data from the server to the device

You have a few options here. First of all, always use HTTPS. After enabling HTTPS, here are two extra security measures I would propose:

你有几个选择。首先,始终使用HTTPS。在启用HTTPS之后,我将提出两个额外的安全措施:

  1. Use an API key system. Include this API key in all your requests and check it on the server side before sending any response back. Remember that since you're using HTTPS, an attacker would not be able to just use a network sniffer to find out your API key. However, this is pretty easy to figure out if someone decompiles your app, which is why you can obfuscate it even further (besides using ProGuard). For example, you can keep the API key broken up into pieces all around your code (for example as static members in two or three classes). Then, when you send a request, you just concatenate all those pieces. You can even apply some other sort of transformation (e.g. bit shifting) to make it even harder to figure out from the decompiled code.
  2. 使用API密钥系统。在所有请求中包含此API键,并在发送任何响应之前在服务器端检查它。请记住,由于您使用的是HTTPS,攻击者将不能仅使用网络嗅探器来查找您的API密钥。然而,如果有人对你的应用程序进行反编译,这很容易算出来,这就是为什么你可以进一步混淆它(除了使用ProGuard)。例如,您可以将API密钥分散到代码中(例如,在两个或三个类中作为静态成员)。然后,当您发送请求时,您只需将所有这些片段连接起来。您甚至可以应用一些其他类型的转换(例如,位移位),使从反编译代码中找出问题变得更加困难。
  3. You can generate a key every time you send a request. That key would be generated by using a bit of logic that only you know, so that you can implement it client- and server-side as well. For example, a request could include the following parameters:
    time=1321802432&key=[generated-key]
    where generated-key is generated from the time parameter. For example: md5(time + salt). When the server receives this request, it can do two things:
    1. Check that key is indeed equal to md5(time + salt) (note that only the client and the server know the salt and it can be obfuscated similarly to the API key above), and
    2. 检查该键是否确实等于md5(time + salt)(注意,只有客户端和服务器知道这个salt,它可以像上面的API键一样混淆),以及
    3. Check that time is not too far back in the past (e.g. if it's more than 1-2 minutes in the past, consider the request invalid).
    4. 检查时间不要太久远(例如:如果超过1-2分钟,认为请求无效)。
  4. 您可以在每次发送请求时生成密钥。这个键将通过使用一些只有您知道的逻辑来生成,这样您就可以实现it客户端和服务器端。例如,一个请求可以包含以下参数:time=1321802432&key=[generated-key],其中从time参数生成generatkey。例如:md5(时间+盐)。当服务器接收到请求时,它可以做两件事:检查关键事实上等于md5(时间+盐)(注意,只有客户端和服务器知道盐和它可以混淆类似于上面的API键),并检查时间回到过去不远(例如,如果它是超过1 - 2分钟过去,考虑到请求无效)。

The second method is more useful if you are also doing plain HTTP requests, where everyone can see the parameters being sent. Also, it's much harder to figure out from decompiled code. Especially if you spread the key calculation logic across multiple classes.

如果您还在进行普通的HTTP请求,那么第二个方法会更有用,因为每个人都可以看到发送的参数。而且,要从反编译代码中找出答案要困难得多。特别是如果将关键的计算逻辑分散到多个类中。

However, note that nothing makes it impossible to crack your app. You can obfuscate as much as you want, if a hacker is really determined to get to your data, he will be able to so by decompiling your application and spending many sleepless nights passing through your code and figuring out how the requests are formed. The only real way of securing your data is by asking your user for a password, besides doing all the work I wrote about above. You can't get a password that only exists in someone's (the user) head from decompiled code :).

但是,要注意让人无法破解你的应用,你可以使尽可能多的你想要的,如果一个黑客是真的决定去你的数据,他能够通过反编译应用程序和支出通过代码并找出许多不眠之夜的请求是如何形成的。确保数据安全的唯一方法是请求用户输入密码,而不需要完成我在上面所写的所有工作。您无法从反编译代码中获得仅存在于某人(用户)头部的密码:)。

#2


10  

(Came here thanks to a Google search)

(多亏了谷歌搜索)

I've been researching this a lot lately and this page has come up a lot thanks to Google and Bing searches. The widely-accepted procedure for storing data on the device securely has been to use a strong encryption algorithm like AES. The harder question is "AES requires a secure key. What do you do with the key?"

我最近一直在研究这个问题,由于谷歌和Bing的搜索,这个页面出现了很多。被广泛接受的存储设备数据的程序是使用像AES这样的强加密算法。更难的问题是“AES需要一个安全的密钥”。你拿钥匙干什么?”

Google recently announced a cloud-based storage solution for apps, so you could consider storing the key there if the situation allows. Otherwise, its seems that getting the key outside the device, like on a server, is better. If you can make the user punch in a PIN, that would actually work the best. You can do password derivation in order to store the password, and you can redo the derivation to verify the password

谷歌最近宣布了一种基于云的应用存储解决方案,如果情况允许,您可以考虑将密钥存储在那里。否则,像在服务器上一样,从设备外部获取密钥似乎更好。如果你能让用户在大头针上打孔,那将是最好的。您可以进行密码派生以存储密码,还可以重新执行派生以验证密码

Without the "user punching in a PIN" part, I haven't found a lot of good answers to that question. However, DO NOT HARD-CODE THE KEY IF YOU MUST STORE ONE WITH THE APP. At the minimum, generate a key using a secure password generator and/or a derivation function like PBKDF2 (Password-based derivation function 2).

如果没有“用户在大头针上打孔”的部分,我就找不到很多关于这个问题的好答案。但是,如果你必须在应用程序中存储一个密钥,那么就不要硬编码密钥,至少要使用安全的密码生成器和/或派生函数,比如PBKDF2(基于密码的派生函数2)来生成密钥。

If I read the posts correctly, Google did say that one approach is to generate a key once the app starts the first time, store the key via the MODE_PRIVATE flag to a lot of file I/O operations, and use that as the key. You can also derive other keys based on that master key, and the NIST actually suggests something along that lines.

如果我正确地阅读了文章,谷歌确实说过,一种方法是在应用程序第一次启动时生成一个密钥,通过MODE_PRIVATE标志将密钥存储到许多文件I/O操作中,并将其作为密钥。您还可以根据主键派生其他键,NIST实际上建议沿着这条线。

Whether or not to trust the master-key method, I'll leave to you. This key would get exposed on a rooted device. I'll also admit that I'm still researching the issue

无论是否信任主键方法,我将留给您。这个密钥将在一个根设备上公开。我也承认我还在研究这个问题

#3


1  

Use SSL on HTTPS to transfer data instead of HTTP you need to setup the certificates on the webserver not very sure how it works..

使用HTTPS上的SSL来传输数据,而不是HTTP。您需要在webserver上设置证书,但不知道它是如何工作的。

If you are really concerned about the data then further encrypt it with a unique algorithm before sending and decrypt it when it reaches the app. I guess that's all about it.. Unless you need something really strong then develop your own protocol based on TCP and/or use another port.. maybe that'll help

如果你真的关心这些数据,那就用唯一的算法对其进行加密,然后在数据到达应用程序时再发送和解密。除非你需要非常强大的东西,然后根据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/

http://en.wikipedia.org/wiki/Secure_Sockets_Layer http://developer.android.com/reference/javax/net/ssl/package-summary.html http://developer.android.com/reference/javax/net/ssl/package-summary.html

As for storing data in the app what you can encrypt the data before storing or you can use another format other than SQLite for better security as you can view sqlite databases using the browser pretty easily.

至于在应用程序中存储数据,你可以在存储前对数据进行加密,或者你可以使用SQLite以外的另一种格式以获得更好的安全性,因为你可以很容易地使用浏览器查看SQLite数据库。

Unless the phone is rooted there should not be a way to extract the data from it.

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

#4


1  

Every application on Android runs in a secure sandbox environment, so other processes on the system cannot access your code or private data without proper handshake. But still there are many vulnerabilities are possible by poor design of the apps. This link from Android developers site advice you some of the good tips for security - https://developer.android.com/training/articles/security-tips.html

Android上的每个应用程序都在一个安全的沙箱环境中运行,因此系统上的其他进程如果没有适当的握手,就不能访问您的代码或私有数据。但由于这些应用程序设计不佳,仍然存在许多漏洞。这个链接来自Android开发者网站,给你提供了一些安全方面的好建议。

#5


0  

If you want to pretty much ensure the user cannot see the data other than by looking at your app then encryption is really the only way. Even the "protected" storage is accessible to the user if a device is rooted. Even encryption is not totally secure as you need to decrypt the data at some point in order to display it. You will dissuade the casual browser but not the determined hacker.

如果你想要确保用户只能通过查看应用程序才能看到数据,那么加密是唯一的方法。即使是“受保护”的存储,如果一个设备是根的,用户也可以访问。即使加密也不是完全安全的,因为为了显示数据,您需要在某些时候对数据进行解密。你会劝阻普通的浏览器,而不是坚定的黑客。

#1


90  

Storing sensitive data on the device

That depends very much on your audience. Normally, the Android OS prohibits apps from accessing each other's files (i.e. databases, preference files, regular files stored in the app's private directory) through proven Linux file permissions. However, on rooted devices an application can obtain root access and read everything. A few things to think about:

这在很大程度上取决于你的听众。通常,Android操作系统禁止应用程序通过经过验证的Linux文件权限访问彼此的文件(例如数据库、首选项文件、存储在应用程序私有目录中的常规文件)。但是,在有根设备上,应用程序可以获得根访问并读取所有内容。有几点需要考虑:

  1. If you know your users won't have root (e.g. if you are not distributing the app through Android Market, but only in your company, or something like that), you can simply rely on Android's filesystem-based security.
  2. 如果您知道您的用户没有根(例如,如果您没有通过Android Market分发应用程序,而是在您的公司内,或者类似的东西),您可以简单地依赖Android的基于文件系统的安全性。
  3. If a user does get root access, he will be very careful what application he gives that priviledge to
  4. 如果用户确实获得了root访问权,那么他会非常小心地将这个特权授予哪些应用程序
  5. If an app does get root access, it can wreak a lot of havoc. The information in your app could be the least of the user's worries.
  6. 如果一个应用程序获得了根访问权限,它就会造成很大的破坏。应用程序中的信息可能是用户最不担心的。
  7. Rooting leads to zero warranty. Including in apps. You can't be held responsible for leaking information on a rooted phone.
  8. 生根导致零保证。包括在应用程序。你不能为在有根的手机上泄露信息负责。

To conclude, if your information is not super-duper sensitive (e.g. credit card information), I'd suggest just sticking with the default security provided by Android (i.e. save everything in plain text, knowing other apps can't access it).

综上所述,如果你的信息不是超敏感的(比如信用卡信息),我建议你只使用Android提供的默认安全(比如,把所有的东西都保存在纯文本中,因为其他应用程序无法访问它)。

Otherwise, encryption is the way to go. It's not 100% secure (a hacker could de-compile your app and figure out how to decrypt the data), but it's a major pain to crack and will stop most hackers. Especially if you obfuscate your code with something like ProGuard.

否则,加密就是解决之道。它并不是100%的安全(黑客可以对你的应用程序进行反编译并找出如何解密数据),但破解它是一件非常痛苦的事情,而且会阻止大多数黑客。特别是如果你用ProGuard之类的东西来混淆你的代码。


Transferring sensitive data from the server to the device

You have a few options here. First of all, always use HTTPS. After enabling HTTPS, here are two extra security measures I would propose:

你有几个选择。首先,始终使用HTTPS。在启用HTTPS之后,我将提出两个额外的安全措施:

  1. Use an API key system. Include this API key in all your requests and check it on the server side before sending any response back. Remember that since you're using HTTPS, an attacker would not be able to just use a network sniffer to find out your API key. However, this is pretty easy to figure out if someone decompiles your app, which is why you can obfuscate it even further (besides using ProGuard). For example, you can keep the API key broken up into pieces all around your code (for example as static members in two or three classes). Then, when you send a request, you just concatenate all those pieces. You can even apply some other sort of transformation (e.g. bit shifting) to make it even harder to figure out from the decompiled code.
  2. 使用API密钥系统。在所有请求中包含此API键,并在发送任何响应之前在服务器端检查它。请记住,由于您使用的是HTTPS,攻击者将不能仅使用网络嗅探器来查找您的API密钥。然而,如果有人对你的应用程序进行反编译,这很容易算出来,这就是为什么你可以进一步混淆它(除了使用ProGuard)。例如,您可以将API密钥分散到代码中(例如,在两个或三个类中作为静态成员)。然后,当您发送请求时,您只需将所有这些片段连接起来。您甚至可以应用一些其他类型的转换(例如,位移位),使从反编译代码中找出问题变得更加困难。
  3. You can generate a key every time you send a request. That key would be generated by using a bit of logic that only you know, so that you can implement it client- and server-side as well. For example, a request could include the following parameters:
    time=1321802432&key=[generated-key]
    where generated-key is generated from the time parameter. For example: md5(time + salt). When the server receives this request, it can do two things:
    1. Check that key is indeed equal to md5(time + salt) (note that only the client and the server know the salt and it can be obfuscated similarly to the API key above), and
    2. 检查该键是否确实等于md5(time + salt)(注意,只有客户端和服务器知道这个salt,它可以像上面的API键一样混淆),以及
    3. Check that time is not too far back in the past (e.g. if it's more than 1-2 minutes in the past, consider the request invalid).
    4. 检查时间不要太久远(例如:如果超过1-2分钟,认为请求无效)。
  4. 您可以在每次发送请求时生成密钥。这个键将通过使用一些只有您知道的逻辑来生成,这样您就可以实现it客户端和服务器端。例如,一个请求可以包含以下参数:time=1321802432&key=[generated-key],其中从time参数生成generatkey。例如:md5(时间+盐)。当服务器接收到请求时,它可以做两件事:检查关键事实上等于md5(时间+盐)(注意,只有客户端和服务器知道盐和它可以混淆类似于上面的API键),并检查时间回到过去不远(例如,如果它是超过1 - 2分钟过去,考虑到请求无效)。

The second method is more useful if you are also doing plain HTTP requests, where everyone can see the parameters being sent. Also, it's much harder to figure out from decompiled code. Especially if you spread the key calculation logic across multiple classes.

如果您还在进行普通的HTTP请求,那么第二个方法会更有用,因为每个人都可以看到发送的参数。而且,要从反编译代码中找出答案要困难得多。特别是如果将关键的计算逻辑分散到多个类中。

However, note that nothing makes it impossible to crack your app. You can obfuscate as much as you want, if a hacker is really determined to get to your data, he will be able to so by decompiling your application and spending many sleepless nights passing through your code and figuring out how the requests are formed. The only real way of securing your data is by asking your user for a password, besides doing all the work I wrote about above. You can't get a password that only exists in someone's (the user) head from decompiled code :).

但是,要注意让人无法破解你的应用,你可以使尽可能多的你想要的,如果一个黑客是真的决定去你的数据,他能够通过反编译应用程序和支出通过代码并找出许多不眠之夜的请求是如何形成的。确保数据安全的唯一方法是请求用户输入密码,而不需要完成我在上面所写的所有工作。您无法从反编译代码中获得仅存在于某人(用户)头部的密码:)。

#2


10  

(Came here thanks to a Google search)

(多亏了谷歌搜索)

I've been researching this a lot lately and this page has come up a lot thanks to Google and Bing searches. The widely-accepted procedure for storing data on the device securely has been to use a strong encryption algorithm like AES. The harder question is "AES requires a secure key. What do you do with the key?"

我最近一直在研究这个问题,由于谷歌和Bing的搜索,这个页面出现了很多。被广泛接受的存储设备数据的程序是使用像AES这样的强加密算法。更难的问题是“AES需要一个安全的密钥”。你拿钥匙干什么?”

Google recently announced a cloud-based storage solution for apps, so you could consider storing the key there if the situation allows. Otherwise, its seems that getting the key outside the device, like on a server, is better. If you can make the user punch in a PIN, that would actually work the best. You can do password derivation in order to store the password, and you can redo the derivation to verify the password

谷歌最近宣布了一种基于云的应用存储解决方案,如果情况允许,您可以考虑将密钥存储在那里。否则,像在服务器上一样,从设备外部获取密钥似乎更好。如果你能让用户在大头针上打孔,那将是最好的。您可以进行密码派生以存储密码,还可以重新执行派生以验证密码

Without the "user punching in a PIN" part, I haven't found a lot of good answers to that question. However, DO NOT HARD-CODE THE KEY IF YOU MUST STORE ONE WITH THE APP. At the minimum, generate a key using a secure password generator and/or a derivation function like PBKDF2 (Password-based derivation function 2).

如果没有“用户在大头针上打孔”的部分,我就找不到很多关于这个问题的好答案。但是,如果你必须在应用程序中存储一个密钥,那么就不要硬编码密钥,至少要使用安全的密码生成器和/或派生函数,比如PBKDF2(基于密码的派生函数2)来生成密钥。

If I read the posts correctly, Google did say that one approach is to generate a key once the app starts the first time, store the key via the MODE_PRIVATE flag to a lot of file I/O operations, and use that as the key. You can also derive other keys based on that master key, and the NIST actually suggests something along that lines.

如果我正确地阅读了文章,谷歌确实说过,一种方法是在应用程序第一次启动时生成一个密钥,通过MODE_PRIVATE标志将密钥存储到许多文件I/O操作中,并将其作为密钥。您还可以根据主键派生其他键,NIST实际上建议沿着这条线。

Whether or not to trust the master-key method, I'll leave to you. This key would get exposed on a rooted device. I'll also admit that I'm still researching the issue

无论是否信任主键方法,我将留给您。这个密钥将在一个根设备上公开。我也承认我还在研究这个问题

#3


1  

Use SSL on HTTPS to transfer data instead of HTTP you need to setup the certificates on the webserver not very sure how it works..

使用HTTPS上的SSL来传输数据,而不是HTTP。您需要在webserver上设置证书,但不知道它是如何工作的。

If you are really concerned about the data then further encrypt it with a unique algorithm before sending and decrypt it when it reaches the app. I guess that's all about it.. Unless you need something really strong then develop your own protocol based on TCP and/or use another port.. maybe that'll help

如果你真的关心这些数据,那就用唯一的算法对其进行加密,然后在数据到达应用程序时再发送和解密。除非你需要非常强大的东西,然后根据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/

http://en.wikipedia.org/wiki/Secure_Sockets_Layer http://developer.android.com/reference/javax/net/ssl/package-summary.html http://developer.android.com/reference/javax/net/ssl/package-summary.html

As for storing data in the app what you can encrypt the data before storing or you can use another format other than SQLite for better security as you can view sqlite databases using the browser pretty easily.

至于在应用程序中存储数据,你可以在存储前对数据进行加密,或者你可以使用SQLite以外的另一种格式以获得更好的安全性,因为你可以很容易地使用浏览器查看SQLite数据库。

Unless the phone is rooted there should not be a way to extract the data from it.

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

#4


1  

Every application on Android runs in a secure sandbox environment, so other processes on the system cannot access your code or private data without proper handshake. But still there are many vulnerabilities are possible by poor design of the apps. This link from Android developers site advice you some of the good tips for security - https://developer.android.com/training/articles/security-tips.html

Android上的每个应用程序都在一个安全的沙箱环境中运行,因此系统上的其他进程如果没有适当的握手,就不能访问您的代码或私有数据。但由于这些应用程序设计不佳,仍然存在许多漏洞。这个链接来自Android开发者网站,给你提供了一些安全方面的好建议。

#5


0  

If you want to pretty much ensure the user cannot see the data other than by looking at your app then encryption is really the only way. Even the "protected" storage is accessible to the user if a device is rooted. Even encryption is not totally secure as you need to decrypt the data at some point in order to display it. You will dissuade the casual browser but not the determined hacker.

如果你想要确保用户只能通过查看应用程序才能看到数据,那么加密是唯一的方法。即使是“受保护”的存储,如果一个设备是根的,用户也可以访问。即使加密也不是完全安全的,因为为了显示数据,您需要在某些时候对数据进行解密。你会劝阻普通的浏览器,而不是坚定的黑客。