概要
コード上でパスワードなどの認証情報を使って外部にアクセスしたい場合があります
もし認証情報が暗号化されている場合は何かしらの方法を使って復号化する処理をコード上に記載する必要があります
今回は ActiveSupport::MessageEncryptor を使って暗号化/復号化された認証情報を扱う方法を紹介します
また復号化の際に重要な復号化キーの管理方法も考えます
環境
- macOS 11.6
- Ruby 3.0.2p107
- activesupport 6.1.4.1
準備
- bundle init
- vim Gemfile
gem "activesupport"
- bundle install
暗号化されたパスワードを生成する
まずは暗号化されたパスワードを生成します
require 'active_support'
key = "sk123456789012345678901234567890" # key must be 32 bytes
crypt = ActiveSupport::MessageEncryptor.new(key)
encrypted_pwd = crypt.encrypt_and_sign("hoge")
これを実行すると TTFaaENWcmdJTTAwSUpuN2g5QWwrZz09LS1yQWw3Ymt3bkdXR3lmc2I3VWNhdWFBPT0=--194ef2156f114d9d1154cdd22dfedc31d5144017
という暗号化されたパスワード情報を取得できます
この暗号化されたパスワードをデータベースなりコンフィグファイルなりコード上で管理しているとします
復号化する処理の部分
では今度は復号化する処理を考えます 基本的には以下で OK です
require 'active_support'
key = "sk123456789012345678901234567890" # key must be 32 bytes
crypt = ActiveSupport::MessageEncryptor.new(key)
encrypted_pwd = "TTFaaENWcmdJTTAwSUpuN2g5QWwrZz09LS1yQWw3Ymt3bkdXR3lmc2I3VWNhdWFBPT0=--194ef2156f114d9d1154cdd22dfedc31d5144017"
raw_password = crypt.decrypt_and_verify(encrypted_pwd)
復号化する場合には decrypt_and_verify
を使います
これで元のパスワードを取得できます
大事なのは 32バイトのキー情報
もうわかるかと思いますが暗号化するキーと復号化するキーはどちらも同じものを使っています
上記のサンプルでは直接コード上に key を記載していますがこれではダメです
データベースなどにある暗号化されたパスワードが漏洩しただけであれば key がわからない限りパスワードは元に戻せませんがもしコードが見れる場合には key がわかってしまうので簡単に復号化できてしまいます
なので key はまた別の場所で管理するようにしましょう
例えば暗号化されたパスワードがあるデータベースでもなくコードが管理されているリポジトリでもない第三のリポジトリを使ってそこで管理する方法です
この場合であればデータベースとコードが見れる状態であっても第三のリポジトリにアクセスできないのであればパスワードの復号化は防げます
ただコード自体は第三のリポジトリで管理されている key が必ず必要になるのでコードがデプロイされているサーバなどに入れてしまうのであれば復号化を防ぐ手段はありません
暗号化キーと復号化キーを更に分ける方法を考える
今回の ActiveSupport::MessageEncryptor ではできませんが暗号化するキーと復号化キーするキーを分けることでもう少しセキュリティを強化することができます
暗号化キーと復号化キーをそれぞれ別のリポジトリで管理することで堅牢にすることはできますがこの方法も結局コードがデプロイされているサーバにログインされてしまえばどちらも見ることができるはずなので微妙な感じにはなります
あとは復号化キーは別のデータベースで管理するという方法もあります
キーを外部から取得する
コード上では必要ですが処理が終了したら必ずキーを削除するようにします
そして再度複合化が必要な場合にはリポジトリや API を使って外部からキー情報を取得して復号化します
こうすればサーバ上に複合化キーの情報は残らないのでサーバにログインされても多少はキーの漏洩を防ぐことができます
bcrypt を使う
そもそも復号化の必要がないような仕組みにするのもありだと思います
ただ外部アクセスするようなケースだと bcrypt を使うのは難しいかもしれません
最後に
すべてのケースを想定した堅牢なパスワード管理を考えるのは不可能な気もします
しかしサーバにログインされたりデータベースにアクセスできたりと局所的になケースであればキーなどの情報を別の場所に保存するなりの対処で漏洩は防げる可能性は増えるかもしれません
最低でも復号化キー情報などはコードに直接書かずに外部で保存するようにしたほうがいいかなと思います
0 件のコメント:
コメントを投稿