Class: SCrypt::Engine

Inherits:
Object
  • Object
show all
Defined in:
lib/scrypt.rb,
ext/mri/scrypt_ext.c

Constant Summary

DEFAULTS =
{ 
  :max_mem => 1024 * 1024,
  :max_memfrac => 0.5,
  :max_time => 0.2
}

Class Method Summary (collapse)

Class Method Details

+ (Object) __sc_calibrate

+ (Object) __sc_crypt

+ (Object) autodetect_cost(salt)

Autodetects the cost from the salt string.



89
90
91
# File 'lib/scrypt.rb', line 89

def self.autodetect_cost(salt)
  salt[/^[0-9a-z]+\$[0-9a-z]+\$[0-9a-z]+\$/]
end

+ (Object) calibrate(options = {})

Returns the cost value which will result in computation limits less than the given options.

Options: :max_time specifies the maximum number of seconds the computation should take. :max_mem specifies the maximum number of bytes the computation should take. A value of 0 specifies no upper limit. The minimum is always 1 MB. :max_memfrac specifies the maximum memory in a fraction of available resources to use. Any value equal to 0 or greater than 0.5 will result in 0.5 being used.

Example:

# should take less than 200ms
SCrypt.calibrate(:max_time => 0.2)


77
78
79
80
# File 'lib/scrypt.rb', line 77

def self.calibrate(options = {})
  options = DEFAULTS.merge(options)
  __sc_calibrate(options[:max_mem], options[:max_memfrac], options[:max_time])
end

+ (Object) generate_salt(options = {})

Generates a random salt with a given computational cost.



43
44
45
46
47
48
# File 'lib/scrypt.rb', line 43

def self.generate_salt(options = {})
  options = DEFAULTS.merge(options)
  cost = calibrate(options)
  salt = Digest::SHA1.hexdigest(OpenSSL::Random.random_bytes(32))
  cost + salt
end

+ (Object) hash_secret(secret, salt)

Given a secret and a valid salt (see SCrypt::Engine.generate_salt) calculates an scrypt password hash.



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/scrypt.rb', line 29

def self.hash_secret(secret, salt)
  if valid_secret?(secret)
    if valid_salt?(salt)
      cost = autodetect_cost(salt)
      salt + "$" + Digest::SHA1.hexdigest(__sc_crypt(secret.to_s, salt, cost))
    else
      raise Errors::InvalidSalt.new("invalid salt")
    end
  else
    raise Errors::InvalidSecret.new("invalid secret")
  end
end

+ (Object) memory_use(cost)

Computes the memory use of the given cost



83
84
85
86
# File 'lib/scrypt.rb', line 83

def self.memory_use(cost)
  n, r, p = cost.scanf("%x$%x$%x$")
  (128 * r * p) + (256 * r) + (128 * r * n);
end

+ (Boolean) valid_cost?(cost)

Returns true if cost is a valid cost, false if not.

Returns:

  • (Boolean)


51
52
53
# File 'lib/scrypt.rb', line 51

def self.valid_cost?(cost)
  cost.match(/^[0-9a-z]+\$[0-9a-z]+\$[0-9a-z]+\$$/) != nil
end

+ (Boolean) valid_salt?(salt)

Returns true if salt is a valid salt, false if not.

Returns:

  • (Boolean)


56
57
58
# File 'lib/scrypt.rb', line 56

def self.valid_salt?(salt)
  salt.match(/^[0-9a-z]+\$[0-9a-z]+\$[0-9a-z]+\$[A-Za-z0-9]{20,}$/) != nil
end

+ (Boolean) valid_secret?(secret)

Returns true if secret is a valid secret, false if not.

Returns:

  • (Boolean)


61
62
63
# File 'lib/scrypt.rb', line 61

def self.valid_secret?(secret)
  secret.respond_to?(:to_s)
end