如何在Android中存储用于SQLCipher的密钥

10

我正在使用SQLCipher for Android。根据http://sqlcipher.net/sqlcipher-for-android/中提到的,我已经完成了所有必要的加载库所需的操作。

我注意到在下面的代码中设置密码,即密钥:

    SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databaseFile, "test123", null);

那么你的密码如何免受黑客攻击?因为它可以从一个Java文件中访问。

有没有正确的方法可以存储密码?

谢谢,Nibs


2
你可以“明目张胆地隐藏它”:如果使用一个与颜色字符串无法区分的密码会怎样呢?比如:“#fad005”... 或者可以类似于id,即:“0x7f070005”... 只是一个想法。 - Phantômaxx
@ArtooDetoo:你能否详细解释一下?我还不是很清楚。谢谢。 - user2234
你可以使用一个密码字符串来轻松地迷惑黑客。他看到代表颜色的字符串,已经习以为常了。但他不知道其中一个“颜色”是你的密码。或者你可以将它隐藏在strings.xml中,就像它是一个普通的字符串一样,比如 <string name="app_ver">2.00.48 r 15</string> - 只是另一个想法。 - Phantômaxx
1
@ArtooDetoo:感谢ArtooDetoo的帮助。我会尝试一下 :) - user2234
1
看,这些只是简单的想法... 例如,你可以将一个字符串隐藏在一些自定义颜色的ARGB组件中... 或者甚至是在png图像中(这种技术被称为“隐写术”)。 - Phantômaxx
3个回答

4
我建议以下方法:
  • 首次创建数据库时,您需要创建一个随机密码。
  • 将此密码存储在Keystore中。
  • 每次打开应用程序时,从keystore读取密码并将其用于连接到数据库。
那么Keystore访问如何工作?请参阅博客文章1博客文章2以及相应的github存储库。该解决方案适用于Android版本2.1至4.3。

重要注意事项:

  1. 该解决方案仅适用于私有API访问,因此可能会在将来失效。
  2. 存储密钥需要屏幕锁密码,并且如果用户删除其锁屏密码,则所有密钥都将被清除。

4

那么你的密码如何安全地免受黑客攻击?

其实是不安全的。硬编码密码只是为了简单演示。

有没有正确的方法可以存储密码?

用户应通过您的用户界面提供用户数据库的密码。然后,用户将密码存储在自己的头脑中,或者您可以将用户头脑中的内容与其他内容结合起来,以进行轻量级的双因素身份验证(例如,配对蓝牙可穿戴设备的MAC地址)。


我不想从UI中获取密码输入。我想存储一个用于加密的密钥。 - user2234
2
@Nibs:既然任何想要的人都可以获得存储的密钥,那加密有什么意义呢?如果他们能够获取数据库,就能够获取密钥。 - CommonsWare
我在链接http://sqlcipher.net/design/上读到了这篇文章。当使用口令初始化SQLCipher时,它会使用PBKDF2(OpenSSL的PKCS5_PBKDF2_HMAC_SHA1)来派生密钥数据。每个数据库都会在文件的前16个字节中初始化一个唯一的随机盐。该盐用于密钥派生,并确保即使使用相同的密码创建两个数据库,它们也不会具有相同的加密密钥。默认配置使用64000次迭代进行密钥派生(可以使用“PRAGMA kdf_iter”在运行时更改)。所以我想在.java文件中保存密码应该是可以的。 - user2234
4
将密码保存在Java文件中意味着任何人都可以获取密码。你所描述的是为了防止暴力破解攻击,当攻击者不知道密码时。 - CommonsWare

1
被忽视的事实是 SQLCipher 给出的演示纯粹只是为了演示。开发者需要自己想象克服明显的问题。稍微不那么明显的是,你不应该将密钥存储在私有局部变量中,因为对类文件进行字符串搜索可能会揭示你的密钥,从而降低成功暴力攻击所需的字典大小。在十六进制编辑器中打开你的 classes.dex 并试一下。
你应该关注的不是 .java 文件,因为只有开发者才能进入其中。关键是 .class 文件。下一个层次的努力是一定程度的混淆,但这真的只是限制了那些没有耐心的人。
看一下这个讨论 https://groups.google.com/forum/#!topic/sqlcipher/OkE0rUwXEb8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接