LoginSignup
0
0
この記事誰得? 私しか得しないニッチな技術で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

SHA-1で作成したsigned_idをRails 7.0でもfind_signedで検索できるようにする

Last updated at Posted at 2024-06-13

はじめに:困ったこと・解決したいこと

Rails 7.0ではActive RecordのデフォルトのハッシュダイジェストアルゴリズムがSHA-1からSHA-256に変更されました。

この変更が入ると、Rails 6.1以前に生成したsigned_idはRails 7.0以降で利用できなくなります。

# Rails 6.1時代に user.signed_id で生成した署名付きid
signed_id = "eyJfcmFpbHMiOnsibWVzc2FnZSI6Ik1USXpORFU9IiwiZXhwIjpudWxsLCJwdXIiOiJ1c2VyL3B1YmxpY19hdHRhY2htZW50cyJ9fQ==--8e20bed4cbb616db63a518d166ac8a5bf0266a18ff7ba55bbfd9bce9d571d6c7"

# ハッシュダイジェストアルゴリズムが変わったため、Rails 7.0環境ではRails 6.1時代の署名付きidは無効
User.find_signed(signed_id) #=> nil

一時的な回避策としてはRails 7.0でも引き続きSHA-1を使う、という方法があります。
ですが、SHA-1の使用は現在では推奨されないため(参考)、あくまで一時的な回避策でしかありません。

# 一時的な回避策としては有効だが、ずっとこのままにはできない
config.active_record.encryption.hash_digest_class = OpenSSL::Digest::SHA1

この記事でやりたいことは、

  • デフォルトはSHA-256とする(Rails 7.0にアップデートした後はSHA-256でsigned_idを読み書きする)
  • 何かしらの理由で古いsigned_idで検索しないといけない場合のみ、SHA-1で作成したsigned_idでもfind_signedで検索できるようにする

です。

解決策

いろいろ調べた結果、以下のようなコードを書くことでSHA-1で作成した古いsigned_idをRails 7.0でも検索できるようになりました。

config/initializers/message_verifiers_rotates.rb
Rails.application.config.after_initialize do |app|
  key_generator = ActiveSupport::KeyGenerator.new(
    app.secret_key_base,
    iterations: 1000,
    hash_digest_class: OpenSSL::Digest::SHA1
  )
  caching_key_generator = ActiveSupport::CachingKeyGenerator.new(key_generator)
  secret = caching_key_generator.generate_key("active_record/signed_id")

  # ここではUserクラスでfind_signedを使う想定
  User.signed_id_verifier.rotate(secret)
end

こうすると、find_signedメソッドは最初はSHA-256で検索し、データが見つからなければSHA-1で検索するようになります。

# まずSHA-256のsigned_idとして検索
# → 見つからなければSHA-1のsigned_idとして検索
# → それでも見つからなければnil
User.find_signed(signed_id)

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0