在数据库中存储用户和密码

10

我正在创建一个带用户和密码的软件。在身份验证后,用户可以访问一些半公共服务,并加密一些只有用户才能访问的文件。

如果可能的话,必须按原样存储用户。在进行身份验证后,只要软件在运行,用户和密码就会被保存在内存中(我不确定这是否安全)。

问题是如何在潜在不安全的数据库中存储此用户+密码组合?

我不太明白应该暴露什么。

假设我像这样创建了增强的密钥:

salt = 随机32个字符的字符串(可以吗?)
key = hash(usr password + salt)
for 1 to 65000 do
  key = hash(key + usr password + salt)

我应该在数据库中存储[明文用户]、[增强的密钥]和[盐]吗?

还有,我应该使用什么来每次都使用新密码来加密(使用AES或Blowfish)一些文件? 我应该生成一个新的盐并使用(程序内存中存储的密码+盐)创建新的增强密钥吗? 如果是这种情况,如果我将加密的文件存储在数据库中,我应该只存储盐。 数据库与存储用户+密码组合的地方相同。

只有当有人可以生成密钥但不知道密码时,该文件才能被解密。对吗?

我使用Python和PyCrypto,但这并不重要,一个通用的例子就足够了。 我已经阅读了一些类似的问题,但它们没有很明确的回答。

非常非常感谢!

2个回答

10

加密很难做好,你能够提出问题是好的。

存储密码:密码应使用 键伸展算法 进行哈希处理。通常情况下,建议使用库而不是自己实现。 键伸展算法旨在消耗处理器周期,因此最好使用良好的C代码进行评估。如果您正在使用带有 glibc 的Linux系统,则可以使用 crypt.crypt 模块 (查阅 man crypt ):

import crypt
encrypted = crypt.crypt(password, '$6$' + salt + '$')

这将返回一个ASCII字符串,您可以安全地存储在数据库中。($6$是一个基于SHA-512的密钥延展函数的glibc扩展。如果您没有此扩展,请不要使用crypt.crypt)。 (编辑:算法与您在问题中询问的算法非常相似。然而,最佳实践通常是让库来完成这些事情,而不是自己编写代码。)

加密文件:不要自己动手。安装GnuPG(或scrypt、bcrypt、ncrypt等)。当您设计自己的文件加密方式时,很容易出现一些问题。这些工具使用适当的密钥派生函数、认证哈希和密码模式,无需进行任何额外配置。它们不是Python库,而是可执行文件,因此您需要编写一个使用subprocess模块的包装器。

内存中的密码:不要。一旦您已经将用户的密码与密码数据库进行了比对,就使用密钥派生函数将密码转换为密钥。然后您可以使用该密钥来解锁加密文件,但是您不能再使用它来获取原始密码。


1
关于密码哈希,还有一个跨平台的SHA512-Crypt实现可供使用。链接 - Eli Collins
非常感谢您的建议,太棒了!@Elis:哇,那个Python库绝对棒极了!// 但是,有一件事我不明白!如果我不将密码保存在内存中,我应该向scrypt/bcrypt/ncrypt程序发送什么作为加密文件的密码? - Cristi Constantin
@Cristi:您可以使用一个不同的盐值来使用密钥派生函数将密码转换为加密文件的密钥。 - Dietrich Epp
@Cristi:关于密钥派生函数,我强烈推荐使用PBKDF2,您甚至可以使用用户的密码哈希作为盐,但无论如何都要使用>10000轮。关于PBKDF2,有passlib实现,来自pycrypto作者的基于pycrypto的模块,以及一个m2crypto实现,尽管这最后两个只使用SHA1。 - Eli Collins

2
如果你为每个用户使用不同的盐值,那么你必须将其存储在某个地方(最好是不同的位置)。如果你为每个用户使用相同的盐值,你可以在应用程序中硬编码它,但这可能被认为不够安全。 如果你不保留盐值,你将无法将给定的密码与数据库中的密码进行匹配。
盐值的目的是使暴力破解或字典攻击变得更加困难。这就是为什么将其分开存储更安全,以避免某人同时拥有哈希密码和对应的盐值。

1
将盐存储在单独的位置没有真正的意义。请参见https://dev59.com/hXM_5IYBdhLWcg3wzmnL。 - Dietrich Epp
盐对于每个用户都是不同的,并且存储在同一个数据库中。 - Cristi Constantin
如果您有一个明确的密码,您不需要哈希或盐,您可以尝试通过正常界面登录。 - Dietrich Epp
取决于您的应用程序和情况。想象一下邮件客户端的数据库,其中包含所有电子邮件帐户的凭据。如果有人没有访问应用程序本身的权限,但却窃取了数据库...但这是一个复杂的情景,我认为我们正在偏离主题。 - Yannick Loiseau
@Yannick:这不仅仅是复杂,而是非常奇怪的情况:密码泄露与数据库泄露相结合,但完全没有访问应用程序的权限,而且泄露的唯一信息是你可以在没有数据库泄露的情况下获得的信息,而且提出的解决方案可能不起作用。 - Dietrich Epp
显示剩余3条评论

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