Haskell でパスワードを作る
最近ネットのサービスを利用することが多くなったが、そこで一番困るのはパスワードをどうするかだ。ひとつのパスワードを使いまわすのは危険だし、かといって、ランダムなパスワードを考えるのは大変だ。そこでパスワードを Haskell で作れないか考えてみた。System.Random のインポート
ソースファイルを作るのが面倒臭かったので ghci で対話的に作ってみた。まず、乱数を使うので System.Random モジュールをインポートする。
Prelude> :m System.Random Prelude System.Random>
文字セットの作成
パスワードに使用する文字のリスト chars を作成した。英小文字、英大文字、数字からなっている。
Prelude System.Random> let chars = ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9']
Prelude System.Random> chars
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
このリストのどの文字を使用するかは、chars に添字を指定してやればいい。
Prelude System.Random> chars !! 5 'f'chars に含まれる文字数を調べるのには length 関数を使えばいい。
Prelude System.Random> length chars 62
乱数のシードを作る
System.Random モジュールで乱数を発生するためにはシードとなる StdGen 型のデータが必要だ。これは mkStdGen 関数で作成できる。mkStdGen 関数は Int を引数に取り StdGen 型の乱数のシードを作る。
Prelude System.Random> let seed = mkStdGen 7 Prelude System.Random> seed 8 1
0 .. 61 までの数の乱数のリストを作るには randomRs 関数を使う。randomRs 関数の引数は整数の範囲を示すペア (0, 61) と乱数のシードだ。発生する乱数リストは無限リストなので、take 関数で適当に切り取る。
Prelude System.Random> take 5 $ randomRs (0, 61) seed [25,12,33,38,20]
この乱数のリストの数字を添字に chars の文字を取り出せば、目指すパスワードが作れるはずだ。
Prelude System.Random> take 8 $ map (chars !!) $ randomRs (0, 61) seed "zmHMuJ2n"
このパスワードは mkStdGen の引数 7 から簡単に取り出せるので覚えやすいが、破られやすい。その場合は、乱数リストの先頭の何文字かを読み捨てて取り出せばいい。
Prelude System.Random> take 8 $ drop 66 $ map (chars !!) $ randomRs (0, 61) seed "XCUb6yu5"
久しぶりに Haskell でプログラムを作ったが、小さいプログラムを Haskell で作るのはやっぱり楽しい。