如何生成随机字符串?


209

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

我可以使用哪些工具?

(出于安全和隐私方面的考虑,字符串最好是离线生成,而不是在网站上在线生成。)


1
AskUbuntu已经有了很好的答案。(我apg个人使用。)
Sparhawk

1
@Sparhawk AskUbuntu问题/解答更多关于列表工具。请考虑在此处添加答案,以展示如何使用apg其生成随机字符串。
landroni

1
在计算机上使用随机数生成时要谨慎。有些随机数远不如它们看起来的随机数,但是要区分“好”和“坏”随机数生成之间的区别是非常困难的。
Sobrique 2015年

@Sobrique关于伪随机数生成器(例如/dev/urandom)的出色观点。使用基于例如random.org的真正的随机数生成器来获得一些答案会很好。
landroni

25
笑话答案:要生成真正的随机字符串,请将新用户放在Emacs(或Vim)的前面,并要求他们退出。;)
通配符

Answers:


186

我最喜欢的方法是/dev/urandom与一起使用tr以删除不需要的字符。例如,仅获取数字和字母:

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

或者,要包含OWASP密码特殊字符列表中的更多字符,请执行以下操作:

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

如果您在tr抱怨输入方面遇到一些问题,请尝试LC_ALL=C像这样添加

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

15
或执行以下操作:head /dev/urandom | tr -dc A-Za-z0-9 | head -c10-这样更准确。您会获得10个大写,小写或数字字符
Brandin

8
第一条head命令可能有问题。它将输出来自的前10行/dev/urandom,这意味着一旦看到第10行,它将停止。因此,发送到tr命令的输出长度是随机的。的输出中少于13个字符的可能tr。我还没有计算出发生这种情况的可能性,计算有些棘手。
kasperd

6
最好这样做:<dev/urandom tr -dc "$charset" | head -c "$length"
PSkocik

3
+1这是快速尝试包含OWASP密码特殊字符页面中的其他字符,针对bash命令行进行了转义:tr -dc A-Za-z0-9\!\"#$\&\'\(\)\*+,-./\:\\\\\;\<=\>\?@[]^_`{\|}~
Rup

2
@Rup我不确定什么不适用于您的tr ..命令,而只是引用所有内容(单引号除外)都可以tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~'
肯尼·埃维特

144

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

pwgen生成随机的,无意义的但可发音的密码。这些密码仅包含小写字母,大写和小写字母混合或输入数字。大写字母和数字的放置方式便于在仅记忆单词时记住它们的位置。

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

geek@liv-inspiron:~$ pwgen 13 7
Eu7Teadiphaec giepahl3Oyaiy iecoo9Aetaib4 phaiChae6Eivi athoo3igee8Co
Iphu4ufeDeelo aesoYi2lie9he 

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

geek@liv-inspiron:~$ pwgen -s 13 7
eAfycrPlM4cYv 4MRXmZmyIVNBp D8y71iqjG7Zq7 FQRHcserl4R8O yRCUtPtV3dsqV
0vJpp2h0OrgF1 QTp7MKtJyTrjz 

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

该软件包生成明显的密码。它使用从提供的任何字典中获得的三字母组合(三边形)的统计信息。

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

geek@liv-inspiron:~$ gpw 7 13
sreepoidahsas
risadiestinge
ntodynesssine
deodstestress
natinglumperm
riasigentspir
enderiferback

21
+1表示不重新发明轮子。如果您不希望减少“可发音”约束的熵,只需使用pwgen -s
Nate Eldredge

122

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

openssl rand -base64 12

要么

openssl rand -hex 12

10
rand -hex会将输出限制为仅16个字符,而不是键盘上的90+。base64更好,因为它是64个字符,但不是随机的(例如,有可预见的填充模式,也许某些字符比其他字符更频繁地出现)。
马丁·图尔诺伊

@Carpetsmoker:请注意,该示例openssl rand -base64 12产生16个字符的输出(因为256个值映射到64个)。十六进制示例产生24个字符。十六进制的情况是没有损失的,因为它是一个简单的1:2映射,但在base64的情况下可能会有所损失,因为使用了填充。基数不影响随机性,这是一个映射到另一个的方式。(总位数非常重要)。
丹尼斯·威廉姆森

现在的问题是“如何产生特定长度的随机字符串” @DennisWilliamson,因此,尽管您的评论是正确的这样,这不是正确的在这个问题的背景下
马丁·图尔诺伊

@Carpetsmoker:在这种情况下,这个答案都没有。
丹尼斯·威廉姆森

