class RbNaCl::PasswordHash::Argon2

over software implementations.
tradeoff attacks. It prevents ASICs from having a significant advantage
use of multiple computing units, while still providing defense against
hard functions. It aims at the highest memory filling rate and effective
Argon2. Argon2 summarizes the state of the art in the design of memory-
Since version 1.0.9, Sodium provides a password hashing scheme called

def self.digest_size_value(digest_size)

Returns:
  • (Integer) - digest_size a valid value for digest size

Raises:
  • (LengthError) - if the value is out of range
def self.digest_size_value(digest_size)
  digest_size = digest_size.to_i
  raise LengthError, "digest size too short" if digest_size < ARGON2_MIN_OUTLEN
  raise LengthError, "digest size too long"  if digest_size > ARGON2_MAX_OUTLEN
  digest_size
end

def self.digest_str_verify(password, digest_string)

Returns:
  • (boolean) - true if password matches digest_string

Parameters:
  • digest_string (String) -- to compare to
  • password (String) -- to be hashed
def self.digest_str_verify(password, digest_string)
  raise ArgumentError, "password must be a String" unless password.is_a?(String)
  raise ArgumentError, "digest_string must be a String" unless digest_string.is_a?(String)
  pwhash_str_verify(
    digest_string,
    password, password.bytesize
  )
end

def self.memlimit_value(memlimit)

Returns:
  • (Integer) - memlimit a valid value for memlimit

Raises:
  • (ArgumentError) - if the value is out of range

Parameters:
  • memlimit, (Integer) -- in bytes
def self.memlimit_value(memlimit)
  case memlimit
  when :interactive then MEMLIMIT_INTERACTIVE
  when :moderate then MEMLIMIT_MODERATE
  when :sensitive then MEMLIMIT_SENSITIVE
  when MEMLIMIT_MIN..MEMLIMIT_MAX then memlimit.to_i
  else
    raise ArgumentError, "memlimit must be within the range 2**(13..32)"
  end
end

def self.opslimit_value(opslimit)

Returns:
  • (Integer) - opslimit a valid value for opslimit

Raises:
  • (ArgumentError) - if the value is out of range

Parameters:
  • opslimit (Integer) -- value to be checked
def self.opslimit_value(opslimit)
  case opslimit
  when :interactive then OPSLIMIT_INTERACTIVE
  when :moderate then OPSLIMIT_MODERATE
  when :sensitive then OPSLIMIT_SENSITIVE
  when OPSLIMIT_MIN..OPSLIMIT_MAX then opslimit.to_i
  else
    raise ArgumentError, "opslimit must be within the range 3..10"
  end
end

def digest(password, salt, algo = nil)

Returns:
  • (String) - scrypt digest of the string as raw bytes

Parameters:
  • digest (Symbol) -- algorithm to use (may be :argon2i or :argon2id)
  • salt (String) -- to make the digest unique
  • password (String) -- to be hashed
def digest(password, salt, algo = nil)
  raise ArgumentError, "digest_size is required" unless @digest_size
  digest = Util.zeros(@digest_size)
  salt   = Util.check_string(salt, SALTBYTES, "salt")
  if algo.nil?
    algorithm = ALG_DEFAULT
  elsif algo == :argon2i
    algorithm = ALG_ARGON2I13
  elsif algo == :argon2id && Sodium::Version::ARGON2ID_SUPPORTED
    algorithm = ALG_ARGON2ID13
  else
    raise ArgumentError, "digest algorithm is not supported"
  end
  status = self.class.pwhash(
    digest, @digest_size,
    password, password.bytesize, salt,
    @opslimit, @memlimit, algorithm
  )
  raise CryptoError, ARGON_ERROR_CODES[status] if status.nonzero?
  digest
end

def digest_str(password)

Returns:
  • (String) - argon2 digest string

Parameters:
  • password (String) -- to be hashed
def digest_str(password)
  raise ArgumentError, "password must be a String" unless password.is_a?(String)
  result = Util.zeros(STRBYTES)
  ok = self.class.pwhash_str(
    result,
    password, password.bytesize,
    @opslimit, @memlimit
  )
  raise CryptoError, "unknown error in Argon2#digest_str" unless ok
  result.delete("\x00")
end

def initialize(opslimit, memlimit, digest_size = nil)

Returns:
  • (RbNaCl::PasswordHash::Argon2) - An Argon2 password hasher object

Parameters:
  • digest_size (Integer) -- the byte length of the resulting digest
  • memlimit (Integer) -- the memory cost (e.g. 2**24)
  • opslimit (Integer) -- the CPU cost (1..10)
def initialize(opslimit, memlimit, digest_size = nil)
  @opslimit    = self.class.opslimit_value(opslimit)
  @memlimit    = self.class.memlimit_value(memlimit)
  @digest_size = self.class.digest_size_value(digest_size) if digest_size
end