2011-04-10 138 views
5

我正在写一个android密码管理器应用程序,我想存储主密码的某处,但我不知道在哪里。我是否应该使用我选择的硬编码密码对用户给予的主密码进行加密,然后将其存储到数据库中?还是我应该做点别的?哪里可以存储密码?

+4

密码管理器的整个想法不是存储主密码吗?您将个人密码与主密码一起存储为加密密钥。主密码永远不会被存储。 – Wolph 2011-04-10 13:43:53

回答

5

你不应该存储未加密的密码。

对于密码,您无法安全地进行加密(因为您必须将解密密钥存储在某个地方),您应该只存储它的不可逆散列。

用这种方法,您可以在用户提供密码时将密码与散列进行比较。如果匹配,则可以使用给定的密码对存储的用户:密码对进行解密。

PS:不要忘记盐散列和please do it properly

+0

我会建议你重新阅读他的问题。创建密码管理器时,您需要存储原始密码;除非目标支持,否则散列不是一个选项。 – Wolph 2011-04-10 13:45:20

+1

@WoLpH:您可以使用主密码加密密码。但是,主密码不必存储。只需存储它的散列就足够了。 – 2011-04-10 13:46:52

+0

Scholly:我看到你修改了原来的答案。现在是正确的:) +1 – Wolph 2011-04-10 13:48:46

3

不,不,一千次没有。

如果您可以查看GPLv2代码,请查看KeePass源代码。

主密码变为密钥(基于密码的密钥派生),并且该密钥用于加密和解密单个数据片段(单个密码)。

因此,该过程与此类似: 1.关闭任何类型的交换到磁盘,您可以关闭。询问用户主密码。

  1. 转动主密码到内存中的仅主加密密钥,通过使用类似PBKDF2(HMAC-SHA-256,主密码,存储的随机盐*,2000000,256) - PBKDF2也称为RFC2898和PKCS#5。 HMAC-SHA-256是哈希函数。主密码是用户输入的任何内容 - 这绝不会以任何形式保存!存储的随机盐是一个64位或更大的加密随机值,只要选择一个新的主密码,就会生成一个随机值,并且保存而不是保存任何形式的主密码。 2000000是我们要运行HMAC的次数,它被存储并且应该是用户可选择的 - 这应该等于你可以忍受的等待的次数(KeePass有一个功能来对它们进行基准测试,看看有多少次需要1秒 - 我建议增加到4或5秒)。 256是所需输出的位数 - 在这种情况下,我假设您将使用CAMELLIA-256或AES-256来加密您的密码(只需匹配您的加密功能对密钥使用的位数) 。 是的,可以使用scrypt或bcrypt。

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

  3. 使用主加密密钥来解密URL的用户名,备注和其他非密码数据。

  4. 使用主加密密钥仅根据用户的请求(但仅限用户请求的确切密码)对现有密码进行解密,然后一旦完成或定时器运行就用随机垃圾覆盖数据出。使用所述主加密密钥加密新密码。

  5. 一旦用户完成或定时器用完,用随机垃圾覆盖所有变量(尤其是内存中唯一的主加密密钥)。

注意你存储:

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

你永远不会存储主密码或它的散列。您永远无法比较主密码,哈希值,甚至是生成的主加密密钥。您只需掌握主密码并将其转换为主密钥,然后使用该密钥对数据进行加密或解密 - 已知数据(“固定”密码)可让您查看该密钥是否提供了预期结果。当您知道主密码正确时,未知数据(用户输入和关注的所有内容)也会被加密或解密。