【问题标题】:Python crypt module -- what's the correct use of salts?Python crypt 模块——盐的正确用法是什么?
【发布时间】:2008-12-01 03:31:45
【问题描述】:

首先,上下文:我正在尝试创建一个基于命令行的工具 (Linux) 需要登录。此工具上的帐户与此无关 系统级帐户——这些都不会查看 /etc/passwd。

我打算使用与 /etc/passwd 相同的格式(大致)将用户帐户存储在文本文件中。

尽管没有使用系统级密码文件,但似乎使用了 crypt 是一种使用的好习惯,而不是将密码存储在 明文。 (虽然 crypt 肯定比将密码存储在 明文,我愿意接受其他方式。)

我的地穴知识基于此: https://docs.python.org/2/library/crypt.html

文档似乎要求一些不可能的东西:“它 建议检查时使用完整的加密密码作为盐 密码。”

嗯?如果我正在创建加密密码(如创建用户时 记录)如何使用加密密码作为盐?它 还不存在。 (我假设您必须使用相同的盐来创建和检查密码。)

我尝试使用明文密码作为盐。这确实 工作,但有两个问题;一种容易克服,一种严重:

1) 明文密码的前两个字母包含在 加密密码。你可以通过不写前两个来解决这个问题 文件中的字符:

user_record = '%s:%s:%s' % (user_name, crypted_pw[2:], user_type)

2) 通过使用明文密码作为盐,您似乎是 减少系统中的熵。可能我是 误解了盐的用途。

我能够得出的最佳做法是使用前两个 用户名中的字符作为盐。这样合适吗 还是有什么我错过的东西让这一步变得糟糕?

我对盐的理解是它可以防止预计算密码 来自字典的哈希。我可以为所有人使用标准盐 密码(例如我的首字母“JS”),但这似乎不是一个 比使用每个用户的用户名中的两个字符对攻击者的负担更大。

【问题讨论】:

    标签: python linux cryptography crypt


    【解决方案1】:

    Python 的 crypt() 是系统的 crypt() 函数的包装器。来自 Linux crypt() 手册页:

    char *crypt(const char *key, const char *salt); key 是用户输入的密码。 salt 是从集合 [a–zA–Z0–9./] 中选择的两个字符的字符串。 此字符串用于扰乱 4096 之一中的算法 不同的方式。

    重点是“双字符字符串”。现在,如果您查看 crypt() 在 Python 中的行为:

    >>> crypt.crypt("Hello", "World")
    'Wo5pEi/H5/mxU'
    >>> crypt.crypt("Hello", "ABCDE")
    'AB/uOsC7P93EI'
    

    您发现结果的前两个字符总是与原始盐的前两个字符一致,这确实形成了真正的双字符盐本身。 也就是说, crypt() 的结果形式为 2char-salt + encrypted-pass。 因此,如果不是传递两个字符的盐或原始的多字符盐,而是传递整个加密的密码,则结果没有区别。

    注意:集合 [a–zA–Z0–9./] 包含 64 个字符,64*64=4096。以下是 两个 字符与“4096 个不同的方式”的关系。

    【讨论】:

      【解决方案2】:

      关于crypt模块的使用:

      在生成加密密码时,您提供盐。只要满足列出的条件,增加对暴力破解的抵抗力也可能是随机的。检查密码时,您应该提供 getpwname 中的值,以防您使用的系统支持更大的 salt 大小并且不是自己生成的。

      一般cmets:

      如果这与实际系统登录无关,那么没有什么能阻止您使用比 crypt 更强大的方法。您可以随机生成 N 个字符的每个用户 salt,以与 SHA-1 哈希中的用户密码组合。

      string_to_hash = user.stored_salt + entered_password
      successful_login = (sha1(string_to_hash) == user.stored_password_hash)
      

      更新:虽然这对彩虹表来说要安全得多,但上述方法仍然存在加密弱点。正确应用 HMAC 算法可以进一步提高您的安全性,但这超出了我的专业范围。

      【讨论】:

      • 首选 PBKDF2 来保存密码:使用 HMAC 加盐并迭代
      【解决方案3】:

      您误解了文档;它说由于盐的长度可能会根据底层 crypt() 实现而有所不同,因此您应该在检查密码时提供整个加密密码作为盐值。也就是说,不要把前两个字符拉出来做盐,而是把整个东西都扔进去。

      您将初始盐基于用户名的想法似乎没问题。

      【讨论】:

        【解决方案4】:

        以下是一些关于加盐密码的一般建议:

        1. 通常,使用盐来使ranbow tables 计算成本过高。因此,您应该在所有密码哈希中添加一点随机盐,并将其以明文形式存储在哈希密码值旁边。
        2. 使用HMAC - 这是一个很好的标准,而且比连接密码和盐更安全。
        3. 使用 SHA1:MD5 已损坏。如果您知道这一点,就没有冒犯的意思,只是彻底。 ;)

        不会让盐成为密码的函数。攻击者必须生成一个彩虹表才能拥有一个即时查找密码数据库,但他们只需要这样做一次。如果您选择一个随机的 32 位整数,它们必须生成 2^32 个表,这(与确定性盐不同)会耗费太多内存(和时间)。

        【讨论】:

          【解决方案5】:

          为了增加强度,您可以通过在格式中使用盐来让 crypt 模块使用 md5。

          $1$ABCDEFGH$
          

          ABCDEFGH 是你的盐字符串。

          >>> p = crypt.crypt('password', '$1$s8Ty3/f$')
          >>> p
          Out: '$1$s8Ty3/f$0H/M0JswK9pl3X/e.n55G1'
          >>> p == crypt.crypt('password', p)
          Out: True
          

          (请注意,这是 crypt 的 gnu 扩展,请参阅 linux 系统上的“man crypt”)。 MD5(现在甚至是 SHA1)可能会“坏掉”,但它们对于密码哈希仍然相对较好,而且 md5 仍然是 linux 本地密码的标准。

          【讨论】:

          • 请注意,如果您的系统允许,如果您不信任 MD5,您甚至可以:crypt.crypt("some_password","$5$some_salt")crypt.crypt("some_password","$6$some_salt") 使用 sha-256 或 sha-512。另请注意,crypt 使用多轮 DES/MD5/SHA* 使其比仅使用单轮更安全。所以 MD5 被破坏并不自动意味着 $1$ 的 crypt 是。
          【解决方案6】:

          密码或从密码派生的任何内容都不应用作盐。特定密码的盐值应该是不可预测的。

          用户名或用户名的一部分是可以容忍的,但更好的是来自加密 RNG 的随机字节。

          【讨论】:

            【解决方案7】:

            使用 PBKDF2,在不同的线程上查看 this comment(包括 Python 实现)。

            【讨论】:

              【解决方案8】:

              查看 Björn Edström 的文章 TrueCrypt explained。它包含对 truecrypt 工作原理的易于理解的解释以及 truecrypt 的一些功能包括密码管理的简单 Python 实现。

              他说的是 Python crypt() 模块,而不是 Python 中的 TrueCrypt

              Python 2 中的默认 crypt.crypt() 不是很安全,the article 解释了更安全的替代方案如何工作。

              【讨论】:

              • 他说的是 Python crypt() 模块,而不是 Python 中的 TrueCrypt。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-04-09
              • 2012-05-14
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-01-19
              相关资源
              最近更新 更多