我正在编写一款Android密码管理应用程序,我想要将主密码存储在某个地方,但我不知道该放在哪里。我应该使用我选择的硬编码密码对用户提供给我的主密码进行加密,然后将其存储到数据库中吗?还是应该采取其他措施?
您永远不应该存储未加密的密码。
对于您无法安全加密的密码(因为您必须在某个地方存储解密密钥),您应仅存储其不可逆哈希值。
这样,当用户提供密码时,您可以将密码与哈希进行比较。如果匹配,则可以使用给定的密码解密存储的用户:密码对。
附注:不要忘记加盐并正确执行。
使用类似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。
检查主密码是否正确:如果我们进入具有现有主密码的现有数据库,请使用该仅存在于内存中的密钥解密一些固定数据,例如“默认”密码。如果值解密成您所期望的值,则输入的主密码正确;否则,主密码错误和/或数据库已损坏。如果我们正在开始一个新数据库或更改主密码,请加密该“默认”密码并存储加密值。
使用主加密密钥解密URL、用户名、注释和其他非密码数据。
仅按用户请求使用主加密密钥解密现有密码(但仅解密用户请求的确切密码),然后在他们完成操作或定时器超时后立即用随机垃圾覆盖数据。使用该主加密密钥加密新密码。
一旦用户完成操作或计时器超时,立即用随机垃圾覆盖所有变量(特别是仅存在于内存中的主加密密钥)。
请注意,您正在存储:
您永远不会存储主密码或其哈希值。您永远不会将主密码、其哈希值或甚至生成的主加密密钥与其他任何内容进行比较。您只需获取主密码并将其转换为主加密密钥,然后使用该密钥加密或解密数据-已知数据(“固定”密码)可让您查看该密钥是否产生了预期的结果。当您知道主密码是正确的时,也会对未知数据(用户输入并关心的所有内容)进行加密或解密。