パスワード文字列を生成できるコマンドラインツールを Golang で書き初めした

この記事は書かれてから1年以上が経過しており、最新の情報とは異なる可能性があります

あけましておめでとうございます。

書き初めとして書きました。

もともと1日かからない程度のものを書き初めとして書きたかったので、大きくずれはなかったです。

パスワード文字列を生成できるコマンドラインツール

まず先にやってないこととして、

  • パスワードの強度チェック

これを挙げておきます。

パスワード文字列を生成するにあたって、 当然セキュリティは一定担保する必要があったのですが、 かといってこの辺のパスワードの強度チェックをゼロから独自に研究するのは 無理がある&仮に出来たとしても圧倒的に時間が足らないので、 外部のライブラリを利用しています。

パスワードの強度としては、例えば以下のようなケースが考えられます。

  • 連続した同じ文字列 (777 など)
  • 連続した順序を持った文字列 (abc など)
  • よくある英単語と一致する文字列その逆順
  • キーボード上の順序を持った文字列 (qwerty など)

こういったチェックは学問、アルゴリズムの話になってきてしまい、個人では追いきれないため、 zxcvbn というライブラリを利用させてもらってます。

https://github.com/dropbox/zxcvbn

提供しているのは Dropbox 社のようですが、 MIT ライセンスで誰でも利用できるようになっています。

実際のところ、上記の JavaScript 実装では新規アカウントを作るフォーム画面中において、 クライアントサイドでのパスワード強度チェックに用いられているようですね。

今回はそちらの Golang 実装を利用します。

https://github.com/nbutton23/zxcvbn-go

なお、ライブラリのページを見てもらえれば分かる話なのですが、 **クラックされるまでのおおよその時間(crack_times_display)**や パスワード強度の5段階評価(score: 0 - 4) などの情報を利用することが出来ます。

アルゴリズムなどを追ってみるのも面白いかもしれませんね。

今回の目的、目標

目的としてはこんな感じです。

  • 新年、ブログに目標書くくらいなら 先に作るべき
  • Web 経由である必要がないもの
  • GUI である必要がないもの

1password を利用しているので、フォーム入力時には強度のあるパスワードが生成できるのですが、 そういった画面も何もないところでパスワードだけ生成したい場合に、 コマンドをちょっと入力するだけですぐ生成できると便利そう です。

その割には、毎回欲しいと思ったときに外部の Web サービスを利用しており、 ブックマークの整理をしている際に、 『これ Web じゃなくていいよなあ、 GUI じゃなくていいよなあ』 と思っていたところでした。

昨年の Golang で DB が簡単に扱える自作コマンドを作ってみた で、Golang で自作コマンドはすでに作っていたので、 今回も同様に(素早く)作ってみようと思います。

各種オプションと初期値

基本的にマニュアル読めば全部書いてあるのですが、 パスワードの桁数は最低8文字ないと、パスワード強度のスコア的にセキュリティが確保できません。 (文字種が少ない、文字数が少ないなどのケースではスコアが 4 にならない)

逆に、桁数が多すぎたとしても今度は各種強度チェックに時間がかかってきてしまいます。

なので、 最小8文字、最大128文字、初期値を10文字 とすることにしました。

また、文字種を以下のもので定義しました。

  • 数値(digit: 0-9)
  • アルファベット大文字(alphabetlarge: A-Z)
  • アルファベット小文字(alphabetsmall: a-z)
  • アンダースコア(underscore: _)
  • 特殊記号(special characters: 制御文字など表示できない文字を除いたもの)

よく使うのは数値、アルファベット大文字・小文字の文字種だと思うので、 これらをオプションなしで true になるように、 それ以外のものはオプション付きで明示することで true にできるようにしました。

表示個数ですが、個人的にはパッといくつか表示したうえで 最終的に自分で選んで利用したいので、 10個ほど初期で表示しつつ、個数の指定も上書きできるようにしました。

あとこれ一番大事ですが、自分でキーボード打つのが面倒にならないようにするため、 コマンド名は一番分かりやすく pw で、 なおかつ オプションを一切何もつけない状態 = 一番自分の利用しやすい設定 となるようにオプションもろもろ考えました。

作ってみた感想

  • package unicode の存在
  • ランダム性を含むユニットテストについて

さっき気づいたのですが、 unicode というパッケージがあって ASCII 周りも定義されてるっぽいので 独自で定義せずにこの辺に乗っかっておくとひょっとすると楽出来たのでしょうか? 後で調べてみることにします。

あと、ランダムに生成する系のものって毎回テストのやり方に悩みますね・・・。

今回のケースだと、例えば実際にパスワード生成を行う関数とかがそうですかね。 文字数の長さと、構成文字以外の文字が入っていないかのチェックくらいですかねえ、うーん。

まとめ

やろうと思ってから実際に出来るところまでが早い Golang は好きです。

やらなきゃと思ったことをすぐに行動に移せるようになりたいですね。 そういう意味でも、実際に書き初めする行動まで移せたことは幸先が良いと思います。 2017年頑張ります。

参考URL

この記事は書かれてから1年以上が経過しており、最新の情報とは異なる可能性があります

もし記事内に誤りなどございましたら、 @girigiribauer @girigiribauer.com までご一報いただけると助かります。

Related articles