Tay*_*mon 22 shell character-encoding binary tr portability
我想生成一个随机密码,并且这样做:
</dev/urandom tr -dc [:print:] | head -c 64
Run Code Online (Sandbox Code Playgroud)
在我运行 Ubuntu 的笔记本电脑上,这仅产生预期的可打印字符。但是,当我通过 ssh 连接到运行 Red Hat Enterprise Linux 的学校服务器并在那里运行时,我得到类似 的输出3!ri?b?Gr???1?H?<?oM????&?nMC[?Pb?|L%MP?????9??fL2q???IFmsd|l?K
,但根本无法执行。这里可能出了什么问题?
cuo*_*glm 36
目前,GNU tr完全支持单字节字符。所以在使用多字节编码的语言环境中,输出可能很奇怪:
$ </dev/urandom LC_ALL=vi_VN.tcvn tr -dc '[:print:]' | head -c 64
`?pv???Z????c?ox"?O???%?YR??F?>?????ov???????^,<H ???>
Run Code Online (Sandbox Code Playgroud)
shell 会正确打印多字节字符,但 GNUtr
会删除它认为不可打印的字节。
如果您希望它稳定,则必须设置语言环境:
$ </dev/urandom LC_ALL=C tr -dc '[:print:]' | head -c 64
RSmuiFH+537z+iY4ySz`{Pv6mJg::RB;/-2^{QnKkImpGuMSq92D(6N8QF?Y9Co@
Run Code Online (Sandbox Code Playgroud)
zwo*_*wol 11
考虑代替
$ dd if=/dev/urandom bs=48 count=1 status=none | base64
imW/X60Sk9TQzl+mdS5PL7sfMy9k/qFBWWkzZjbYJttREsYpzIguWr/uRIhyisR7
Run Code Online (Sandbox Code Playgroud)
这有两个好处:
您只从随机设备中读取了 48 个字节,而不是 ~8KB;如果同一主机上的其他进程需要随机数,一次全部耗尽 8KB 可能是一个严重的问题。(是的,可以说没有人应该使用阻塞随机设备,但人们确实这样做了。)
的输出base64
几乎不包含具有特殊含义的字符。(对于根本没有,钉| tr +/ -_
在端,以及(如实施例)确保的字节数输入到base64
是3的倍数)
以这种方式生成的密码正好有 384 位的熵,这比您所做的要少一些(日志2 96 64 ≈ 421.4),但对于大多数用途来说已经足够了(256 位的熵安全地处于“仍在猜测何时除了RSA 密钥,AFAIK之外,Sun 会烧毁”领土)。