生成随机密码;为什么不便携?


21

我想生成一个随机密码,并且这样做:

</dev/urandom tr -dc [:print:] | head -c 64

在运行Ubuntu的笔记本电脑上,这只会按预期生成可打印的字符。但是,当我进入学校的运行Red Hat Enterprise Linux的服务器并在其中运行服务器时,3!ri�b�GrӴ��1�H�<�oM����&�nMC[�Pb�|L%MP�����9��fL2q���IFmsd|l�K会得到诸如之类的输出,但根本无法执行。这里可能出什么问题了?

Answers:


34

这是您的语言环境tr问题。

当前,GNU tr仅完全支持单字节字符。因此,在使用多字节编码的语言环境中,输出可能很奇怪:

$ </dev/urandom LC_ALL=vi_VN.tcvn tr -dc '[:print:]' | head -c 64
`�pv���Z����c�ox"�O���%�YR��F�>��췔��ovȪ������^,<H ���>

Shell将正确打印多字节字符,但是GNU tr会删除它认为不可打印的字节。

如果要使其稳定,则必须设置区域设置:

$ </dev/urandom LC_ALL=C tr -dc '[:print:]' | head -c 64
RSmuiFH+537z+iY4ySz`{Pv6mJg::RB;/-2^{QnKkImpGuMSq92D(6N8QF?Y9Co@

14
+1是因为这使我意识到(仅在Unix / Linux上使用shell已有30年之久了),并不需要将stdin / stdout / stderr重定向放在其所应用的命令之后
Anthon

只是注释一下,如果设置了一些奇怪的语言环境,即使它们不是ascii,外壳程序是否仍不能正确打印字符?至少有能力的shell(当然不包括xterm)?
Orion

2
@orion:shell将正确打印字符。在这种情况下,这是tr问题。它删除了它认为不可打印的字节,使结果变得怪异。
cuonglm

@orion通常,统一的字节流不是格式良好的UTF-8字符编码的统一随机流。
zwol

同样,除非你有什么空间在您的密码,你应该使用:graph:,而不是:print:</dev/urandom LC_ALL=C tr -dc '[:graph:]' | head -c 64
鹅蛋

11

考虑代替

$ dd if=/dev/urandom bs=48 count=1 status=none | base64
imW/X60Sk9TQzl+mdS5PL7sfMy9k/qFBWWkzZjbYJttREsYpzIguWr/uRIhyisR7

这有两个优点:

  • 您只能从随机设备读取48个字节,而不是〜8KB;如果同一主机上的其他进程需要随机数,则一次耗尽8KB可能是一个严重的问题。(是的,可以说任何人都不应使用随机器,但人们这样做。)

  • 的输出base64几乎不包含具有特殊含义的字符。(对于根本没有,钉| tr +/ -_在端,以及(如实施例)确保的字节数输入base64是3的倍数)

这种方式生成一个密码,熵,这是正好384位稍微低于你正在做(日志2 96 64 ≈421.4),但更足以满足大多数目的(熵的256位是安全的“的时候,还在猜测Sun烧尽了”区域, RSA密钥AFAIK除外。


3

其他人已经指出,语言环境决定了什么[:print:]。但是,并非所有可打印的字符都适用于密码(即使在ascii中也不适用)。您真的不想要空格,制表符和#$%^吗?用您的密码-不仅难以记住,而且还对基础身份验证系统造成潜在危险,可能无法在输入字段中输入,依此类推。在这种情况下,您应该只手动选择“理智”字符:

LC_ALL=C </dev/urandom tr -dc '[:alnum:]_' | head -c 64

或简单地

</dev/urandom tr -dc 'A-Za-z0-9_' | head -c 64

甚至更好,base64按照其他答案中的建议使用。


有问题的密码永远不会由人输入(如果要使用Diceware的话),而且我很确定底层系统可以毫无问题地处理特殊字符。不管怎么说,还是要谢谢你。
塔蒙2015年

4
你所说的完全错误。强迫用户仅使用ascii字母,数字和下划线会大大减小字母的大小,从而使攻击者更容易破解密码。认证系统甚至无法处理?^太糟糕以至于不能被认真对待。
2015年

2
如果您的身份验证系统或输入字段在常规的ASCII符号上阻塞...那么您在做错了事,不要被我的私人信息所信任。绝对没有理由不接受密码中的所有字符(包括空格)。
nzifnab

2
似乎这里不是这种情况,但是当涉及到人工输入时,记住一个长字母数字密码对所有者而言具有独特的意义,而不是一个较短的符号混乱,要容易得多。还存在在各种键盘上输入这些字符的问题(并不是每个人在第一级上都有^,而且大多数人甚至都不知道反引号在哪里或什么),输入框几乎可以肯定不能处理制表符,并且数量惊人的Web表单仍然容易受到验证错误,SQL注入甚至不确定的区分大小写的影响。
Orion

1
刚一说明:在C语言环境[:print:]类并没有包含标签。它只是[:alnum:]+ [:punct:]+空间(单个空间,不是 [:space:])。
jimmij 2015年

2

关于什么

tr -dc [:print:] < /dev/urandom | head -c 64 | strings

字符串应以可打印的格式打印urandom的输出


这给出了-bash: /dev/urandom: Permission denied
Anthon

抱歉忘了领头猫
Blindstealer

2

我不知道您是否有理由使用/dev/random该密码来生成密码,但是我建议您使用pwgen来减轻您的痛苦。

$ pwgen -s 10 1

其中10是密码的长度。

http://man.cx/pwgen


1
#Chars allowed in password (I don't like l,o,O, etc):
P="0123456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz"

#Or such:
#P="a-zA-Z0-9"

head -c 8 < /dev/urandom | tr '\000-\377' "$P$P$P$P$P"
echo

当从/ dev / urandom中使用数据时,此方法IMHO更为智能。粘贴为$ P $ P $ P ...的字符串必须至少为256个字符。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.