📖

Redmineにおけるユーザーのパスワードの保存方法(暗号化方法)

2022/12/22に公開

Redmineに保存されているユーザーのパスワードはSHA-1による2回のハッシュ化が行われている。手順は以下の通り。

  1. 平文のパスワードをSHA-1でハッシュ化
  2. 1で得られたハッシュ値の16進数にソルト(ユーザーごとにランダムに生成した32桁の16進数)を結合し、それに対してさらにSHA-1でハッシュ化
  3. データベースにはソルトと2で得られたハッシュ値を保存

ハッシュ化のコード

ハッシュ化は app/models/user.rb 内の User#salt_password で行われている。

  def salt_password(clear_password)
    self.salt = User.generate_salt
    self.hashed_password = User.hash_password("#{salt}#{User.hash_password clear_password}")
    self.passwd_changed_on = Time.now.change(:usec => 0)
  end

User#salt_password 内で呼び出されている User.generate_salt はランダムな16バイトの値の16進表現(32桁の16進数)を生成する。

    def generate_salt
      Redmine::Utils.random_hex(16)
    end

User.hash_password は、与えられたパスワードをSHA-1でハッシュ化する。

    def hash_password(clear_password)
      Digest::SHA1.hexdigest(clear_password || "")
    end

ハッシュ化処理例

パスワード himitsu をハッシュ化する例

平文のパスワード himitsu をSHA-1でハッシュ化。 c44ade485240212403b41eba503fcb222d190cd0 が得られる。

irb(main):001:0> Digest::SHA1.hexdigest('himitsu')
=> "c44ade485240212403b41eba503fcb222d190cd0"

ランダムなソルトを得る。

irb(main):002:0> Redmine::Utils.random_hex(16)
=> "a729c5ff76d2254e105848e93d54a63c"

ソルトとパスワードのハッシュを結合し、さらにSHA-1でハッシュ化。

irb(main):004:0>  Digest::SHA1.hexdigest("c44ade485240212403b41eba503fcb222d190c
d0" + "a729c5ff76d2254e105848e93d54a63c")
=> "33409a07d26e3f82ef88e63ed28e5e4c3650e5f9"

データベースにはソルト a729c5ff76d2254e105848e93d54a63c と最終的に得られたハッシュ値 33409a07d26e3f82ef88e63ed28e5e4c3650e5f9 を保存。

Discussion