4
这个答案值得更多的赞扬。urandom,pwgen,gpw等在您的系统上可能可用或不可用;同样在不同的环境中,适用于一个策略的策略可能不适用于另一个策略。如果没有openssl,那将是一个非常不正常的设置。更好:openssl rand -base64 32 | tr -d / = + | cut -c -16这将为您提供32个字符减去非字母数字,并修剪为16个字符长度。使其易于以管理员身份处理。用户只有字母数字(他们倾​​向于使用字母数字)。该长度足够长,以至于特殊字符的去除不会过度影响熵。金色的
zentechinc

18

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

cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 10 | head -n 1

1
+1这个答案是POSIXly正确的,/dev/urandom当然要减去使用
Harold Fischer

12

为了使用我在每个发行版中内置的标准Linux工具生成具有最大熵的密码,我使用:

< /dev/urandom tr -cd "[:print:]" | head -c 32; echo

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


1
这与现有答案有何不同?具体来说,赫伯特想到了。
Fox

3
@Fox他的解决方案使用硬编码的字符列表,由于代码的可读性,紧凑性和简洁性,因此不鼓励使用这种编程习惯。bash还能解释一些特殊的可打印ASCII字符,更不用说他的一个衬里最明显的缺点-如果需要最大的熵,可以确定所有可用字符都包含在列表中吗?而且没有重复可能改变tr的行为吗?自从您问起他的回答就应该由我代替:)
drws

2
许多(如果不是大多数)网站都对密码中的字符有限制,因此对我来说,硬编码'[:print:]'并不比硬编码OWASP密码特殊字符列表更好。我觉得几乎每个答案都可以通过使用变量来改善,但这是一个很小的更改,我只建议进行编辑
Fox

1
< /dev/urandom tr -cd '[:graph:]'| tr -d '\\' | head -c 32; echo如果您不想要` characters in generated string. `,因为在许多语言中都是转义字符会导致问题
mzzzzb,

