LoginSignup
14
12

More than 3 years have passed since last update.

bashによるランダム文字列の生成【パスワード生成スクリプト追加】

Last updated at Posted at 2014-12-02

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!

パスワード生成シェルスクリプト

今までのランダム文字列生成ルールで、パスワード文字列を生成するシェルスクリプトを作成しました。

mkpasswd.sh
#!/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アナリティクスでモニタできるように設定したら、何気にこのページの参照が多かったです。
そして内容をよくよく確認するとバグなどが、多々あったので修正しました。
あと、スクリプトの修正と、重複なしのパスワードリストの作成方法の追記をしました。

14
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12