密码应该存储在哪里?

5

我正在编写一款Android密码管理应用程序,我想要将主密码存储在某个地方,但我不知道该放在哪里。我应该使用我选择的硬编码密码对用户提供给我的主密码进行加密,然后将其存储到数据库中吗?还是应该采取其他措施?


4
密码管理器的整个概念不就是你不需要存储主密码吗?你使用主密码作为加密密钥来存储各个密码。而主密码本身则不会被存储。 - Wolph
2个回答

5

您永远不应该存储未加密的密码。

对于您无法安全加密的密码(因为您必须在某个地方存储解密密钥),您应仅存储其不可逆哈希值。

这样,当用户提供密码时,您可以将密码与哈希进行比较。如果匹配,则可以使用给定的密码解密存储的用户:密码对。

附注:不要忘记加盐并正确执行


我建议你重新阅读他的问题。创建密码管理器时,“必须”存储原始密码;除非目标支持,否则哈希不是选项。 - Wolph
1
@WoLpH:您可以使用主密码加密密码。然而,您不必存储主密码。仅存储其哈希值即可。 - Georg Schölly
Scholly:我看到你修改了原来的答案。现在它是正确的 :) +1 - Wolph

3
不,千万不要。
如果您被允许查看GPLv2代码,请查看KeePass源代码。
主密码会被转换成密钥(基于密码的密钥导出),并且该密钥用于加密和解密各个数据片段(单独的密码)。
因此,过程类似于这样: 1. 关闭所有可以关闭的swap-to-disk。要求用户输入主密码。
  1. 使用类似PBKDF2(HMAC-SHA-256,主密码,存储的随机salt*,2000000,256)的算法将主密码转换为仅存在于内存中的主加密密钥。PBKDF2也称为RFC2898和PKCS#5。HMAC-SHA-256是哈希函数。主密码是用户输入的内容,绝不以任何形式保存!存储的随机salt是一个64位或更大的加密随机值,每当选择新的主密码时,都会生成一个新的值,并保存该值而不是保存任何形式的主密码。2000000是我们将运行HMAC的次数,它将被存储并且应该由用户选择 - 这应该尽可能多,KeePass有一个函数来对它们进行基准测试并查看需要多少时间 - 我建议将其增加到4或5秒。256是所需输出的比特数 - 在本例中,我假设您将使用CAMELLIA-256或AES-256来加密密码(只需匹配您的加密函数使用多少位密钥)。 是的,也可以使用scrypt或bcrypt。

  2. 检查主密码是否正确:如果我们进入具有现有主密码的现有数据库,请使用该仅存在于内存中的密钥解密一些固定数据,例如“默认”密码。如果值解密成您所期望的值,则输入的主密码正确;否则,主密码错误和/或数据库已损坏。如果我们正在开始一个新数据库或更改主密码,请加密该“默认”密码并存储加密值。

  3. 使用主加密密钥解密URL、用户名、注释和其他非密码数据。

  4. 仅按用户请求使用主加密密钥解密现有密码(但仅解密用户请求的确切密码),然后在他们完成操作或定时器超时后立即用随机垃圾覆盖数据。使用该主加密密钥加密新密码。

  5. 一旦用户完成操作或计时器超时,立即用随机垃圾覆盖所有变量(特别是仅存在于内存中的主加密密钥)。

请注意,您正在存储:

  • 迭代次数
  • 盐值
  • 加密的“固定”密码,仅用于验证主密码是否正确
  • 加密的用户名、URL、注释等
  • 加密的个人网站密码

您永远不会存储主密码或其哈希值。您永远不会将主密码、其哈希值或甚至生成的主加密密钥与其他任何内容进行比较。您只需获取主密码并将其转换为主加密密钥,然后使用该密钥加密或解密数据-已知数据(“固定”密码)可让您查看该密钥是否产生了预期的结果。当您知道主密码是正确的时,也会对未知数据(用户输入并关心的所有内容)进行加密或解密。


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