DBは大抵外部から直接アクセスできないように、厳重に守られていると思いますが、それでも格納するのに躊躇するような大切なデータの場合は、もう一歩踏み込んで保護したいところです。
そんな場合に役に立つ、複合可能な暗号アルゴリズムを使って、データの暗号化をやってみたいと思います。
簡単に、暗号化 → 復号化 をやってみます。
ややこしいのは、「password、salt」とkey「key、iv」の関係性。
saltを暗号データとセットで保存しても大丈夫なのか?という疑問は尤もなところですが、opensslコマンドをCUIから実行して作成した暗号データを見てみると、データの先頭の16バイト(くらいだったと思う)にはsaltがばっちり保存されております。
こちらも別々に保存してある方が安全なのだと思いますが、要は復号化に必要な4つの要素がすべて揃わないと復号化には時間がかかるという事なんだということなのかなと思います:-)
取得した暗号化済みデータはバイナリなので、base64に変換すると文字列になり、DBに投入しやすい形に変更されるので何かと便利です。
そんな場合に役に立つ、複合可能な暗号アルゴリズムを使って、データの暗号化をやってみたいと思います。
事前準備
opensslを使用するので予めgem installしておくgem install openssl
簡単に、暗号化 → 復号化 をやってみます。
require "openssl"
# 暗号化するデータ
data = "*secret data*"
# パスワード
pass = "**secret password**"
# salt
salt = OpenSSL::Random.random_bytes(8)
# 暗号化器を作成する
enc = OpenSSL::Cipher.new("AES-256-CBC")
enc.encrypt
# 鍵とIV(Initialize Vector)を PKCS#5 に従ってパスワードと salt から生成する
key_iv = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, 12345, enc.key_len + enc.iv_len)
key = key_iv[0, enc.key_len]
iv = key_iv[enc.key_len, enc.iv_len]
# 鍵とIVを設定する
enc.key = key
enc.iv = iv
# 暗号化する
encrypted_data = ""
encrypted_data << enc.update(data)
encrypted_data << enc.final
p encrypted_data
# 復号化器を作成する
dec = OpenSSL::Cipher.new("AES-256-CBC")
dec.decrypt
# 鍵とIVを設定する
dec.key = key
dec.iv = iv
# 復号化する
decrypted_data = ""
decrypted_data << dec.update(encrypted_data)
decrypted_data << dec.final
p decrypted_data
ややこしいのは、「password、salt」とkey「key、iv」の関係性。
- passwordは、大抵システムに対して1つ設定しておく感じになるが、saltは毎回ランダム生成になる。
- keyとivを生成するアルゴリズム(暗号アルゴリズム、ハッシュする回数)は固定なので、「key、iv」を一意な存在にするのはsaltという事になる。
- なので、saltを失うとほぼ復号化は不可能。
- このサンプルプログラムでは、暗号化と復号化を同時にやっているので「key、iv」は使い回しているが、本来は都度生成することになる。
saltを暗号データとセットで保存しても大丈夫なのか?という疑問は尤もなところですが、opensslコマンドをCUIから実行して作成した暗号データを見てみると、データの先頭の16バイト(くらいだったと思う)にはsaltがばっちり保存されております。
こちらも別々に保存してある方が安全なのだと思いますが、要は復号化に必要な4つの要素がすべて揃わないと復号化には時間がかかるという事なんだということなのかなと思います:-)
取得した暗号化済みデータはバイナリなので、base64に変換すると文字列になり、DBに投入しやすい形に変更されるので何かと便利です。
コメント
コメントを投稿