Class: CryptCheckpass::SHA2

Inherits:
CryptCheckpass show all
Defined in:
lib/crypt_checkpass/sha2.rb

Overview

The sha256crypt / sha512crypt by Ulrich Drepper. Default for /etc/shadow of most Linux distributions. Also no security flaws are known at the moment.

Newhash:

You can use crypto_newhash to create a new password hash using SHA2:

crypt_newhash(password, id: 'sha256', rounds: 1024)

where:

  • password is the raw binary password that you want to digest.

  • id is either "sha256" or "sha512".

  • rounds is for iteration rounds.

The generated password hash has following format.

Format:

Hash strings generated by sha256crypt is constructed like this:

%r{
  (?<id>     5                   ){0}
  (?<rounds> rounds=[1-9]\d{3,8} ){0}
  (?<salt>   [A-Za-z0-9./]{,16}  ){0}
  (?<csum>   [A-Za-z0-9./]{43}   ){0}

  \A     [$] \g<id>
     (?: [$] \g<rounds> )?
         [$] \g<salt>
         [$] \g<csum>
  \z
}x

That of sha512crypt is constructed like this:

%r{
  (?<id>     6                   ){0}
  (?<rounds> rounds=[1-9]\d{3,8} ){0}
  (?<salt>   [A-Za-z0-9./]{,16}  ){0}
  (?<csum>   [A-Za-z0-9./]{86}   ){0}

  \A     [$] \g<id>
     (?: [$] \g<rounds> )?
         [$] \g<salt>
         [$] \g<csum>
  \z
}x
  • id is 5 for sha256crypt, 6 for sha512crypt.

  • rounds is, if present, the stretch rounds in decimal integer. Should be in range of 1,000 to 999,999,999 inclusive.

  • salt and csum are the salt and checksum strings. Both are encoded in base64-like strings that do not strictly follow RFC4648. The only difference between $5$ and $6$ is the length of csum.

Examples:

crypt_newhash 'password', id: 'sha256'
# => "$5$eWGIDuRO1LEg8sAB$Pjdxj3AVy4GnFfeOfz8Ek1Gn.vDwTFMMyNk56x/lc.4"
crypt_checkpass? 'password', '$5$eWGIDuRO1LEg8sAB$Pjdxj3AVy4GnFfeOfz8Ek1Gn.vDwTFMMyNk56x/lc.4'
# => true
crypt_newhash 'password', id: 'sha512'
# => "$6$oIlkXbDGlU.HktGx$L7xkRSQYLe/yCbz6hIM2JSY6EMtkr/CyvR71Bhr9VkotfEOUiwY8A0rAuSFmO1titWLA8hTKQXWl3ZX0QqokS0"
crypt_checkpass? 'password', '$6$oIlkXbDGlU.HktGx$L7xkRSQYLe/yCbz6hIM2JSY6EMtkr/CyvR71Bhr9VkotfEOUiwY8A0rAuSFmO1titWLA8hTKQXWl3ZX0QqokS0'
# => true

See Also:

Class Method Summary collapse

Methods inherited from CryptCheckpass

crypt_checkpass?, crypt_newhash

Class Method Details

.checkpass?(pass, hash) ⇒ true, false

Checks if the given password matches the hash.

Parameters:

  • pass (String)

    a password to test.

  • hash (String)

    a good hash digest string.

Returns:

  • (true)

    they are identical.

  • (false)

    they are distinct.

Raises:

  • (NotImplementedError)

    don't know how to parse hash.



129
130
131
132
133
# File 'lib/crypt_checkpass/sha2.rb', line 129

def self.checkpass? pass, hash
  require 'unix-crypt', 'unix_crypt'

  return UnixCrypt.valid? pass, hash
end

.newhash(pass, id: 'sha256', rounds: nil) ⇒ String

Note:

There is no way to specify salt. That's a bad idea.

Generate a new password hash string.

Parameters:

  • pass (String)

    raw binary password string.

  • id (String) (defaults to: 'sha256')

    name of the algorithm.

  • rounds (Integer) (defaults to: nil)

    rounds of stretching.

Returns:

  • (String)

    hashed digest string of password.



149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/crypt_checkpass/sha2.rb', line 149

def self.newhash pass, id: 'sha256', rounds: nil
  require 'unix-crypt', 'unix_crypt'

  case id
  when 'sha256' then
    klass = UnixCrypt::SHA256
  when 'sha512' then
    klass = UnixCrypt::SHA512
  else
    raise ArgumentError, 'unknown id: %p', id
  end
  return klass.build pass, nil, rounds
end

.provide?(id) ⇒ true, false

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

Parameters:

  • id (String)

    hash function ID.

Returns:

  • (true)

    it does.

  • (false)

    it desn't.



136
137
138
139
140
141
142
# File 'lib/crypt_checkpass/sha2.rb', line 136

def self.provide? id
  case id when 'sha256', 'sha512' then
    return true
  else
    return false
  end
end

.understand?(str) ⇒ true, false

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

Parameters:

  • str (String)

    a good hashed string.

Returns:

  • (true)

    it does.

  • (false)

    it desn't.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/crypt_checkpass/sha2.rb', line 108

def self.understand? str
  md = %r{
    (?<id>     5 | 6                ){0}
    (?<rounds> rounds=[1-9]\d{3,8}  ){0}
    (?<salt>   [A-Za-z0-9./]{,16}   ){0}
    (?<csum>   [A-Za-z0-9./]{43,86} ){0}

    \A     [$] \g<id>
       (?: [$] \g<rounds> )?
           [$] \g<salt>
           [$] \g<csum>
    \z
  }x.match str
  return false unless md
  case md['id']
  when '5' then return md['csum'].length == 43
  when '6' then return md['csum'].length == 86
  end
end