我正在创建一个用户可以在设备上存储数据的应用程序。我在考虑使用数据库存储。但我一直在读某处可以操纵本地存储在设备上的数据。那么什么是避免对数据进行这种“攻击”的最佳方法呢?我一直在考虑加密数据库中的每个字段,但我又要在设备上存储一个加密密钥(?),我想这可以找到?那么有没有人有任何其他想法/改变我的想法?
感谢您的帮助!
答案 0 :(得分:4)
我正在寻找一种让它成为一项重大挑战的方法
接受挑战:)
您应该做的第一件事是将数据存储在您的应用程序目录中,因为它对于常规设备上的用户/其他应用程序是不可读的。可以从Context
获取应用数据的链接,例如Context.html#getDir()
。您从Environment
获得的目录是公开的。
这会阻止普通用户获取数据。但是很多人已经植根设备并且可以毫无问题地访问数据,所以这仍然是非常不安全的。
要让它变得更加困难,你需要加密。任何强大的加密都不会像WEP那样从根本上打破。使用加密会强制用户找到密钥(和加密方法),因为加密数据无法在合理的时间内解密。
这会导致在应用程序可用的某个地方使用密钥而不是用户的问题。这是你需要创造性的部分,因为没有安全的方法可以做到这一点。
最简单的方法是将密钥以明文形式放入应用代码中。像private static final String SECRET = "42"
一样。通过简单地加密文件,您已经可以阻止大多数用户进一步挖掘,因为此时您需要一些编程技能来读取数据。
如果用户具备这些技能,他可能会开始查看您应用的代码(使用例如dex2jar + jd-gui)。如果您想知道对应用程序进行逆向工程有多难,那么您应该这样做。
如果使用proguard来混淆代码,那么理解代码/找到加密方法+密码会变得更难,因为app内部的类,方法和变量名称将缩短为A.B.c(d)
代码。但是,由于您需要重命名设备上的方法,因此无法重命名对Android API的方法调用。此类字符串常量(如"42"
)也不会更改。
使其变得更难的下一步是通过代码动态生成的内容替换该常量。例如,下面的基本示例通过将数字除以2来构建密码。使用此方法的优点是密码不再以明文形式存储,您需要了解/反向设计将数据转换为密码的方法。
private static final byte[] password = {8, 4};
private String getPassword(byte[] data) {
StringBuilder sb = new StringBuilder();
for (byte b : data) {
sb.append(String.valueof(b / 2));
}
return sb.toString();
}
// returns "42" if I did not make a mistake
下一个易受攻击的点是,可以轻松找到对设备加密API的调用(因为它们无法重命名),这使得查找加密位置变得更加容易。如果您不想编写自己的加密方法,我强烈建议您不要这样做,因为此处的轻微错误可能会破坏数据或破坏完整的加密。
如果您使用反射(例如通过提供String
中提供的方法/类的名称来调用方法),则可以加强该问题。 String
也可以像上面的例子一样使用密码进行混淆。
如果你做了所有这些,并且不使用不像这个那么简单的方法,你可以使它变得非常困难。例如,dexguard可以为您做到这一点,但它不是免费的,并且存在许多应用程序使用相同方法的问题,并且会有更多人试图打破这种方法而不是您的自定义方法。
找到一种很好的方法来隐藏应用中用于生成密钥的信息和隐藏密钥生成的方法。加密/解密最好由你自己解决,所以方法本身不是公共知识。
您可以结合使用许多技术来隐藏信息,例如将其中的部分移动到本机代码中,这样像我这样的Java人员很难或者使用网络连接让您的服务器做一些工作。
但最终全部Security through obscurity并且所有额外的安全措施都不会使用户受益,但需要额外的处理时间和时间。额外的应用程序大小。
答案 1 :(得分:2)
那么避免对数据进行“攻击”的最佳方法是什么?
请勿将其放在设备上。
我想针对应用的用户确保数据安全。
然后不要把它放在设备上。它是用户的设备和用户的带宽,因此它是用户的数据。
但是如果用户发现他/她会尝试这样做,我正在寻找一种方法来使它成为一个巨大的挑战。
只需在内部存储上使用数据库或其他内容即可阻止99%的Android设备用户访问您的数据。没有什么可以阻止剩下的1%。