< /dev/urandom tr -cd "[:print:]" | tr -d ' \\/\`\|' | head -c 32; echo排除| \ /`和空间
Ryan Krage

9

根据所需的随机性级别,您可以简单地使用bash的内置变量(zsh以及和ksh,可能还有其他$RANDOM变量):

$ echo $RANDOM | tr '[0-9]' '[a-z]'
bfeci
$ echo $RANDOM | tr '[0-9]' '[a-z]'
cijjj

直接读取的方法/dev/urandom要简单得多,但是为了完整起见,您还可以使用$RANDOM

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

重要提示:此解决方案仅使用字母的前10个字母生成随机字符串。对于您而言,这是否足够取决于您所需要的。


您如何控制生成的字符串的长度?
landroni 2015年

@landroni我认为除非长度合适,否则您不能缺少循环。$RANDOM将打印0和32767之间的数
terdon

我已经尝试运行该命令约20次,而我得到的任何信息都不能超过4-5个字符……
landroni 2015年

2
@landroni谢谢,我添加了一种指定长度的方法,但这不是很好。我只是用类似的东西rand=$(head -c 100 /dev/urandom | tr -dc A-Za-z0-9 | head -c13)
terdon

1
@SkippyleGrandGourou非常好。我将此添加到答案中,谢谢。
terdon

8

受Pablo Repetto的启发,我得出了一个易于记忆的解决方案:

shuf -zer -n20  {A..Z} {a..z} {0..9}

-z避免多行输出

-e回显结果

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

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

{A..Z} {a..z} {0..9}允许使用char类

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


5

@Brandin在注释中解释到另一个回答如何从获得最多100个字节/dev/urandom使用head -c 100。另一种方法是dd

tr -dc A-Za-z0-9 < /dev/urandom | dd bs=100 count=1 2>/dev/null

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

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

tr抱怨输入的两种方法都存在问题。我以为这是因为它不喜欢接受二进制输入,因此建议先过滤/dev/randomiconv -c -t US。但是,吉尔斯提出了另一种诊断和解决方案,对我有用:

LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | dd bs=100 count=1 2>/dev/null

出于某种原因,该iconv解决方案最大化了一个CPU内核,并且没有产生输出(我等了10
秒钟

在我的Ubuntu 14.04系统上,iconv由libc-bin2.19 提供。我不确定是否是相同的
图标

tr支持二进制输入。但是,类似的范围A-Z可能会受到区域设置的影响。试试LC_ALL=C tr …
Gilles

1
@Gilles根据POSIX规范,它不“支持二进制输入”。只有GNU tr支持,因为它根本不支持多字节(例如,上次我检查它的大小写更改是通过简单地设置每个字节的第六位来实现的)。其他系统(例如BSD)确实支持多字节,并且在那里失败,因为在大多数编码中,随机输入流也是有效的多字节流的机会很小。GNU 可能会在任何给定时刻添加多字节支持,这将失败。当然,设置LC_ALL=C可以解决该问题。
马丁·图尔诺伊

@Carpetsmoker POSIX确实需要tr处理二进制输入(在C语言环境中)。(好吧,好吧,它只是明确表示要支持空字节,并不是说要支持不以换行符结尾的非空文件,但实际上总是如此。)
Gilles 2016年

4

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

要生成“ Special”,“ Numeric”,“ Capital”和“ Lower”子集的大小为5到10的密码,命令为:

apg -MSNCL -m 5 -x 10

并返回

@OpVeyhym9
3:Glul
3DroomIc?
hed&Os0
NefIj%Ob3
35Quok}

正如@landroni在评论中所说。


1
以下是生成包含许多特殊字符的随机14个字母密码的选项:apg -a1 -m14
neuhaus

3

您可以使用md5具有此目的的工具之一。在创建完全随机的密码的情况下,您可以使用md5pass。这是一个非常简单易用的工具,对您很有帮助,因为您可以将“普通文本”与“盐”一起使用,以跳跃式构造相同的密码,然后在以后恢复该密码,或者,您可能希望获得一个完整的密码。始终提供随机密码。一般用法是:

md5pass [password] [salt]

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

md5pass word

$1$.MUittVW$j.XDTF1QRnxqFdXRUiSLs0

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

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

md5pass word 512

$1$512$.0jcLPQ83jgszaPT8xzds0

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


当使用a时salt,这听起来类似于PasswordMaker的方法...
landroni 2015年

-是的听起来可能类似于一个制造商的密码,但是区别在于它不是商业程序或其他任何东西,因为这里涉及的md5工具集“ md5pass,md5sum,md5sum.textutils”受关注并且对系统可用不花一分钱!
Joke S. OK OK

我实际上想到过PasswordMaker,它也是开源的且非商业性的。
landroni 2015年


2

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

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' ' '

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

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

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


1

我发现在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

检查我的答案的最后一个例子。它不使用tr。unix.stackexchange.com/a/494931/203075
Zibri

1

我用:

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

这给了我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,尤其是对我最初灵感的评论。


如果您需要数字/特殊字符-通常会有一个数字,如果不需要,您可以安全地追加1而不降低熵(生成一个新的数字以获得一个w / a的数字确实会降低熵)。您也可以安全地附加一个!而不降低熵。两种方案都不会增加熵的价值,但是会使生成的字符串符合较早的密码要求。
艾里达恩

1

在这种情况下,Unix的哲学“很多能做一件事情的小工具”可以很好地为您服务。

  • /dev/urandom随机 “字节”(包括不可打印的字符)的流
  • base64 将字节数据编码为 [A-Za-z0-9/+](可以完全打印)
  • dd 将输入复制到作为参数提供的应用修饰符的输出(可以包括块大小和块数)

OSX

base64     < /dev/urandom | dd bs=1k count=1

的Linux

base64 -w0 < /dev/urandom | dd bs=1k count=1

笔记:

  • 如果需要字符的子集,则可以在管道中插入修饰符。
    • 例如:tr -d '[A-Z/+]'摆脱大写字母+/
  • 您可以将bs(块大小)设置为所需的任何长度。
  • 在Linux上,base64默认情况下换行为76列,-w0除非需要,否则必须重新设置。

1

我想贡献我通常的命令来生成密码

$ cat /dev/urandom | base64 | head -n 1 |tr -dc '[:alnum:]' |cut -c -13
b0R55751vWW9V

要配置密码的长度,请将cut命令中的数字更改为所需的长度,例如24个字符

$ cat /dev/urandom | base64 | head -n 1 |tr -dc '[:alnum:]' |cut -c -24
WFBhVHuKbrnRhd5kdWXPzmZG

不想混淆0或O,1或l?用另一个过滤掉tr

$ cat /dev/urandom | base64 | head -n 1 |tr -dc '[:alnum:]' | tr -d '0O1l'|cut -c -24
JuCphwvhrhppD9wVqfpP2beG

我个人从不喜欢在密码中使用特殊字符,这就是为什么我只选择[:alnum:]密码生成器


0

secpwgen使用Alpine Linux进行维护并将源代码保存在我的Github中

它可以产生随机的字符串或骰子短语:

musl64 [~]$ secpwgen
USAGE: secpwgen <-p[e] | -A[adhsy] | -r | -s[e]> N

PASSPHRASE of N words from Diceware dictionary
  -p    generate passphrase
  -pe   generate enhanced (with symbols) passphrase

SKEY PASSWORD of N words from S/Key dictionary
  -s    generate passphrase
  -se   generate enhanced (with symbols) passphrase

ASCII RANDOM of N elements (at least one option MUST be present)
  -A    Each letter adds the following random elements in output:
    a    alphanumeric characters
    d    decimal digits
    h    hexadecimal digits
    s    special characters
    y    3-4 letter syllables

RAW RANDOM
  -r    output BASE64 encoded string of N random BITS
  -k    output koremutake encoding of N random BITS

要生成一个13个字符的随机字符串,您可以使用:

musl64 [~]$ secpwgen -Aas 13
----------------
WK5#*V<]M3<CU ;ENTROPY=67.21 bits
----------------
INFO: destroying random number generator.
INFO: zeroing memory.

musl64 [~]$ secpwgen -Aa 13
----------------
GP0FIEBM9Y3BT ;ENTROPY=67.21 bits
----------------
INFO: destroying random number generator.
INFO: zeroing memory.

为了使用户记住密码,请使用diceware短语:

musl64 [~]$ secpwgen -p 5
----------------
wq seen list n8 kerr  ;ENTROPY=65.00 bits
----------------
INFO: destroying random number generator.
INFO: zeroing memory.

我个人喜欢:

musl64 [~]$ secpwgen -r 512
----------------
h62lL7G4gwh3/j9c7YteQvVXoqJrQKKPWVR3Lt7az36DcfWZWtUgBT19iwmJBwP4UahNzPe7qYD7OcklUFpCzQ== ;ENTROPY=512.00 bits
----------------
INFO: destroying random number generator.
INFO: zeroing memory.

0

我使用非常安全的密码(其中pw长度为16)的方式:

cat /dev/urandom | tr -cd [:graph:]|head -c 16

结果示例:

jT@s_Nx]gH<wL~W}

或者,生成多个密码:

猫/ dev / urandom | tr -cd [:graph:] | fold -w 16 | head -6

结果示例:

7ck%G7'|f&}_8(]s
<?*]E.CG[NB'gK#A
:tF-WPTOa3!i7S(h
2xy(>=%3=Kb1B$`6
*98Lf{d?Jzb}6q1\
E7uCEAN2Hz]]y|5*

