gallu’s blog

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

技術メモ:認証変

認証系を作り直しているので、備忘録兼ねて。


とりあえず
・パスワードの持ち方を変えつつ
・セッションIDにmcryptを使わないように
してみやう。…いやmcryptは捨てがたいのだが(苦笑)、オプションとして。


・パスワードの持ち方
以前はsha1でハッシュしていたのですが(何がしかの暗号ロジックを使うことも考えたのですが。… http://d.hatena.ne.jp/gallu/20060731/p3 うわぁ2006年って何年前よw)
ちょいと「一意じゃないお塩で味付け」しつつ「柔軟体操」をしてみようか、と。


・・明日に向かってその1:お塩
ソルト(salt)っていいますねぇ普通。
対象文字列の前後どっちかに(普通前かなぁ? あんまり後ろって見ないような…なんで?)、いらん文字列を付けます。この文字列が「お塩」。
うちでは「ユーザさんは固有のID持ってる」んで(普通そうか)、ユーザIDをお塩につかいます。
お塩で味付けをすると
→レインボーアタックが出来ない http://d.hatena.ne.jp/gallu/20071211/p1
というメリットがあり、またユーザごとに違うお塩にすると
→「同一パスワード」でも出力(保存される文字列)が異なるので、より推測がしにくい
なんてメリットもあります。


・・明日に向かってその2:柔軟体操
ストレッチいいます。上述の「お塩大作戦」だと、いわゆる「ブルートフォース(Brute Force:総当り/力ずく)」な攻撃には無力です。
なので、ストレッチっていう方法を使って「クラック時間を少し延ばします」。あくまで「少し延ばすだけ」なので、そんなに過信されてもまぁ困るのですが。
参考は…わかりやすいあたりですとこちら。
〜 ハワイより 〜 Mikeのプログラミング・メモ
http://blog.makotoishida.com/2011/03/blog-post.html
頑張って英文読むなら(…頑張らずに読めるようになりたいっていうかまず「ちゃんと読める」ようになりたい orz )
Key stretching
http://en.wikipedia.org/wiki/Key_strengthening


んで…ざっくりググってみたのですが…数千回程度から数万回程度まで、ちょいと幅がある感じですねぇ…どしよ?
とりあえずMagicWeaponでは、きりよく「65536」という数値にしてみます。…でも、ふつ〜のサーバでこれやって、150ms程度で処理がおわる orz 10倍くらいにしたほうがよいのかしらん?
ちょっとデフォルトの数値については、もう少し悩んでみまふ。


とまぁこんな思考過程を経て、「DBに保存するパスワード文字列」は、概ねこんな感じになります。
コードっぽい書き方してますが限りなく「嘘言語」なので、適当に脳内で補完してください。
なお、事前に、idとpassを、文字列で入手していると仮定します。
注:ストレッチ回数を微妙に「ぶらしている」理由は。記憶が定かではない「ストレッチ回数もユーザごとに可変なほうがより好ましいって誰かが言ってたような気がする」的記憶によります。理由が定かではないので削除ってもよいのですが、とりあえず書いてみると、是非のどちらに拠らず、なにか突っ込んでいただけるんじゃかなろうか、的な甘くて淡い期待を元に、残しておきます(笑

stretching_num = ( hash_md5(id) % 0xff ) + config(stretching_num, default:65536);

loop stretching_num
 pass = hash_sha512(id + pass);
pool

hashed_pass = pass;


後は、ここで書く内容でもないのですが「パスワード固定、IDをぶん回す系総当り攻撃」用のギミックも用意しておきたいなぁ、っと。
アラート鳴るだけでもなにか違うっしょ。たぶん。


おちゅぎ。セッションID。
セッションIDのベースになるのは、MagicWeaponの中にある「トークナイザ」ってやつです。
この子は
・現在のエポック秒
・現在のミリ秒
・現在のプロセスID
・乱数
から、概ね「一意な文字列」を作り出します。その気になると「自分のIP」も足せるので、並列させてもまずもって一意なんじゃなかろうか、と。
推測不能性については概ね「乱数」部分に頼ってる気がするので、今度この辺を「暗号学的に安全性の高い擬似乱数」に差し替える予定です。
…いつにしよう?


で。
いやまぁトークン自身が丈夫ならそれでいい気もするのですが、現在は
・セッションID(の前後にソルトぶち込んだ文字列)を暗号化(具体的にはRijndael 256)した文字列
を使ってます。
これだと、まず「Rijndael 256の解析コスト」があるので&セッションIDのデフォルト寿命が10分なので、比較的安全性は担保されるんじゃなかろうか、と。少し重いけど。


ただまぁ、PHPだとmcryptライブラリいれなきゃいけなくて、その辺で微妙に不評だったりもしたので。
ちと考えているのが
・セッションIDのベース(トークン)をsha512でハッシュした文字列
にしようかなぁ、とかも考えてます。
うちのトークナイザのトークンは多分レインボーテーブルには入れにくいのですが、一応「お塩&ストレッチ」は「オプション的に考慮」してみようかなぁ、とかなんとか。


こっちもなんか「ブルートフォース系」への対策をしておきたいような気がするのですが…DDoSまでを視野に入れたときに…どうしようかなぁ? と。
とりあえず「いい手があったらやる」程度に備忘録。


まぁ基本的に「ガチャコン構成(気に食わなかったら、インタフェースあわせた「別クラス」に差し替えられる構成)」にするつもりなので。
「まずいってわかったらその時点で改修すりゃいいや」的に楽観視はしているのですが。
# きっと親切な おもひかね が突っ込んでくれるって信じてる。


以上、明らかにメモ(笑