随机密码生成器 Bash

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26665389/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 11:40:43  来源:igfitidea点击:

Random Password Generator Bash

bashpasswords

提问by Jeremy

I am trying to make a password generator that generates a password between 8-16 characters. It also has to contain a digit and lower and uppercase letters, as well as only one special character that is randomly placed in the string when being generated.

我正在尝试制作一个密码生成器,可以生成 8-16 个字符之间的密码。它还必须包含一个数字和大小写字母,以及在生成时随机放置在字符串中的一个特殊字符。

At the moment, my code will sometimes give me a password that does not meet the requirements eg. AOKOKKK@1(no lowercase letters) In addition, I also need help to make it so that the special symbol only appears once in the password. How can I fix this?

目前,我的代码有时会给我一个不符合要求的密码,例如。AOKOKKK@1(没有小写字母)此外,我还需要帮助使特殊符号在密码中只出现一次。我怎样才能解决这个问题?

Here's my code:

这是我的代码:

length=$[ 8 +$[RANDOM % 16]]

char=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ! @ \# $ % ^ \&)

max=${#char[*]}
for ((i = 1; i <= $length ; i++))do

let rand=${RANDOM}%${max}
password="${password}${char[$rand]}"
done
echo $password

回答by John1024

This guarantees one and only one special characters, as well as at least one of digits, lower case, and upper case. To place those characters randomly within the password, sort -Ris used to scramble the order of characters before the password is printed:

这保证了一个且只有一个特殊字符,以及数字、小写和大写中的至少一个。将这些字符随机放置在密码中,sort -R用于在打印密码之前打乱字符的顺序:

#!/bin/bash
choose() { echo ${1:RANDOM%${#1}:1}; }

{
    choose '!@#$%^\&'
    choose '0123456789'
    choose 'abcdefghijklmnopqrstuvwxyz'
    choose 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    for i in $( seq 1 $(( 4 + RANDOM % 8 )) )
    do
        choose '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    done
} | sort -R | tr -d '\n'
echo ""

How it works

这个怎么运作

  1. We define a convenience function:

    choose() { echo ${1:RANDOM%${#1}:1}; }
    

    choosetakes one argument, a string, and randomly selects a character from that string.

  2. We print one character per line of one of each of the required types of characters:

    choose '!@#$%^\&'
    choose '0123456789'
    choose 'abcdefghijklmnopqrstuvwxyz'
    choose 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    
  3. We print the remaining number of characters needed, one character per line. These characters are selected randomly from digits, lower case, and upper case:

    for i in $( seq 1 $(( 4 + RANDOM % 8 )) )
    do
        choose '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    done
    
  4. From the above, the special character is always first and the digit second, etc. We need to randomize. We do that with sort -R:

    sort -R | tr -d '\n'
    

    tr -d '\n'serves to removes the newlines from between the characters, resulting in a string of characters on one line.

  1. 我们定义了一个便利函数:

    choose() { echo ${1:RANDOM%${#1}:1}; }
    

    choose接受一个参数,一个字符串,并从该字符串中随机选择一个字符。

  2. 我们每行打印一个字符,每个字符类型中的每一种:

    choose '!@#$%^\&'
    choose '0123456789'
    choose 'abcdefghijklmnopqrstuvwxyz'
    choose 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    
  3. 我们打印所需的剩余字符数,每行一个字符。这些字符是从数字、小写和大写中随机选择的:

    for i in $( seq 1 $(( 4 + RANDOM % 8 )) )
    do
        choose '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    done
    
  4. 由上可知,特殊字符总是排在第一位,数字排在第二位,依此类推,我们需要随机化。我们这样做sort -R

    sort -R | tr -d '\n'
    

    tr -d '\n'用于删除字符之间的换行符,从而在一行中生成一串字符。

Improvement

改进

In the comments, JonathanLeffer shows that the output of sort -Ris not fully random. sort -Rsorts on a hash of each line. Apparently a random seed is added but each line receives the same seed. To get around this, the version below provides its own seed on each line. This is done by a change to the choosefunction. At the end, awkis used to remove those numbers and display the complete password:

在评论中,JonathanLeffer 表明 的输出sort -R不是完全随机的。 sort -R对每一行的散列进行排序。显然添加了一个随机种子,但每行接收相同的种子。为了解决这个问题,下面的版本在每一行都提供了自己的种子。这是通过更改choose函数来完成的。最后,awk用于删除这些数字并显示完整的密码:

#!/bin/bash
choose() { echo ${1:RANDOM%${#1}:1} $RANDOM; }

{
    choose '!@#$%^\&'
    choose '0123456789'
    choose 'abcdefghijklmnopqrstuvwxyz'
    choose 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    for i in $( seq 1 $(( 4 + RANDOM % 8 )) )
    do
        choose '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    done

} | sort -R | awk '{printf "%s",}'
echo ""

In awk, each line is divided into fields. The first field is the randomly chosen letter while the second is the random number that we added to seed the hash. The statement printf "%s",$1prints the first field (with no trailing whitespace) and ignores the second field. The end result is the password that we want.

在 中awk,每行都分为字段。第一个字段是随机选择的字母,而第二个字段是我们添加的随机数以播种散列。该语句printf "%s",$1打印第一个字段(没有尾随空格)并忽略第二个字段。最终结果是我们想要的密码。

Capturing the password to a variable

将密码捕获到变量

To capture the output to a variable, we use command substitution:

要将输出捕获到变量,我们使用命令替换

choose() { echo ${1:RANDOM%${#1}:1} $RANDOM; }
pass="$({ choose '!@#$%^\&'
  choose '0123456789'
  choose 'abcdefghijklmnopqrstuvwxyz'
  choose 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  for i in $( seq 1 $(( 4 + RANDOM % 8 )) )
     do
        choose '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
     done
 } | sort -R | awk '{printf "%s",}')"

Command substitution, denoted by $(...), runs the commands in the parens and captures their stdout.

用 表示的命令替换$(...)运行括号中的命令并捕获它们的标准输出。

回答by whereswalden

pwgenis installed on some linux distros (notably Ubuntu) by default and has a windows version as well. Why not use that?

pwgen默认安装在一些 linux 发行版(特别是 Ubuntu)上,并且也有 Windows 版本。为什么不使用它?

回答by angdev

#!/bin/bash

#Password Generator Script

echo "Password Generator Script"
read -p "Enter the password lenght: " PASS_LENGTH
for VAR in $(seq 1 3); #how many times password will generate, you can set range
do
    openssl rand -base64 48 | cut -c1-$PASS_LENGTH
    #-base64(Encode) 48 is length 
    #cut is for user input column -c1 is column1
done