首先,背景:我正在尝试创建一个需要登录的基于命令行的工具(Linux)。该工具上的帐户与系统级帐户无关 - 这些都不是 /etc /passwd。

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

尽管不使用系统级密码文件,但使用Crypt似乎是一种很好的做法,而不是在ClearText中存储密码。(虽然crypt肯定比在clearText中存储密码更好,但我愿意采用其他方法。)

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

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

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

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

1)宣传密码中包含了明文密码的前两个字母。您可以通过不将前两个字符写入文件来解决此问题:

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

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

我能够得出的最佳实践是将用户名中的前两个字符用作盐。这是合适的,还是我错过的事情会导致这一不良举动?

我对盐的理解是,它可以防止词典的预计密码哈希。我可以将标准盐用于所有密码(例如我的缩写“ JS”),但对于攻击者来说,这似乎不如使用每个用户用户名中的两个字符的负担。

有帮助吗?

解决方案

有关使用隐窝模块的:

当产生加密的密码,则提供该盐。它也可能是随机的,以增加暴力破解阻力,只要符合上市条件。当检查密码,则应当提供从getpwname的值,如果您在支持更大的盐的尺寸和不产生它自己。在系统上

总评:

如果此无关瓦特/实际的系统登录,没有什么阻止您使用比隐窝更强的方法。你可以随机产生每个用户的盐的N个字符,以与用户的在SHA-1散列密码组合。

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

更新:虽然这是针对远彩虹表更安全,上面仍该方法具有加密的弱点。一个HMAC算法的正确应用可以再进一步提高安全性,但超出了我的专业领域。

其他提示

Python的隐窝()是用于该系统的隐窝()函数的包装。从Linux隐窝()手册页:

char *crypt(const char *key, const char *salt);

key is a user’s typed password.
salt is a two-character string chosen from the set [a–zA–Z0–9./]. 
This string is used to perturb the algorithm in one of 4096 
different ways.

重点是 “两个字符的字符串”。现在,如果你看的crypt()的行为在Python:

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

你发现结果的前两个字符总是与原始盐的前两个字符,这的确形成真实的二字符盐本身重合。 也就是说,隐窝的()的结果具有以下形式2char盐+加密通。 因此,存在在结果没有区别,如果不是传递传递全部加密密码的两个字符的盐或原许多字符盐的

注意:集合[a-zA-Z0-9./]包含64个字符,和64×64 = 4096。这里是如何的的文字涉及到 “ 4096 的不同的方式。”

你误解的文件;它说的是,由于该盐的长度可以根据底层的隐窝()实现而改变,则应该提供整个加密的密码作为盐值的当检查密码。也就是说,代替拉动前两个字符关是盐,只是抛在整个事情。

您具有初始盐的想法是基于用户名似乎正常。

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

  1. 一般来说,盐用于制造 兰弓表 计算成本太高。因此,您应该向所有密码哈希添加一点随机盐,并将其以明文形式存储在哈希密码值旁边。
  2. 使用 哈马卡 - 这是一个很好的标准,并且比连接密码和盐更安全。
  3. 使用 SHA1:MD5 已损坏。如果您知道这一点,无意冒犯,只是彻底。;)

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

对于一些附加的强度,就可以得到隐窝模块通过在格式使用盐使用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

(注意,这是一个GNU扩展加密,请参见“人隐窝” Linux系统上)。 MD5(现在连SHA1)可以是“断开的”,但他们仍然对密码哈希值比较好,MD5是仍然为Linux本地密码标准。

的密码,或从密码导出任何东西,不应该被用作盐。对于特定的密码的盐应该是不可预测的。

的用户名的用户名或部分是可容许的,但更重要的将是从加密RNG随机字节。

使用PBKDF2,请参阅在不同的线程此评论(包括Python实现)。

看一看文章 TrueCrypt的解释通过的Björn卓环球的。它包含易于理解如何TrueCrypt的作品的解释和一些TrueCrypt加密的功能,简单的Python实现的包括密码管理

  

他在谈论Python的隐窝()模块,而不是大约的TrueCrypt在Python

在Python 2默认crypt.crypt()不是非常安全和制品解释了如何更安全的替代品可能会奏效。

scroll top