如何仅使用符合 POSIX 标准的外壳工具生成字母数字字符串?



我正在尝试使用符合 POSIX 的 shell 工具生成一个八个字符的字母数字字符串。我正在尝试使用/dev/urandom 来生成这个字符串(顺便说一下,我不知道/dev/random 和/dev/urandom 不是由 POSIX 指定的,但我会使用它,因为它们存在于 Linux、FreeBSD、Mac OS、AIX 等上(。

有很多指南展示了如何做到这一点,但我发现没有一个接近于正确。特别是我一直看到使用 head -c(-c 参数未在 POSIX 中定义(,如下所示:

head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo ''

我的另一个担忧是,我见过的解决方案几乎没有一个尊重字节流和字符流之间的区别,这让我担心我正在生成不安全的字符串。

这是我似乎能想到的最好的,但我并不完全理解它:

strings -n 1 < /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1

它符合 POSIX 标准(减去/dev/urandom(,但我是否正确实现了我的目的?如果是这样,有没有更好的方法来实现这一目标?如果有一种方法可以在没有/dev/urandom 的情况下生成随机字符串,那也会很酷,但我想我在做梦。

只需使用awk,POSIX 授权提供rand函数。

$ cat password.awk
BEGIN {
srand();
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
s = "";
for(i=0;i<8;i++) {
s = s "" substr(chars, int(rand()*62), 1);
}
print s
}
$ awk -f password.awk
Cl7A4KVx

(这几乎可以肯定是用代码打高尔夫球成更短的东西;我的awk技能有些有限。

如果需要多个密码,请将所需的数字作为参数传递,这样就不需要每秒运行awk多次:

BEGIN {
srand();
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
for(i=0;i<n;i++) {
s = "";
for(j=0;j<8;j++) {
s = s "" substr(chars, int(rand()*62), 1);
}
print s
}
}

要传递值n,以awk -v n=5 -f password.awk身份运行以生成 5 个密码。

或者,您可以将不同的种子直接传递给awk

BEGIN {
srand(seed);
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
s = "";
for(i=0;i<8;i++) {
s = s "" substr(chars, int(rand()*62), 1);
}
print s
}

awk -v seed=$newseed -f password.akw.请注意,newseed本身每次都需要具有不同的值,但使用简单的种子顺序序列就足够了。

seed=$(date +%s)
awk -v seed=$seed -f password.awk; seed=$((seed + 1))
awk -v seed=$seed -f password.awk; seed=$((seed + 1))
awk -v seed=$seed -f password.awk; seed=$((seed + 1))
# etc

试试这个:

head -n 1 /dev/urandom | hexdump | head -n 1 | sed ‘s/0+| //g’ | sed ‘s/(......).*/1/g’

八个"随机"字母数字字符,只有 POSIX 工具箱?很好,一个挑战!

让我们首先观察一下,Base-64 编码几乎只使用字母数字(以及+/(,出色的 POSIX 人员在 uuencode 实用程序中添加了 Base-64 支持-m

接下来,我们从哪里得到一些(伪?几乎?(随机性?再次观察当前的进程列表是非常随意的,特别是如果它包含长格式的所有进程,带有 CPU 时间等等。

我们使用 POSIXly cksum 实用程序进一步压缩 ps 熵,因为 ps 输出的第一行非常恒定,我们必须在 uuencoding 输出中寻找合适的行(这很混乱(。

到目前为止,我们有

$ ps|cksum|uuencode -m -
begin-base64 644 -
MjUwMDcyMjY3NSAxOTExCg==
====

运行几次,我们注意到(或知道(第二行中的前两个字符不是很随机的,因为它们包含行的长度。所以我们从第 3 行的位置 2 中提取 8 个字符

$ ps|cksum|uuencode -m -|sed -n 's,[+/],0,g; 2s/^..(........).*/1/p'
kzNDkzMj
$ ps|cksum|uuencode -m -|sed -n 's,[+/],0,g; 2s/^..(........).*/1/p'
I0NTcxND

并将不需要的+/转置为0.几乎可以保证每次调用的结果都不同,因为每次运行时三重管道中命令的进程 ID 都不同。

瞧!不需要/dev/urandom:-(

最新更新