下記の記事を見て、改めてパスワード保存の安全性について勉強しようと思ったので、簡潔にまとめます。
【bcrypt】ユーザーパスワードを本当に安全に保存する方法
##パスワード保存の安全性確保について
1. パスワードのハッシュ化
パスワードを何の加工もせずにデータベースに保管するのは、非常に危険なので、ハッシュ関数で違う文字列に変更して保存します。
ここで言うハッシュ関数とは、
・ 暗号化すると元に戻せない変換
・ 同じ値を関数に通すと同じハッシュ値が得られる
・ 称号する時は、この結果の値を照合する
という性質を持っています。
2. ソルトの追加
ハッシュ関数は、 同じ値を関数に通すと同じハッシュ値が得られるという性質を持っています。
ということは、総当たり攻撃で時間をかければ同じハッシュ値が得られ、元のパスワードを見つけ出せる可能性があります。
パスワードを十分長くしておけば、元のパスワードの算出に時間がかかるため耐える事が可能ですが、全てのユーザーに非常に長いパスワードを入力させる事は現実的ではありません。
そこで、ソルトと呼ばれるランダムな文字列をユーザーが入力したパスワードにくっ付けて暗号化します。こうする事で、十分長いパスワードを保証する事が出来、解読される可能性を低くする事が出来ます。
3. ストレッチング
ソルトを付与して暗号化したとは言っても攻撃側が膨大な時間をかければ、解読される可能性はあります。
なので、ハッシュ関数を数千回通して、非常に複雑で解読に時間をかけせる嫌がらせを行います。
これをストレッチングといいます。
bcrypt導入準備
これら3つを踏まえたbcryptoというアルゴリズムがあります。今回は、gemのbcryptoを使用しながら安全なパスワード保存を試してみましょう。
まず、Gemfileにbcryptを追加します。
gem 'bcrypt'
追加したらbundle install
bundle install
パスワード暗号化を試すためにUser modelを作ります。
パスワードを保存するカラムはpassword_digest
にして下さい。後で説明するメソッドの仕様で、password_digest
にしておく必要があります。
rails g model User name:string email:string password_digest:string
モデルが出来たら、マイグレートしましょう。
rake db:migrate
user.rbに次のhas_secure_password
を記述して下さい。これは、bcryptをbundle installすると使用可能になるメソッドで、password_digestに暗号化したパスワードを保存してくれるものです。
class User < ApplicationRecord
has_secure_password
end
bcryptを使ってみる
導入出来たところで、パスワードの暗号化保存を使ってみましょう。
rails consoleを開いて下さい。
rails console
下記のようにuserデータを作成しましょう。
ここでhas_secure_passwordメソッドにより、passwordの文字列が暗号化されてpassword_digestに保存されます。
User.create(name: 'name', email: 'test@email.com', password: 'password')
createするとrails consoleの画面に作られたデータが表示されると思いますが、password_digestに下記のように暗号化された文字列が入っていればOKです。
password_digest: "$2a$10$BUD6HR0ljHwVR.2bElaTZugMvrjCFj9HpQxjh8GUzTG..."
何気なく使っていた暗号化ですが、まとめてみると理解が深まった気がします。
ユーザーのパスワードは、安全に保管しましょう。