2021年9月27日月曜日

Ruby でパスワードを暗号化してコード上で補完する保存する方法

Ruby でパスワードを暗号化してコード上で補完する保存する方法

概要

Ruby のコード上またはコンフィグファイルなどでパスワードを管理する場合があると思います 平文だとさすがにあぶないので何かしらの方法で暗号化して記載する必要があるかなと思います

今回は bcrypt を使って暗号化して保存する方法を紹介します

環境

  • macOS 11.6
  • Ruby 3.0.2p107
  • bcrypt 3.1.16

準備

  • bundle init
  • vim Gemfile
gem "bcrypt"
  • bundle install

暗号化されていないコード

まずは暗号化されていないコードを紹介します パスワードが平文で保存されているのがわかるかなと思います

require 'io/console'

password = "hoge"
input_password = STDIN.noecho(&:gets).chomp
puts input_password == password

これを実行する場合には以下のようにします

  • bundle exec ruby test.rb

これでターミナル上でパスワードの入力を求められるので適当に文字列を入力しましょう
当然「hoge」と入力した場合は true が出力されます

見ての通り認証するためのパスワード情報を平分で管理しているので危険です

パスワードを暗号化して管理する

bcrypt を使います

require 'io/console'
require 'bcrypt'

password = BCrypt::Password.new("$2a$12$8HvnCbkJHhqJMtXdmgAwJeNOlOpSubId3yvk64RC/JqXW8uNZ3Vti") # => hoge
input_password = STDIN.noecho(&:gets).chomp
puts password == input_password

同じように実行してみましょう

  • bundle exec ruby test.rb

これで同じように「hoge」を入力すると true が出力されるのが確認できます

暗号化されたパスワードを生成する方法は

BCrypt::Password.create("hoge")

でできます

ポイント

BCrypt::Password.new で生成したオブジェクトの == メソッドを使うのがポイントです

もし上記のコードで比較の部分を以下のように書き換えると例えパスワードが合っていても false が返ります

puts password == input_password

これは String クラスの == を使っているのでエラーになっています

input_password を puts してみるとわかりますが暗号化されたままのパスワードが表示されます なので単純に文字列クラスの比較を使ってもエラーになるので BCrypt::Password クラスのオブジェクトを元に比較するのが重要です

最後に

今回は Ruby 上だけで解決する方法を紹介しました
データベースなどを使えばデータベース側の暗号化機能も使えるので Ruby 側で考える必要はなくなります

基本的に復号化できないのでハッシュ化されたパスワードが漏洩しても元のパスワードを取得するのができないのが bcrypt のメリットです
ただ逆に言うと復号化して使うことはできないのでコード上のパスワードを情報を使って外部に認証する場合などはこの方法は使えません

あくまでもこの方法はユーザからの入力に対して暗号化する手法になります

とにかく重要なのはコードやデータベース上に平文のパスワードなどは保存しないようにすることが重要です そもそも漏洩しないことが重要ですが

0 件のコメント:

コメントを投稿