安全性稍差(字符集较小):

cat /dev/urandom |base64 -w 0|fold -w 16|head -6

结果示例:

rJqYxYZLOTV+A45w
PUKQ+BoBf6yfZw5m
+LRfpsN9CsLRiN8V
yMS6zDpL6NHmG17s
yTUWPG7Rum97schi
cognvjVwaKaAyPRK

-1

一种超级简单的方法(可能比您想要的简单)可以实现此目的,即生成给定范围内的随机数,将该数字转换为等效的ASCII字符,然后将其附加到字符串的末尾。

这是Python中的一个基本示例:

import random # import random library  
passFile = open("passwords.txt", 'w') # create file passwords.txt
passNum = int(input("Number of passwords: ")) # get number of  passwords
passLength = int(input("Password length: ")) # get length of passwords  
for i in range(passNum):
    password = "" # reset password
    for i in range(passLength):
        num = random.randint(65, 122) # get random number
        while num in range(91, 97): # Don't include punctuation
            num = random.randint(65, 122)
        password += chr(num) # add character to current password 
    passFile.write(password + "\n") # add current password to file  
passFile.close() # close file

编辑:添加注释,并添加代码以生成多个密码并将其写入文件


3
如果拥有Python的功能,我将不会以这种方式做到这一点。在包含所有对密码有效的字符的字符串上使用联接,并使用random来选择字符会容易得多。
Mike McMahon


-2

我想要以下命令:

date +%s | sha256sum | base64 | head -c 12

1
我宁愿使用更多的随机纳秒方法: date +%N 因为如果您在脚本中生成许多用户和密码,那么对于许多甚至所有日期命令而言,秒数都可能变为相同,从而生成相同的密码。
约翰·马约尔

1
@JohnMayor:是这样的做法更稳健:dd if=/dev/random bs=512 count=1
Eugen Konkov

8
这个答案非常危险!您可以从易于预测的已知种子生成密码。我可以生成最近几年使用此方法生成的所有密码,并将此列表用于暴力破解。
流量

-4

我可以访问 http://passwordsgenerator.net/, 它允许生成最多2048个字符的随机字符字符串,选择大写,小写,数字0到9,标点符号或任何组合。


2
我已经澄清了这个问题,以明确表明离线生成的字符串更可取。直接在网站上生成密码是不安全的,尤其是如果连接不是HTTPS(如您的回答)时。
landroni

1
从互联网上获取随机密码非常愚蠢和幼稚。现在,有人知道您用于某些服务或站点的密码以及有关您的唯一个人详细信息(IP地址,浏览器/环境信息)。现在,该站点可以将信息与收集到的有关您的其他数据进行交叉引用。例如,您曾经张贴到邮件列表,您的IP地址在邮件的标题中,因此我们现在有了密码,名称和电子邮件地址...您真的在这里信任随机陌生人的密码。
马丁·图尔诺伊
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.