LoginSignup
7
5

More than 5 years have passed since last update.

RailsのMessage Verifiersは何をしているのか

Posted at

今さらですが、Rails4.1リリースノートにある Message Verifiers を調べてみました.

TL;DR

使い方はとてもシンプルで以下のように使うだけです.

rails_console
> token = Rails.application.message_verifier(:foo).generate('data')
=> "BAhJIglkYXRhBjoGRVQ=--c1d9142a4741bbe8d377d5d9d475948137805e5b"
> Rails.application.message_verifier(:foo).verify(token)
=> "data"

特徴

  • config/secrets.ymlのsecret_key_baseと引数(:foo)を使って秘密鍵を作るから強度がある.
  • データ('data')自体は暗号化されてない
  • Base64の文字列なのでURLに乗せられる
    • +,/,=がメッセージ(token)中に含まれるから少し注意
  • メッセージが改竄されても検出できる

キーとなるコードとか

メッセージのフォーマット

メッセージのフォーマットはデータ格納する[DATA]
検証で利用する[DIGEST]部分をつないだ文字列になります.

[DATA]--[DIGEST]

試しに以下のメッセージをデコードしていきます.

BAhJIglkYXRhBjoGRVQ=--c1d9142a4741bbe8d377d5d9d475948137805e5b

[DATA]のデコード

MarshalとBase64だけでできてます

[DATA]は以下のような感じでデコードできます
符号化しているだけなので簡単にデコードできます.

::Marshal.load(::Base64.strict_decode64('BAhJIglkYXRhBjoGRVQ='))
#=> "data"

[DIGEST]のデコード

Rails.application.key_generatorを使った秘密鍵と
HMCAのハッシュ値を計算しています.

secret = Rails.application.key_generator.generate_key('foo')
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get('SHA1').new, secret, 'BAhJIglkYXRhBjoGRVQ=')
#=> "c1d9142a4741bbe8d377d5d9d475948137805e5b"

検証自体はこのハッシュ値とメッセージに含まれるハッシュ値を比較してる感じです.
正確には単純な文字列比較でなくバイナリ単位で比較してるっぽい.

7
5
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
7
5