bashを使ったランダム文字列の生成
既に、投稿されているような気もするのですが、取りあえず投稿します。
単純にランダムな文字列を生成するのではなく、
- 生成する文字列は英数字だけではなく、記号を必ず入れる。
- 紛らわしい文字は除外する。
という、内容で考えてみました。
パスワード用にランダムな文字列が欲しい時などの場合、コマンドラインに下記のように入力して実行します。
出力されるランダムな文字列は "12345678"
の数字と、",.+-!"
の記号を必ず含み、間違い易い "0,9(数字の0,9)"
、"O(英字大文字のO)"
、"l,o(英字小文字のl,o)"
を除いています。
$ cat /dev/urandom | \
tr -dc '12345678abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ,.+\-!' | \
fold -w 12 | grep -E '[12345678]' | grep -E '[,\.+\-\!]' | head -n 8
これで 12ケタのランダム文字列を 8個作成します。実行結果は下記のようになります。
+PsPBAIf26u2
D!jd5gXnNqcc
jXW,qmCvE5DY
,Jnk6n1brTQR
Q5XSR!ahdzJu
T57sPc5TnJD,
,tgc!H6jPUFI
.v,-TD.GvJw6
先頭に記号が来るのを、避けたかったので下記のように修正しました。
$ cat /dev/urandom | \
tr -dc '12345678abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ,.+\-!' | \
fold -w 12 | grep -E '[12345678]' | grep -E '[,\.+\-\!]' | \
grep -E '^[12345678abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ]' | \
head -n 8
実行結果は下記のようになります。
b.zp+G.26F7w
3UPCySe2D.ui
ZVe6-.DBwTYg
ZxV,wVXLyb3U
MI2SyF.xcpfY
YyXNQ.Byk!q2
d3SkMfVyxKm.
gU5pAfx!.5E!
パスワード生成シェルスクリプト
今までのランダム文字列生成ルールで、パスワード文字列を生成するシェルスクリプトを作成しました。
#!/bin/bash
LEN=$1
CNT=$2
if [ -z ${LEN} ] ; then LEN=12 ; fi
if [ -z ${CNT} ] ; then CNT=16 ; fi
cat /dev/urandom | \
tr -dc '12345678abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ,.+!\-' | \
fold -w ${LEN} | grep -E '[12345678]' | grep -E '[,\.+\-\!]' | \
grep -E '^[12345678abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ]' | \
head -n ${CNT}
こののシェルスクリプトの場合、引数としてパスワードの長さと出力数を与えることが可能で、
引数が無い場合は、ディフォルトで12桁のパスワードを16個作成するようにしています。
このシェルスクリプトを ASUS Chromebook Flip C101PA の Linuxターミナルで、16桁のパスワードを10,000件生成したときの実行結果は下記になります。(timeコマンドの戻り値がおかしいような気がしますが。。。)体感的には一瞬で生成されました。
$ time ./mkpasswd.sh 16 10000 > passwd_list.txt
real 0m0.133s
user 0m0.221s
sys 0m0.159s
生成したパスワードの検証。
$ wc -l passwd_list.txt
10000 passwd_list.txt
件数は問題なし。
$ sort passwd_list.txt | uniq -c | sort -r | head
1 z,ZX7DXCcnsBSh86
1 ZzvPpS!Hm4aSCpDU
1 zzmvEfGTbNV!3Kug
1 ZZMtzuhX-1xt,qN+
1 zzkjzXJH5-Zvn.HI
1 zzctpetS!4yFP5,W
1 ZZ+C!3vJWEEuV8y!
1 zZav7D7sv!CGSmCj
1 zz8hNaX+6BPGZ2Xx
1 Z,Z8BQHJMf,2qDug
uniqコマンドで重複数をカウント、sort -r
で降順にソートして、先頭10行のすべてが 1件のみだけだったので重複なし。
$ grep -E '^,' passwd_list.txt | wc -l
0
$ grep -E '^\.' passwd_list.txt | wc -l
0
$ grep -E '^\+' passwd_list.txt | wc -l
0
$ grep -E '^\-' passwd_list.txt | wc -l
0
$ grep -E '^\!' passwd_list.txt | wc -l
0
先頭に記号があるパスワードもなし。
重複したパスワード文字列を除きたい場合
重複については、特に制限していないので重複した文字列を除く場合は、下記にようにすれば生成可能です。
$ ./mkpasswd.sh 16 10000 | \
uniq -c | sort -r | \
awk '$1== "1" { print $2 }' | sort -R > passwd_list.txt
aws コマンドで、重複していない文字列を抽出して sort -R
でランダムにソートしてファイルに出力しています。
2019.05.01 修正について
QiitaをGoogleアナリティクスでモニタできるように設定したら、何気にこのページの参照が多かったです。
そして内容をよくよく確認するとバグなどが、多々あったので修正しました。
あと、スクリプトの修正と、重複なしのパスワードリストの作成方法の追記をしました。