Class: SafeDb::KdfSCrypt
- Inherits:
-
Object
- Object
- SafeDb::KdfSCrypt
- Defined in:
- lib/keytools/kdf.scrypt.rb
Overview
SCrypt is a Key Derivation Function (KDF) with a reliable OpenSSL implementation that converts low entropy password-like text to a high entropy key that is computationally infeasible to acquire through brute force.
SCrypt is incredibly resistant to attacks using dedicated hardware with massive memory to boot.
Constant Summary collapse
- SCRYPT_SALT_BYTE_LENGTH =
SCrypt salts are recommended to contain 16 and 32 bytes inclusive. Here we opt for 24 bytes which unrolls out to 192 bits which serializes into 32 base64 characters.
24- SCRYPT_ITERATION_INTEGER =
The iteration count is determined using the powers of two so if the iteration integer is 12 there will be two to the power of 12 ( 2^12 ) giving 4096 iterations. The minimum number is 4 (16 iterations) and the max is 31.
16- SCRYPT_KEY_LENGTH =
The scrypt algorithm produces a key that is 181 bits in length. The algorithm then converts the binary 181 bits into a (6-bit) Radix64 character.
181 / 6 = 30 remainder 1 (so 31 characters are needed).
31- SCRYPT_KEY_TRANSPORT_LENGTH =
When the key is transported using a 64 character set where each character is represented by 6 bits - the Scrypt key expands to 186 bits rather than the original 181 bits.
This expansion is because of the remainder.
181 bits divided by 6 is 30 characters plus 1 character for the extra bit. The 31 transported characters then appear as 31 times 6 which equals 186 bits. 186- SCRYPT_SALT_LENGTH =
The scrypt algorithm salt string should be 22 characters and may include forward slashes and periods.
22- SCRYPT_OUTPUT_TEXT_PREFIX =
Scrypt outputs a single line of text that holds the prefix then the Radix64 encoded salt and finally the Radix64 encoded hash key.
The prefix consists of two sections sandwiched within two dollar $ signs at the extremeties and a third dollar separating them.
The two sections are the
-
Scrypt algorithm version number (2a or 2b) and
-
a power of 2 integer defining the no. of interations
-
"$2a$#{SCRYPT_ITERATION_INTEGER}$"
Class Method Summary collapse
-
.generate_key(secret_text, scrypt_salt) ⇒ Key
Key generators should first use the generate_salt method to create a Scrypt salt string and then submit it to this method together with a human generated password in order to derive a key.
-
.generate_scrypt_salt ⇒ String
Generate a secure random and unpredictable salt suitable for the SCrypt algorithm.
Class Method Details
.generate_key(secret_text, scrypt_salt) ⇒ Key
Key generators should first use the generate_salt method to create a Scrypt salt string and then submit it to this method together with a human generated password in order to derive a key.
The salt can be persisted and then resubmitted again to this method in order to regenerate the same key at any time in the future.
Generate a binary key from the scrypt password derivation function.
This differs from a server side password to hash usage in that we are interested in the 186bit key that scrypt produces. This method returns this reproducible key for use during symmetric encryption and decryption.
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/keytools/kdf.scrypt.rb', line 124 def self.generate_key secret_text, scrypt_salt binary_salt = Key.to_binary_from_bit_string( scrypt_salt ) puts "" puts $LOADED_FEATURES.grep(/openssl/) puts "" scrypt_key = OpenSSL::KDF.scrypt(secret_text, salt: binary_salt, N: 2**SCRYPT_ITERATION_INTEGER, r: 8, p: 1, length: 33) =begin hashed_secret = Scrypt::Engine.hash_secret( secret_text, to_scrypt_salt(scrypt_salt) ) encoded64_key = Scrypt::Password.new( hashed_secret ).to_s key_begin_index = SCRYPT_OUTPUT_TEXT_PREFIX.length + SCRYPT_SALT_LENGTH radix64_key_str = encoded64_key[ key_begin_index .. -1 ] key_length_mesg = "The scrypt key length should have #{SCRYPT_KEY_LENGTH} characters." raise RuntimeError, key_length_mesg unless radix64_key_str.length == SCRYPT_KEY_LENGTH return Key.new(radix64_key_str) =end return scrypt_key end |
.generate_scrypt_salt ⇒ String
Generate a secure random and unpredictable salt suitable for the SCrypt algorithm. SCrypt salts are recommended to contain 16 and 32 bytes inclusive. Here we opt for 24 bytes which unrolls to 192 bits which in turn is 32 base64 characters.
The SCRYPT_SALT_BYTE_LENGTH constant defines the number of random bytes required for a robust SCrypt salt.
The salt can be persisted and then resubmitted in order to regenerate the same key in the future.
89 90 91 |
# File 'lib/keytools/kdf.scrypt.rb', line 89 def self.generate_scrypt_salt return Key.to_random_bits( SCRYPT_SALT_BYTE_LENGTH ) end |