質問: ログインシステムについて質問があります。 パスワードを暗号化ではなくハッシュ関数を使い符号化する安全性と使い方はわかりました。 またそれに文字を足して何回か行う、ということもわかりました。(ソルトとストレッチングのことです) そこで質問があります。 1. SHA256を使おうと思っているのですが、ハッシュ化という行為は元に戻せないということでした。いずれ新しいタイプのハッシュを使おうと思った際に、どのようにシステムを移行させればよいのでしょうか。あるいはどのようにSHA1などからの移行を果たしましたか? 2. もちろんSSL通信化での送信になりますが、パスワードを送信する際は符号化して送信するべきだと思うのです。しかし符号化すると元へは戻せません。この場合サーバーと同じ処理をjsで書いてしまうとロジックの公開になり安全性が保てないような気がしています。そこで公開鍵と秘密鍵を使ったもので暗号化しようと思い立ちましたが、あまりにコストが高い気がしています。皆さんはこのようなところはどのように解決なされているのでしょうか。 以上二点、宜しくお願いします。
回答: ハッシュアルゴリズムを切り替える方法 1. DBのユーザー情報を保存しているテーブルにハッシュアルゴリズムを保存するカラムを追加します。すべてのユーザーに旧アルゴリズムを表す値を入れておくか、NULであれば旧アルゴリズムと見なす、とします。 2. ユーザー認証時は、このカラムの値を見てアルゴリズムを選択します。 3. パスワード変更時は新アルゴリズムを用いてハッシュ値を計算し、ハッシュ値をDBに保存するのと同時にアルゴリズム示す値も更新します。 4. ハッシュアルゴリズムの更新を強制したい場合は、「旧アルゴリズムになっているユーザーはログイン後パスワードを強制する」という動作にすればよいでしょう。 このユーザー毎にハッシュアルゴリズムを記録しておく、というのは古くから行われているオーソドックスな方法です。 パスワードを送信する方法 一般的な用途ではSSLで経路が暗号化されているのであれば、その区間は安全と見なしてかまいません。これが信頼できないなら通信のすべてを別途暗号化する必要があります。 認証強度を高めるのが目的であれば、二要素認証のようなパスワード認証を補強する方法や、ワンタイムパスワード、ユーザー証明書による認証など別の方法を検討するほうが理にかなっています。 > > サーバーと同じ処理をjsで書いてしまうとロジックの公開になり安全性が保てない > > > これは2つの点で間違っています。まず、ロジックの公開はセキュリティ上の懸念にはなりません。ロジック、ハッシュ値、salt、ストレッチ回数のすべてが漏洩したとしても、元のパスワードを求めることは非常に困難です。それこそがパスワードをハッシュ値で保存する目的だからです。 安全性が保てないという点は間違いではありませんが理由が間違っています。クライアント側でハッシュ値を計算して送付するのは、盗聴対策であれば全く意味がありません。第三者がハッシュ値を入手した場合、そのハッシュ値を用いて認証できてしまうからです。 どうしても生のパスワードをネットワーク上に送出したくない場合は、暗号化やfumiyasさんの回答で紹介されているようなチャレンジレスポンス認証のような仕組みの検討が必要です。そこまでのセキュリティレベルが要求されるシステムなのであれば、専門家にコンサルティングしてもらうことをお勧めします。 SHA2を用いたパスワードの保存に計算量上の弱点があり、思ったよりもかなり多い数のstretchingが必要なのは事実です。大量の計算資源を用いたブルートフォースアタックに対する高度な耐性が求められるのであれば、別のアルゴリズムの検討が必要かも知れません。 一方、SHA2には選定段階にも実運用に入ってからも微に入り細を穿つ研究が行われた上で致命的な欠陥は見つけられていない非常に信頼性の高いアルゴリズムです。 新しいアルゴリズムは古いものを研究した上で作られるので優れた点は多々ありますが、(特にセキュリティ分野では)古いからこその信頼性が存在するのも事実です。アルゴリズムそのものに問題は無くても実装に問題があると言う場合もあります。 どういうアルゴリズムを選択すべきかはこういった点も考慮して検討してください。