如何生成随机字符串?

lan*_*oni 377 password string random

我想生成一个随机字符串(例如密码、用户名等)。应该可以指定所需的长度(例如 13 个字符)。

我可以使用哪些工具?

(出于安全和隐私原因,最好是离线生成字符串,而不是在网站上在线生成。)

小智 362

我最喜欢的方法是使用/dev/urandomwithtr删除不需要的字符。例如,只获取数字和字母:

tr -dc A-Za-z0-9 </dev/urandom | head -c 13 ; echo ''
Run Code Online (Sandbox Code Playgroud)

或者,从OWASP 密码特殊字符列表中包含更多字符:

tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' </dev/urandom | head -c 13  ; echo
Run Code Online (Sandbox Code Playgroud)

如果您在tr抱怨输入时遇到一些问题,请尝试添加LC_ALL=C以下内容:

LC_ALL=C tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' </dev/urandom | head -c 13 ; echo
Run Code Online (Sandbox Code Playgroud)

  • 或者这样做:`head /dev/urandom | tr -dc A-Za-z0-9 | head -c10` - 这种方式更准确。你得到 10 个大写、小写或数字的字符 (26认同)
  • 第一个 `head` 命令可能有问题。它将输出 `/dev/urandom` 的前 10 行,这意味着它会在看到第 10 个换行符后停止。所以发送到 `tr` 命令的输出长度是随机的。`tr` 的输出可能少于 13 个字符。我还没有计算过这种情况发生的概率,计算有点棘手。 (14认同)
  • 最好这样做:`&lt;dev/urandom tr -dc "$charset" | head -c "$length"` (7认同)
  • 对于`LC_ALL=C` 解决方法+1。在我的情况下`head /dev/urandom | LC_ALL=C tr -dc A-Za-z0-9 | head -c 13)` 就地修复了 OSX `tr` 问题。 (6认同)
  • +1 快速尝试包含 [OWASP 密码特殊字符页面](https://www.owasp.org/index.php/Password_special_characters) 中的其他字符,为 bash 命令行转义:`tr -dc A- Za-z0-9\!\"#$\&amp;\'\(\)\*+,-./\:\\\\\;\&lt;=\&gt;\?@[]^_\`{\ |}~` (3认同)
  • 不适用于 OSX 的 `tr` 版本,但适用于 GNU `tr`(您可以通过 `brew install coreutils` 获得。) (3认同)
  • @Rup 我不确定什么不适用于您的 `tr ..` 命令,但只是引用所有内容(单引号除外)有效 – `tr -dc 'A-Za-z0-9!"#$%&amp;' \''()*+,-./:;&lt;=&gt;?@[\]^_\`{|}~'`。 (2认同)
  • macOS `tr` 默认需要 UTF-8 输入,但 `/dev/urandom` 不是 UTF-8 编码字符而是随机字节,所以你会得到一个 `tr: Illegal byte sequence` 错误。您可以通过将管道中的“tr”命令的“LC_ALL”环境变量设置为“C”来解决此问题。这导致 `tr` 期望任意字节。 (2认同)

400*_*Cat 272

我正在使用openssl命令,密码学的瑞士军刀。

openssl rand -base64 12
Run Code Online (Sandbox Code Playgroud)

或者

openssl rand -hex 12
Run Code Online (Sandbox Code Playgroud)

  • `rand -hex` 将输出限制为 16 个字符,而不是键盘上的 90+。base64 更好,因为它有 64 个字符,但它不是随机的(例如,有可预测的填充模式,也许某些字符比其他字符出现得更频繁)。 (18认同)
  • 这个答案值得更多赞成。urandom、pwgen、gpw 等可能在您的系统上可用,也可能不可用;同样在不同的环境中,适用于一个的策略可能不适用于另一个。没有 openssl 将是一个非常不正常的设置。更好:openssl rand -base64 32 | tr -d /=+ | cut -c -16 这将为您提供 32 个字符减去非字母数字并修剪为 16 个字符的长度。以管理员身份轻松应对。用户只有字母数字(他们倾​​向于欣赏)。长度足够长,去除特殊字符不会过度影响熵。金的。 (10认同)
  • 请注意,手册说“openssl rand”是一个_加密安全的_伪随机数生成器(CSPRNG)。 (6认同)
  • 请注意,根据其手册,“openssl rand”命令仍然是一个伪随机生成器,因此在密码学上并不安全。这适合我的需要,但可能不适合所有应用程序的需要,例如在另一条评论中提到初始化 IV。 (5认同)
  • @Carpetsmoker:请注意,示例 `openssl rand -base64 12` 产生 16 个字符的输出(因为 256 个值映射到 64 个)。十六进制示例产生 24 个字符。在十六进制的情况下没有损失,因为它是一个简单的 1:2 映射,但在 base64 情况下可能会有一点损失,因为使用了填充。基数不影响随机性,这是一个映射到另一个的方式。(并且总位数更为重要)。 (2认同)
  • 问题是“如何生成特定长度的随机字符串”@DennisWilliamson,因此虽然您的评论*本身是正确的*,但*在这个问题的上下文中*是不正确的。 (2认同)

lan*_*oni 176

要生成随机密码,您可以使用pwgen

pwgen 生成随机的、无意义但可发音的密码。这些密码要么只包含小写字母,要么包含大小写混合,要么包含数字。大写字母和数字的放置方式可以在只记住单词时轻松记住它们的位置。

生成 7 个长度为 13 的密码:

geek@liv-inspiron:~$ pwgen 13 7
Eu7Teadiphaec giepahl3Oyaiy iecoo9Aetaib4 phaiChae6Eivi athoo3igee8Co
Iphu4ufeDeelo aesoYi2lie9he 
Run Code Online (Sandbox Code Playgroud)

如评论中所述,您可以通过使用-s参数来避免减少熵(即生成更安全、完全随机但难以记住的密码):

geek@liv-inspiron:~$ pwgen -s 13 7
eAfycrPlM4cYv 4MRXmZmyIVNBp D8y71iqjG7Zq7 FQRHcserl4R8O yRCUtPtV3dsqV
0vJpp2h0OrgF1 QTp7MKtJyTrjz 
Run Code Online (Sandbox Code Playgroud)

要生成随机用户名,您可以使用gpw

这个包生成可发音的密码。它使用从您提供给它的任何词典中获取的三字母组合(三合字母)的统计数据。

生成 7 个长度为 13 的密码(用户名):

geek@liv-inspiron:~$ gpw 7 13
sreepoidahsas
risadiestinge
ntodynesssine
deodstestress
natinglumperm
riasigentspir
enderiferback
Run Code Online (Sandbox Code Playgroud)

  • +1 表示没有重新发明轮子。如果您不希望“发音”约束的熵减少,只需使用 `pwgen -s`。 (28认同)
  • 太糟糕了`pwgen` 没有包含在标准 bash 版本中。 (3认同)

小智 29

这是方法,我做到了。它生成 10 个字符的随机字符串。您可以通过用其他字符串处理工具替换“折叠”来优化它。

cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 10 | head -n 1
Run Code Online (Sandbox Code Playgroud)


小智 22

受 Pablo Repetto 的启发,我最终得到了这个易于记忆的解决方案:

shuf -zer -n20  {A..Z} {a..z} {0..9}
Run Code Online (Sandbox Code Playgroud)

-z 避免多行输出

-e 回显结果

-r 允许任何字符出现多次

-n20 长度为 20 个字符的随机字符串

{A..Z} {a..z} {0..9} 允许的字符类

shuf 是 linux coreutils 的一部分,可广泛使用或至少已移植。

  • 这里的一个问题是“-z”,因为它不会“避免多行输出”,而是向每个字符串附加一个 \0 而不是换行符。通过附加“| od -xc”来测试它。您可以使用 tr 删除零字符:`shuf -zer -n20 {A..Z} {a..z} {0..9} | tr -d '\0'` (2认同)

drw*_*rws 19

要使用我使用的每个发行版中内置的标准 Linux 工具生成具有最高熵的密码:

< /dev/urandom tr -cd "[:print:]" | head -c 32; echo
Run Code Online (Sandbox Code Playgroud)

这将输出所有 ASCII 可打印字符 - 从 32(空格)到 126(波浪号,~.)。密码长度可以通过head's-c标志控制。还有其他可能的字符集tr(不包括空格,只有字符 33-126,使用[:graph:])。

  • @Fox 他的解决方案使用硬编码的字符列表,由于代码可读性、紧凑性和清洁度,这不是一种鼓励的编程实践。还有一些特殊的可打印 ASCII 字符可以被 bash 解释,更不用说他的一个班轮最明显的缺点 - 如果需要最大熵,可以确定所有可用字符都包含在列表中吗?并且没有可能改变 tr 行为的重复项?既然你问了,他的答案应该被我的答案取代:) (5认同)
  • `&lt; /dev/urandom tr -cd '[:graph:]'| tr -d '\\' | 头-c 32; echo` 如果您不想在生成的字符串中使用 `\` 字符。`\` 因为是许多语言中的转义字符会导致问题 (3认同)
  • 这与现有答案有何不同?具体来说,[赫伯特的](/a/230676/) 浮现在脑海中。 (2认同)
  • 许多网站(如果不是大多数)对密码中的字符都有限制,因此硬编码 '[:print:]' 对我来说并不比硬编码 OWASP 密码特殊字符列表更好。我觉得这里几乎每个答案都可以通过使用变量来改进,但这是一个很小的变化,我只建议进行编辑 (2认同)
  • @RyanKrage `:graph:` 已经排除了空间,因此比 `:print:` 更好的解决方案。 (2认同)

ter*_*don 14

根据你想要的随机性的水平,你可以简单地使用bash的(也去zshksh,可能还有其他)内置$RANDOM变量:

$ echo $RANDOM | tr '[0-9]' '[a-z]'
bfeci
$ echo $RANDOM | tr '[0-9]' '[a-z]'
cijjj
Run Code Online (Sandbox Code Playgroud)

直接读取的方法/dev/urandom要简单得多,但为了完成,您也可以使用$RANDOM

echo $(for((i=1;i<=13;i++)); do printf '%s' "${RANDOM:0:1}"; done) | tr '[0-9]' '[a-z]'
Run Code Online (Sandbox Code Playgroud)

重要提示:此解决方案将仅使用字母表的前 10 个字母生成随机字符串。这对你来说是否足够取决于你需要它做什么。

  • @landroni我认为在获得正确的长度之前你不能缺少使用循环。`$RANDOM` 将打印 0 到 32767 之间的数字。 (2认同)
  • @landroni 谢谢,我添加了一种指定长度的方法,但它不是很好。我只会使用类似 `rand=$(head -c 100 /dev/urandom | tr -dc A-Za-z0-9 | head -c13)` 之类的东西。 (2认同)

小智 12

使用xxd命令指定长度(通过 -l),这在 Linux 和 OS 中都有效。 https://www.howtoforge.com/linux-xxd-command/

xxd -l16 -ps /dev/urandom
Run Code Online (Sandbox Code Playgroud)


San*_*urg 8

APG 在某些 Linux 发行版中默认包含。

要在子集 Special、Numeric、Capital 和 Lower 中生成大小从 5 到 10 的密码,命令是:

apg -MSNCL -m 5 -x 10
Run Code Online (Sandbox Code Playgroud)

并返回

@OpVeyhym9
3:Glul
3DroomIc?
hed&Os0
NefIj%Ob3
35Quok}
Run Code Online (Sandbox Code Playgroud)

正如@landroni 在评论中所说。


dub*_*jim 6

@Brandin 在对另一个答案的评论中解释了如何从/dev/urandom使用head -c 100. 另一种方法是使用dd

tr -dc A-Za-z0-9 < /dev/urandom | dd bs=100 count=1 2>/dev/null
Run Code Online (Sandbox Code Playgroud)

2>/dev/null在年底dd的命令是抑制“......在/ ...记录记载了”输出。

我不知道这两种方法之间有什么实质性的优点/缺点。

我对两种tr抱怨输入的方法都有问题。我认为这是因为它不喜欢接收二进制输入,因此建议首先/dev/random使用iconv -c -t US. 然而,吉尔斯提出了不同的诊断和解决方案,这对我有用:

LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | dd bs=100 count=1 2>/dev/null
Run Code Online (Sandbox Code Playgroud)


小智 5

您可以使用md5具有此目的的工具之一。在创建完全随机密码的情况下,您可以使用md5pass. 这是一个使用起来非常简单且非常有用的工具,因为您可以将“普通文本”与“盐”一起使用来跳转位构造相同的密码,然后您可以恢复,或者您可能想要获得一个完整的密码一直是随机密码。一般用法是:

md5pass [password] [salt]
Run Code Online (Sandbox Code Playgroud)

其中password是将用于构建随机字符串的选定单词,并且salt是要使用的字节跳转。像这样:

md5pass word

$1$.MUittVW$j.XDTF1QRnxqFdXRUiSLs0
Run Code Online (Sandbox Code Playgroud)

这将创建一个“随机序列”密码供您使用。如果您使用 no salt,则之后您可能无法重新创建相同的字符串。

但是,如果您使用salt这样的:

md5pass word 512

$1$512$.0jcLPQ83jgszaPT8xzds0
Run Code Online (Sandbox Code Playgroud)

然后您可以创建一个序列,如果您将单词与最初定义的相同盐(或跳转)结合使用,则可以恢复该序列。


小智 5

这两个命令分别生成随机密码和密码短语。

shuf --random-source=/dev/urandom --repeat --head-count=20 file_with_characters | tr --delete '\n'

shuf --random-source=/dev/urandom --repeat --head-count=7 file_with_words | tr '\n' ' '
Run Code Online (Sandbox Code Playgroud)

密码生成器需要一个 file_with_characters ,其中包含您希望密码使用的所有字符,每行一个字符,并且每个字符恰好一次。文件不得包含空行,并且行必须以换行符终止。

密码短语生成器需要一个 file_with_words ,其中包含您希望密码短语使用的所有单词,每行一个单词,并且每个单词恰好一次。文件不得包含空行,并且行必须以换行符终止。

--head-count 选项指定密码的长度(以字符为单位)或密码短语(以单词为单位)。


小智 5

我发现在 macOS 上通过管道 /dev/urandom 到 tr 不起作用。这是另一种方法:

set="abcdefghijklmonpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
n=6
rand=""
for i in `seq 1 $n`; do
    char=${set:$RANDOM % ${#set}:1}
    rand+=$char
done
echo $rand
Run Code Online (Sandbox Code Playgroud)


Iir*_*ayn 5

我用:

base64 < /dev/urandom | tr -d 'O0Il1+/' | head -c 44; printf '\n'

这给了我 57 个可能的字符。字符串可以复制粘贴(删除+和``)或打印并重新键入,因为难以区分的字符 ( I1lO0) 已被删除。

  • 44 个字符给了我:log 2 (57 44 ) > 256.64 位熵
  • 22 个字符给了我:log 2 (57 22 ) > 128.32 位熵

我喜欢这个因为:

  • 该命令易于输入且易于记忆
  • 它使用标准系统工具 - 没有额外的二进制文件
  • 不会“浪费”太多随机性(使用它接收到的随机位的 89%,而对于直接管道到 tr 的解决方案使用 ~24%)
  • 22 和 44 个字符很好地配对(略高于偶数)两个断点的公共幂
  • 可以轻松选择和粘贴或打印和重新输入输出,并将人为错误率降至最低
  • 比十六进制编码(32 和 64 而不是 22 和 44)更短的解决方案,例如 md5sum/sha1sum 等。

归功于https://unix.stackexchange.com/a/230676/9583,尤其是我最初灵感的评论。