0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

bcrypt-rubyのmodule BCryptのソースコードを日本語訳する

Posted at

Railsチュートリアル9章に出てきたBCrypt::Password.new(remember_digest).is_password?(remember_token)が初見では理解できなかったので、このコードの大元であるmodule BCryptを日本語訳します。

module BCrypt
  # A password management class which allows you to safely store users' passwords and compare them.
  #ユーザーのパスワードを安全に保管し、比較することができるパスワード管理クラスです。
  #
  # Example usage: 使用例:
  #
  #   include BCrypt
  #
  #   # hash a user's password ユーザーのパスワードのハッシュ化
  #   @password = Password.create("my grand secret")
  #   @password #=> "$2a$12$C5.FIvVDS9W4AYZ/Ib37YuWd/7ozp1UaMhU28UKrfSxp2oDchbi3K"
  #
  #   # store it safely 安全に保管する
  #   @user.update_attribute(:password, @password)
  #
  #   # read it back 読み返す
  #   @user.reload!
  #   @db_password = Password.new(@user.password)
  #
  #   # compare it after retrieval 回収後の比較
  #   @db_password == "my grand secret" #=> true
  #   @db_password == "a paltry guess"  #=> false
  #
  class Password < String
    # The hash portion of the stored password hash.
    # 保存されているパスワードのハッシュの部分
    attr_reader :checksum
    # The salt of the store password hash (including version and cost).
    # ストアパスワードハッシュのソルト(バージョンとコストを含む)
    attr_reader :salt
    # The version of the bcrypt() algorithm used to create the hash.
    # ハッシュの作成に使用されるbcrypt()アルゴリズムのバージョン
    attr_reader :version
    # The cost factor used to create the hash.
    # ハッシュの作成に使用されるコスト係数
    attr_reader :cost

    class << self
      # Hashes a secret, returning a BCrypt::Password instance. Takes an optional <tt>:cost</tt> option, which is a
      # logarithmic variable which determines how computational expensive the hash is to calculate (a <tt>:cost</tt> of
      # 4 is twice as much work as a <tt>:cost</tt> of 3). The higher the <tt>:cost</tt> the harder it becomes for
      # attackers to try to guess passwords (even if a copy of your database is stolen), but the slower it is to check
      # users' passwords.
      #
      # 秘密をハッシュ化し、BCrypt::Passwordインスタンスを返します。オプションで
      # <tt>:cost</tt>を取ります。これはハッシュを計算するのにどれだけの計算量が必
      # 要かを決定する対数変数です(4の<tt>:cost</tt>は3の<tt>:cost</tt>の2倍の仕事
      # 量です)。<tt>:cost</tt>が高いほど、攻撃者がパスワードを推測しようとするのは
      # 難しくなりますが(データベースのコピーが盗まれたとしても)、#ユーザーのパ
      # スワードをチェックするのは遅くなります。ユーザーのパスワードをチェックする
      # のが遅くなります。
      #
      # Example: 例
      #
      #   @password = BCrypt::Password.create("my secret", :cost => 13)
      def create(secret, options = {})
        cost = options[:cost] || BCrypt::Engine.cost
        raise ArgumentError if cost > BCrypt::Engine::MAX_COST
        Password.new(BCrypt::Engine.hash_secret(secret, BCrypt::Engine.generate_salt(cost)))
      end

      def valid_hash?(h)
        /\A\$[0-9a-z]{2}\$[0-9]{2}\$[A-Za-z0-9\.\/]{53}\z/ === h
      end
    end

    # Initializes a BCrypt::Password instance with the data from a stored hash.
    # 保存されたハッシュからのデータで BCrypt::Password インスタンスを初期化します。
    def initialize(raw_hash)
      if valid_hash?(raw_hash)
        self.replace(raw_hash)
        @version, @cost, @salt, @checksum = split_hash(self)
      else
        raise Errors::InvalidHash.new("invalid hash")
      end
    end

    # Compares a potential secret against the hash. Returns true if the secret is the original secret, false otherwise.
    # 潜在的な秘密をハッシュと比較します。秘密がオリジナルの秘密であればtrueを、そうでなければfalseを返します。
    #
    # Comparison edge case/gotcha:
    # 比較エッジケース/ゴッチャ
    #
    #    secret = "my secret"
    #    @password = BCrypt::Password.create(secret)
    #
    #    @password == secret              # => True
    #    @password == @password           # => False
    #    @password == @password.to_s      # => False
    #    @password.to_s == @password      # => True
    #    @password.to_s == @password.to_s # => True
    def ==(secret)
      super(BCrypt::Engine.hash_secret(secret, @salt))
    end
    alias_method :is_password?, :==

  private

    # Returns true if +h+ is a valid hash.
    # +h+が有効なハッシュであればtrueを返します
    def valid_hash?(h)
      self.class.valid_hash?(h)
    end

    # call-seq:
    # 呼び出し手順
    #   split_hash(raw_hash) -> version, cost, salt, hash
    #
    # Splits +h+ into version, cost, salt, and hash and returns them in that order.
        # h+をバージョン、コスト、ソルト、ハッシュに分割し、その順に返します。
    def split_hash(h)
      _, v, c, mash = h.split('$')
      return v.to_str, c.to_i, h[0, 29].to_str, mash[-31, 31].to_str
    end
  end
end
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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?