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