最初に
時間と計算能力のあるコンピュータがあれば暴けないパスワードはありません。パスワードの正しい保存法は絶対に暴かれないパスワードの保存方法ではなく、パスワードを出来るだけ暴かれにくくする方法です。
データベースにユーザーの情報を保存する際のパスワードについて
まずは、絶対に平文での保存はやめましょう!!
データベースを見られた瞬間に全ユーザーのアカウントにアクセスされてしまいます。
User ID | Pasword |
---|
user1| This |
user2 | is |
user3 | a |
user4 | plain |
user5 | password |
user6 | !!!!!!!!! |
丸見えです。絶対にやめましょう。
ではどうするか。
パスワードにSALTを足してからHashします!
どうゆうことか
まずはHashについて。
ハッシュ化の特性として
- パスワードのハッシュ化は簡単
- ハッシュ値からのパスワードの計算は難しい
が挙げられます。
パスワードをハッシュすることによってDBを見られたとしても簡単にはパスワードを暴けられなくします。
しかし、それだけではまだ、セキュリティ面において万全ではありません。次はsaltです。
SALT について
パスワードをハッシュ化する前に余分に文字を付け足してからハッシュ化することによって、パスワードを計算する時間や、同一のパスワードを持つユーザーを見分けることのできないようにします。そしてこの付け足す余分な文字をSALTと言います。
ただのハッシュでは (DBには平文のパスワードは挿入しません)
User ID | Password (平文) | ハッシュ値 |
---|---|---|
user1 | pass | asldfkjsld |
user2 | pass | asldfkjsld |
user3 | word | saflsdjls |
こうなっており、user1とuser2が同じパスワードを持っているのは一目瞭然です。つまりuser1かuser2のパスワードを見つけられれば、もう片方のアカウントのアクセスもできるようになります。また、さらにいうと4文字のハッシュ値を計算するのは簡単であり、さらにはレインボーテーブル攻撃というのも存在します。
SALT を付け足すと: (ハッシュ値については適当に打っています)
User ID | Password (平文) | SALT値 | (SALT + Password)のハッシュ値 |
---|---|---|---|
user1 | pass | hello | alsjflasjdflajsdfnklnsf |
user2 | pass | world | lkjlkvirwefsndflskdn |
user3 | word | yesterday | vbeiwbfnisndviabds |
となり、user1とuser2が同じパスワードであることもわかりにくいし、パスワードの計算をするのにも4文字から8文字になり、計算量が増えパスワードの計算が大変になりました。(実際には8文字ではダメです。)
SALT のポイント
- ユーザー一人一人に違うSALTをつける。
- SALTが長ければそれだけ攻撃者の計算量が増える。
Rails でのパスワードの保存の実装
User Name | Salted Password |
---|---|
user1 | skfhkshdfa;ks |
user2 | asdfhak;shdf |
user3 | wiasfh;akshfl |
このようなデータベースにしようと思います。
*User model (カラムがUser Nameだけの)がすでにあると仮定します。
class User < ApplicationRecord
has_secure_password
end
gem 'bcrypt', '3.1.12'
rails generate migration add_password_digest_to_users password_digest:string
<div class="field">
<%= form.label :password %>
<%= form.password_field :password %>
</div>
<div class="field">
<%= form.label :password_confirmation %>
<%= form.password_field :password_confirmation %>
</div>
これだけです。
データベースには"hello"にSALTを加え、それがハッシュされたものがパスワードとして保存されました。