class CryptCheckpass

Mother of all KDF classes.

Subclasses of this are expected to implement the following 4 class methods:

If a subclass's `provide?` returns `true` for an id, then that class is responsible for generating new hash of that id. Likewise if `understand?` returns `true` for a hash, that should be able to checkpass.

Caveats:

Public Class Methods

checkpass?(pass, hash) click to toggle source

Checks if the given password matches the hash.

@param pass [String] a password to test. @param hash [String] a good hash digest string. @return [true] they are identical. @return [false] they are distinct. @raise [NotImplementedError] don't know how to parse hash.

# File lib/crypt_checkpass/api.rb, line 107
def checkpass? pass, hash
  return false # default false
end
crypt_checkpass?(pass, hash) click to toggle source

(see ::#crypt_checkpass?)

# File lib/crypt_checkpass/api.rb, line 54
def crypt_checkpass? pass, hash
  kdf = find_kdf_by_string hash
  return kdf.checkpass? pass, hash
end
crypt_newhash(password, pref = nil, id: nil, **kwargs) click to toggle source

(see ::#crypt_newhash)

# File lib/crypt_checkpass/api.rb, line 60
  def crypt_newhash password, pref = nil, id: nil, **kwargs
    raise ArgumentError, <<-"end".strip if pref && id
      wrong number of arguments (given 2, expected 1)
    end
    raise ArgumentError, <<-"end".strip, kwargs.keys if pref &&! kwargs.empty?
      unknown key: %p
    end

    if pref then
      require_relative 'bcrypt'
      return CryptCheckpass::Bcrypt.new_with_openbsd_pref password, pref
    else
      kdf = find_kdf_by_id id
      return kdf.newhash password, id: id, **kwargs
    end
  end
newhash(*;) click to toggle source

Generate a new password hash string.

@note There is no way to specify salt. That's a bad idea. @return [String] hashed digest string of password.

# File lib/crypt_checkpass/api.rb, line 115
def newhash *;
  raise 'NOTREACHED'
end
provide?(id) click to toggle source

Checks if the given ID can be handled by this class. A class is free to handle several IDs, like 'argon2i', 'argon2d', …

@param id [String] hash function ID. @return [true] it does. @return [false] it desn't.

# File lib/crypt_checkpass/api.rb, line 87
def provide? id
  return false # default false
end
understand?(str) click to toggle source

Checks if the given hash string can be handled by this class.

@param str [String] a good hashed string. @return [true] it does. @return [false] it desn't.

# File lib/crypt_checkpass/api.rb, line 96
def understand? str
  return false # default false
end

Private Class Methods

find_kdf_by_id(id) click to toggle source
# File lib/crypt_checkpass/api.rb, line 212
  def find_kdf_by_id id
    kdf = @kdfs.find {|i| i.provide? id }
    return kdf if kdf
    raise ArgumentError, <<-"end".strip, id
      don't know how to generate %s hash.
    end
  end
find_kdf_by_string(str) click to toggle source
# File lib/crypt_checkpass/api.rb, line 220
  def find_kdf_by_string str
    kdf = @kdfs.find {|i| i.understand? str }
    return kdf if kdf
    raise ArgumentError, <<-"end".strip, str
      don't know how to parse %p, maybe clobbered?
    end
  end
inherited(klass) click to toggle source

@!endgroup

Calls superclass method
# File lib/crypt_checkpass/api.rb, line 207
def inherited klass
  super
  @kdfs.push klass
end
match?(str, re) click to toggle source

Fallback routine counterpart. @param re [Regexp] the language to accept. @param str [String] target string to test. @return [true] accepted. @return [false] otherwise.

# File lib/crypt_checkpass/api.rb, line 175
def match? str, re
  return re.match? str
end
phcdecode(str) click to toggle source
# File lib/crypt_checkpass/api.rb, line 200
def phcdecode str
  require 'phc_string_format'
  return PhcStringFormat::Formatter.parse str
end
phcencode(id, params, salt, csum) click to toggle source

@!group PhcStringFormat wrappers

# File lib/crypt_checkpass/api.rb, line 194
def phcencode id, params, salt, csum
  require 'phc_string_format'
  return PhcStringFormat::Formatter.format \
    id: id, params: params, salt: salt, hash: csum
end
raise(class_or_string, *argv) click to toggle source

Utility raise + printf function. It is quite hard to think of exceptions that only concern fixed strings. @shyouhei really doesn't understand why this is not a canon.

@overload raise(klass, fmt, *va_args)

@param klass   [Class]  exception class.
@param fmt     [String] printf-format string.
@param va_args [Array]  anything.
@raise         [klass]  always raises a klass instance.

@overload raise(fmt, *va_args)

@param fmt     [String]       printf-format string.
@param va_args [Array]        anything.
@raise         [RuntimeError] always raises a RuntimeError.
Calls superclass method
# File lib/crypt_checkpass/api.rb, line 139
  def raise class_or_string, *argv
    case class_or_string
    when Class, Exception then
      klass  = class_or_string
      string = sprintf(*argv)
    when String then
      klass  = RuntimeError
      string = class_or_string % argv
    else # recursion
      raise TypeError, <<-"end".strip
        wrong argument type %p (%p expected)
      end
    end
    return super klass, string, caller
  end
require(gem, lib = gem) click to toggle source

Utility gem + require function. It is often the case a library is a gem and calling gem before require is desirable.@shyouhei really doesn't understand why this is not a canon.

@return [void] @param gem [String] gem name. @param lib [String] library name. @raise [Gem::LoadError] gem not found. @raise [LoadError] lib not found.

# File lib/crypt_checkpass/api.rb, line 164
def require gem, lib = gem
  Kernel.gem gem
  Kernel.require lib
end