如何在安卓设备上安全地存储密码?

6
任务是保存输入的密码(PasswordStr)或mKey.getEncoded字节数组,并在以后自动发送到加密API(Cipher)。
    SecretKey mKey = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(new PBEKeySpec(PasswordStr.toCharArray());

很明显,这个密码也可以被加密,但这需要另一个密码,以此类推,无限循环。

也许安卓已经提供了一种存储密码的机制?

p.s. 使用远程服务器不可行。需要本地存储。


1
你的使用情况是什么?为什么需要存储密码或密钥?目前还不清楚你是否要存储密码或密钥。如果可以选择,应该保存生成的“密钥”(当然也要保存公共盐)。你不想将用户的密码泄露给其他人! - Maarten Bodewes
最好将字符串密码存储起来。 但是考虑到Java代码的漏洞,原则上并不重要。我想确保我的用户数据的安全性。 盐、迭代等在反编译后可以看到。 - Mixer
现在它甚至更加没有意义。盐不应该在代码中,盐应该是随机的,而不是“这种随机”(http://xkcd.com/221/)。盐和迭代次数可以公开。 - Maarten Bodewes
也许我在密码学科学方面的知识不是很丰富。 但是公共盐有什么意义呢? 或者说,盐的使用只是增加了破解密码的时间吗?如果是这样的话,更合理的做法是存储密码,而非秘密密钥。 - Mixer
2
盐用于确保无法创建彩虹表,并确保您无法发现两个人(或同一人在不同情况下)重复使用密码,导致相同的密码哈希。因此,它可以公开使用而没有问题。有时会使用静态/秘密盐(称为胡椒粉)进行扩展,但仍需要盐。不要存储密码;人们可能会重复使用密码,因此如果密码泄漏,您将对损害负责。 - Maarten Bodewes
3个回答

4
您可以使用Android的Keystore API
一个秘密是由手机的密码或PIN派生的主密码加密的。这被认为是一种良好的基于软件的加密解决方案。请注意,用户必须在手机上设置密码/PIN才能使用此功能。 Nelenkov提供了很好的概述: Android的凭证存储实现为本地Linux服务(守护程序),并在其顶部添加了几个额外的层,使其可用于框架。让我们快速回顾一下我们对密钥库守护程序的了解(更详细的描述在此处):
  • 它是一个本地守护程序,在启动时启动
  • 它提供本地控制套接字以允许应用程序和系统服务进行交互
  • 它使用AES 128位主密钥加密密钥
  • 加密的键存储在/data/misc/keystore中,每个键一个文件
  • 主密钥派生自设备解锁密码或PIN
  • 根据调用者UID授权管理命令执行和键访问
有关更多详细信息,请参见Android文档

3
我投下反对票,因为我认为这不会解决问题。问题是安全地存储密码,而不是秘密密钥。通常使用平台密钥库确实是一个好主意,但需要补充一个示例来说明如何使用它来存储密码。 - Maarten Bodewes
在你的例子中,你提到了一个秘密密钥,所以我认为这对你来说是一个可行的解决方案。当然,你可以使用这个密钥来加密密码(或其他任何东西),这将使你摆脱密码循环(“...但这将需要另一个密码,以此类推无穷无尽。”)。 - jHilscher
好吧,我以为这是要求的,但现在我有些困惑了。撤销了踩,通过评论向发布者请求澄清。 - Maarten Bodewes
1
现在改为点赞。您应该存储派生密钥或秘密,而不是密码(如果需要存储任何内容)。但这也意味着您必须在某个地方存储盐。 - Maarten Bodewes
主密钥是从设备解锁密码或PIN派生的。如果用户没有在系统上设置PIN怎么办?KeyStore将无法工作吗?这样不太好。 - Mixer

2
检查Android开发者指南上的处理凭据部分。我会在这里引用它。
在可能的情况下,用户名和密码不应存储在设备上。相反,使用用户提供的用户名和密码进行初始身份验证,然后使用短期、服务特定的授权令牌
将对多个应用程序可访问的服务使用AccountManager进行访问。如果可能,请使用AccountManager类调用基于云的服务,并且不要将密码存储在设备上。
在使用AccountManager检索账户之后,在传递任何凭据之前,使用CREATOR,以便不会错误地将凭据传递给错误的应用程序。
如果凭据仅由您创建的应用程序使用,则可以使用 checkSignature() 验证访问 AccountManager 的应用程序。或者,如果只有一个应用程序将使用凭据,则可以使用 KeyStore 进行存储。

这一切都是正确的,但有时候存储密码是有合法用例的(例如为第三方服务),而这个答案并没有涉及到这些情况。 - Maarten Bodewes

0

你可以在安卓中使用SQLCipher。它是SQLite的扩展,可为数据库文件提供透明的256位AES加密。


没有更多的安全细节,这个答案并不像它本来可以那样强大。AES-256实际上对提供的安全级别一无所知。 - Maarten Bodewes

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