Haskell プログラム集


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 で作るのはやっぱり楽しい。