随机密码生成器Bash

Jer*_*emy 7 passwords bash

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

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

这是我的代码:

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
Run Code Online (Sandbox Code Playgroud)

Joh*_*024 11

这保证了一个且只有一个特殊字符,以及至少一个数字,小写和大写字母.要在密码中随机放置这些字符,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 ""
Run Code Online (Sandbox Code Playgroud)

这个怎么运作

  1. 我们定义了一个便利功能:

    choose() { echo ${1:RANDOM%${#1}:1}; }
    
    Run Code Online (Sandbox Code Playgroud)

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

  2. 我们在每个所需类型的字符之一的每行打印一个字符:

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

    for i in $( seq 1 $(( 4 + RANDOM % 8 )) )
    do
        choose '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    done
    
    Run Code Online (Sandbox Code Playgroud)
  4. 从上面来看,特殊字符总是第一个,数字第二个,等等.我们需要随机化.我们这样做sort -R:

    sort -R | tr -d '\n'
    
    Run Code Online (Sandbox Code Playgroud)

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

起色

在评论中,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",$1}'
echo ""
Run Code Online (Sandbox Code Playgroud)

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

捕获变量的密码

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

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",$1}')"
Run Code Online (Sandbox Code Playgroud)

命令替换,表示为$(...),运行parens中的命令并捕获它们的标准输出.