【问题标题】:Storing user and password in a database在数据库中存储用户和密码
【发布时间】:2011-08-28 19:38:25
【问题描述】:

我正在使用用户+密码创建一个软件。认证后,用户可以访问一些半公共服务,但也可以加密一些只有用户才能访问的文件。

如果可能,用户必须按原样存储,不得修改。认证后,只要软件在运行,用户和密码就会一直保存在内存中(我也不知道这样行不行)。

问题是我应该如何将这个用户+密码组合存储在一个可能不安全的数据库中?

我真的不明白我应该暴露什么。

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

salt = 随机 32 个字符的字符串(可以吗?) 密钥 = 哈希(用户密码 + 盐) 对于 1 到 65000 做 key = hash(key + usr 密码 + salt)

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

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

只有在有人可以生成密钥但不知道密码的情况下才能解密文件。对吧?

我将 Python 与 PyCrypto 一起使用,但这并不是很重要,一个一般的例子就可以了。 我读过一些类似的问题,但不是很明确。

非常感谢!

【问题讨论】:

    标签: python security passwords


    【解决方案1】:

    加密货币很难做对,你问问题很好。

    存储密码:密码应使用密钥拉伸算法进行哈希处理。通常,您希望使用库而不是自己实现它。关键拉伸算法旨在消耗处理器周期,因此用漂亮的 C 代码评估它们是很好的。如果您在带有glibc 的Linux 系统上,您可以使用crypt.crypt 模块(阅读man crypt):

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

    这将返回一个 ASCII 字符串,您可以将其安全地存储在数据库中。 ($6$ 是一个 glibc 扩展,它使用基于 SHA-512 的密钥拉伸功能。如果您没有此扩展,则不要使用 crypt.crypt)。 (编辑:该算法与您在问题中询问的算法非常相似。但是,最佳做法通常是让库来做这些事情,而不是自己动手。)

    加密文件:不要自己做。安装 GnuPG(或 scrypt、bcrypt、ncrypt,你有什么)。当您设计自己的文件加密方式时,有些事情很容易出错。这些工具使用正确的密钥派生函数、身份验证哈希和密码模式,无需任何额外配置。它们不是 Python 库,而是可执行文件,因此您必须编写一个使用 subprocess 模块的包装器。

    内存中的密码:不要。根据密码数据库检查用户密码后,使用密钥派生函数将密码转换为密钥。然后您可以使用该密钥来解锁加密文件,但您不能再使用它来取回原始密码。

    【讨论】:

    • 关于密码哈希,还有一个cross-platform SHA512-Crypt 实现可用。
    • 非常感谢您的建议,太好了! @Elis:哇,那个 python 库真是太棒了! // 但是,有一点我不明白!...如果我不将密码保存在内存中,我应该发送什么 scrypt/bcrypt/ncrypt 程序作为加密文件的密码?
    • @Cristi:您可以使用带有不同盐的密钥派生函数将密码转换为加密文件的密钥。
    • @Cristi:关于密钥派生函数,我强烈推荐 PBKDF2,您甚至可以使用用户的密码哈希作为盐,但无论如何绝对要使用 >10000 轮。关于 PBKDF2,有来自 pycrypto 作者的passlib implementationpycrypto-based modulem2crypto implementation,尽管最后两个只做 SHA1。
    【解决方案2】:

    如果您为每个用户使用不同的盐,则必须将其存储在某个地方(最好是在不同的地方)。如果您为每个用户使用相同的盐,您可以在您的应用程序中对其进行硬编码,但它可能被认为不太安全。 如果您不保留盐,您将无法将给定的密码与数据库中的密码进行匹配。

    盐的目的是使蛮力或字典攻击更加困难。这就是为什么单独存储更安全的原因,以避免有人同时拥有哈希密码和相应的盐。

    【讨论】:

    • 将盐存放在单独的地方没有实际意义。见stackoverflow.com/questions/1219899/…
    • 盐对于每个用户来说都是不同的,并且存储在同一个数据库中。
    • @Dietrich Epp:只是为了避免社会工程发现密码(尽管只是一个密码)或在同一用户的多个帐户(例如,多个服务的客户端)的情况下检查是否其他帐户使用相同的密码。
    • 因为每个需要访问哈希的应用程序都需要访问盐,反之亦然,如果没有另一个应用程序就不太可能受到损害。如果两次使用相同的密码,盐仍然会有所不同,这就是首先使用盐的意义所在。所以你无法检查两个密码是否相同。
    • @Dietrich Epp:似乎您可以通过使用相应的哈希重新哈希每个帐户密码来检查您是否有一个清晰的密码和每个盐(在此测试的密码数量很少塞纳里奥)。但是,我同意两者可能会同时受到损害。
    猜你喜欢
    • 1970-01-01
    • 2019-05-17
    • 2017-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-20
    • 2011-04-26
    相关资源
    最近更新 更多