safedb 0.01.0001

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.yardopts +3 -0
  4. data/Gemfile +10 -0
  5. data/LICENSE +21 -0
  6. data/README.md +793 -0
  7. data/Rakefile +16 -0
  8. data/bin/safe +5 -0
  9. data/lib/configs/README.md +58 -0
  10. data/lib/extension/array.rb +162 -0
  11. data/lib/extension/dir.rb +35 -0
  12. data/lib/extension/file.rb +123 -0
  13. data/lib/extension/hash.rb +33 -0
  14. data/lib/extension/string.rb +572 -0
  15. data/lib/factbase/facts.safedb.net.ini +38 -0
  16. data/lib/interprete.rb +462 -0
  17. data/lib/keytools/PRODUCE_RAND_SEQ_USING_DEV_URANDOM.txt +0 -0
  18. data/lib/keytools/kdf.api.rb +243 -0
  19. data/lib/keytools/kdf.bcrypt.rb +265 -0
  20. data/lib/keytools/kdf.pbkdf2.rb +262 -0
  21. data/lib/keytools/kdf.scrypt.rb +190 -0
  22. data/lib/keytools/key.64.rb +326 -0
  23. data/lib/keytools/key.algo.rb +109 -0
  24. data/lib/keytools/key.api.rb +1391 -0
  25. data/lib/keytools/key.db.rb +330 -0
  26. data/lib/keytools/key.docs.rb +195 -0
  27. data/lib/keytools/key.error.rb +110 -0
  28. data/lib/keytools/key.id.rb +271 -0
  29. data/lib/keytools/key.ident.rb +243 -0
  30. data/lib/keytools/key.iv.rb +107 -0
  31. data/lib/keytools/key.local.rb +259 -0
  32. data/lib/keytools/key.now.rb +402 -0
  33. data/lib/keytools/key.pair.rb +259 -0
  34. data/lib/keytools/key.pass.rb +120 -0
  35. data/lib/keytools/key.rb +585 -0
  36. data/lib/logging/gem.logging.rb +132 -0
  37. data/lib/modules/README.md +43 -0
  38. data/lib/modules/cryptology/aes-256.rb +154 -0
  39. data/lib/modules/cryptology/amalgam.rb +70 -0
  40. data/lib/modules/cryptology/blowfish.rb +130 -0
  41. data/lib/modules/cryptology/cipher.rb +207 -0
  42. data/lib/modules/cryptology/collect.rb +138 -0
  43. data/lib/modules/cryptology/crypt.io.rb +225 -0
  44. data/lib/modules/cryptology/engineer.rb +99 -0
  45. data/lib/modules/mappers/dictionary.rb +288 -0
  46. data/lib/modules/storage/coldstore.rb +186 -0
  47. data/lib/modules/storage/git.store.rb +399 -0
  48. data/lib/session/fact.finder.rb +334 -0
  49. data/lib/session/require.gem.rb +112 -0
  50. data/lib/session/time.stamp.rb +340 -0
  51. data/lib/session/user.home.rb +49 -0
  52. data/lib/usecase/cmd.rb +487 -0
  53. data/lib/usecase/config/README.md +57 -0
  54. data/lib/usecase/docker/README.md +146 -0
  55. data/lib/usecase/docker/docker.rb +49 -0
  56. data/lib/usecase/edit/README.md +43 -0
  57. data/lib/usecase/edit/delete.rb +46 -0
  58. data/lib/usecase/export.rb +40 -0
  59. data/lib/usecase/files/README.md +37 -0
  60. data/lib/usecase/files/eject.rb +56 -0
  61. data/lib/usecase/files/file_me.rb +78 -0
  62. data/lib/usecase/files/read.rb +169 -0
  63. data/lib/usecase/files/write.rb +89 -0
  64. data/lib/usecase/goto.rb +57 -0
  65. data/lib/usecase/id.rb +36 -0
  66. data/lib/usecase/import.rb +157 -0
  67. data/lib/usecase/init.rb +63 -0
  68. data/lib/usecase/jenkins/README.md +146 -0
  69. data/lib/usecase/jenkins/jenkins.rb +208 -0
  70. data/lib/usecase/login.rb +71 -0
  71. data/lib/usecase/logout.rb +28 -0
  72. data/lib/usecase/open.rb +71 -0
  73. data/lib/usecase/print.rb +40 -0
  74. data/lib/usecase/put.rb +81 -0
  75. data/lib/usecase/set.rb +44 -0
  76. data/lib/usecase/show.rb +138 -0
  77. data/lib/usecase/terraform/README.md +91 -0
  78. data/lib/usecase/terraform/terraform.rb +121 -0
  79. data/lib/usecase/token.rb +35 -0
  80. data/lib/usecase/update/README.md +55 -0
  81. data/lib/usecase/update/rename.rb +180 -0
  82. data/lib/usecase/use.rb +41 -0
  83. data/lib/usecase/verse.rb +20 -0
  84. data/lib/usecase/view.rb +71 -0
  85. data/lib/usecase/vpn/README.md +150 -0
  86. data/lib/usecase/vpn/vpn.ini +31 -0
  87. data/lib/usecase/vpn/vpn.rb +54 -0
  88. data/lib/version.rb +3 -0
  89. data/safedb.gemspec +34 -0
  90. metadata +193 -0
@@ -0,0 +1,262 @@
1
+ #!/usr/bin/ruby
2
+ # coding: utf-8
3
+
4
+ module SafeDb
5
+
6
+
7
+ # PBKDF2 is a powerful leading <b>Key Derivation Function (KDF)</b> that exists to
8
+ # convert <b>low entropy</b> human created passwords into a high entropy key that
9
+ # is computationally infeasible to acquire through brute force.
10
+ #
11
+ # As human generated passwords have a relatively small key space, key derivation
12
+ # functions must be slow to compute with any implementation.
13
+ #
14
+ # PBKDF2 offers an <b>iteration count</b> that configures the number of iterations
15
+ # performed to create the key.
16
+ #
17
+ # <b>One million (1,000,000) should be the iteration count's lower bound.</b>
18
+ #
19
+ # == Upgrading the OpenSSL <em>pbkdf2_hmac</em> Behaviour
20
+ #
21
+ # As soon as the new Ruby and OpenSSL libraries become commonplace this class should
22
+ # be upgraded to use the <b>new and improved {OpenSSL::KDF.pbkdf2_hmac} behaviour</b>
23
+ # rather than {OpenSSL::PKCS5.pbkdf2_hmac}.
24
+ #
25
+ # The difficulty is in detecting the operating system's C libraries that are directly
26
+ # accessed for OpenSSL functionality. If the distinction can be made accurately, those
27
+ # with newer libraries can reap the benefits immediately.
28
+ #
29
+ # == PBKDF2 Cost Iteration Timings on an Intel i-5 Laptop
30
+ #
31
+ # An IBM ThinkPad was used to generate the timings.
32
+ #
33
+ # Memory RAM ~> 15GiB
34
+ # Processors ~> Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
35
+ #
36
+ # The timing results show that a prudent value is somewhere
37
+ # between one hundred thousand and ten million iterations.
38
+ #
39
+ # 9.6 seconds for 10,000,000 ten million iterations
40
+ # 0.96 seconds for 1,000,000 one million iterations
41
+ # 0.096 seconds for 100,000 one hundred thousand iterations
42
+ #
43
+ # Open key sets iteration counts for PBKDF2 in hexadecimal and
44
+ # a valid range starts at 1 and counts up in chunks of a hundred
45
+ # thousand (100,000).
46
+ #
47
+ # 1 ~> 100,000
48
+ # 5 ~> 500,000
49
+ # 10 ~> 1,000,000
50
+ # 16 ~> 16,000,000
51
+ # 256 ~> 256,000,000
52
+ #
53
+ # The maximum iteration multiplier allowed is 16,384.
54
+ class KeyPbkdf2
55
+
56
+
57
+ # <b>One million iterations</b> is necessary due to the
58
+ # growth of <b>GPU driven cloud based computing</b> power
59
+ # that is curently being honed by mining BitCoin and training
60
+ # neural networks.
61
+ #
62
+ # == PBKDF2 Cost Iteration Timings on an Intel i-5 Laptop
63
+ #
64
+ # An IBM ThinkPad was used to generate the timings.
65
+ #
66
+ # Memory RAM ~> 15GiB
67
+ # Processors ~> Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
68
+ #
69
+ # The timing results show that a prudent value is somewhere
70
+ # between one hundred thousand and ten million iterations.
71
+ #
72
+ # Open key sets iteration counts for PBKDF2 in hexadecimal and
73
+ # a valid range starts at 1 and counts up in chunks of a hundred
74
+ # thousand (100,000).
75
+ #
76
+ # 1 ~> 100,000
77
+ # 5 ~> 500,000
78
+ # 10 ~> 1,000,000
79
+ # 16 ~> 16,000,000
80
+ # 256 ~> 256,000,000
81
+ PBKDF2_ITERATION_MULTIPLIER = 1
82
+
83
+ # The quantity used to multiply the iteration multiplier by to
84
+ # gain the iteration count.
85
+ ONE_HUNDRED_THOUSAND = 100000
86
+
87
+
88
+ # Documentation for this algorithm says this about the key length.
89
+ #
90
+ # Make the key length <b>larger than or equal to the output length</b>
91
+ # of the <b>underlying digest function</b>, otherwise an attacker could
92
+ # simply try to brute-force the key.
93
+ #
94
+ # According to PKCS#5, security is limited by the output length of
95
+ # the underlying digest function, i.e. security is not improved if a
96
+ # key length strictly larger than the digest output length is chosen.
97
+ #
98
+ # Therefore, when using PKCS5 for password storage, it suffices to
99
+ # store values equal to the digest output length, nothing is gained
100
+ # by storing larger values.
101
+ PBKDF2_EXPORT_KEY_LENGTH = OpenSSL::Digest::SHA384.new.digest_length
102
+
103
+
104
+ # For a 384 bit digest the key length is 48 bytes and the bit length
105
+ # is 384 bits.
106
+ PBKDF2_EXPORT_BIT_LENGTH = PBKDF2_EXPORT_KEY_LENGTH * 8
107
+
108
+
109
+ # The documented recommended salt length in bytes for the PBKDF2
110
+ # algorithm is between <b>16 and 24 bytes</b>. The setting here is
111
+ # at the upper bound of that range.
112
+ PBKDF2_SALT_LENGTH_BYTES = 24
113
+
114
+
115
+ # Return a random cryptographic salt generated from twenty-four
116
+ # random bytes produced by a secure random number generator. The
117
+ # returned salt is primarily a Base64 encoded string that can be
118
+ # stored and then passed to the {KeyPbkdf2.generate_key} method.
119
+ #
120
+ # + ------------ + -------- + ------------ + ------------- +
121
+ # | | Bits | Bytes | Base64 |
122
+ # | ------------ | -------- | ------------ | ------------- |
123
+ # | PBKDF2 Salt | 192 Bits | 24 bytes | 32 characters |
124
+ # + ------------ + -------- + ------------ + ------------- +
125
+ #
126
+ # The leading part of the character sequence indicates the length
127
+ # of the salt in chunks of 100,000 and is plus sign separated.
128
+ #
129
+ # 42+12345678abcdefgh12345678ABCDEFGH ~> 4,200,000 iterations
130
+ # 9+12345678abcdefgh12345678ABCDEFGH ~> 900,000 iterations
131
+ # 100+12345678abcdefgh12345678ABCDEFGH ~> 10,000,000 iterations
132
+ #
133
+ # Note that the generate key method will convert the trailing 32
134
+ # base64 characters back into a <b>24 byte binary</b> string.
135
+ #
136
+ # @return [String]
137
+ # a relatively small iteration count multiplier separated from the
138
+ # main salt characters by a plus sign. The salt characters will
139
+ # consist of 32 base64 characters which can be stored and fed into
140
+ # the {generate_key}.
141
+ #
142
+ # These 32 characters are a representation of the twenty-four (24)
143
+ # randomly and securely generated bytes.
144
+ def self.generate_pbkdf2_salt
145
+
146
+ pbkdf2_salt = Key64.from_bits( Key.to_random_bits( PBKDF2_SALT_LENGTH_BYTES ) )
147
+ return "#{PBKDF2_ITERATION_MULTIPLIER}+#{pbkdf2_salt}"
148
+
149
+ end
150
+
151
+
152
+ # Generate a 128 bit binary key from the PBKDF2 password derivation
153
+ # function. The most important input to this function is the human
154
+ # generated key. The best responsibly sourced key with at least 95%
155
+ # entropy will contain about 40 characters spread randomly over the
156
+ # set of 95 typable characters.
157
+ #
158
+ # Aside from the human password the other inputs are
159
+ #
160
+ # - a base64 encoded randomly generated salt of 16 to 24 bytes
161
+ # - an iteration count of at least 1 million (due to GPU advances)
162
+ # - an output key length that is at least 16 bytes (128 bits)
163
+ # - a digest algorithm implementation (we use SHA512K)
164
+ #
165
+ # The {Key} returned by this method encapsulates the derived
166
+ # key of the byte (bit) length specified.
167
+ #
168
+ # <b>PBKDF2 Output Key Length Note</b>
169
+ #
170
+ # Documentation for this algorithm says this about the key length.
171
+ #
172
+ # Typically, the key length should be larger than or equal to the
173
+ # output length of the underlying digest function, otherwise an
174
+ # attacker could simply try to brute-force the key. According to
175
+ # PKCS#5, security is limited by the output length of the underlying
176
+ # digest function, i.e. security is not improved if a key length
177
+ # strictly larger than the digest output length is chosen.
178
+ #
179
+ # Therefore, when using PKCS5 for password storage, it suffices to
180
+ # store values equal to the digest output length, nothing is gained
181
+ # by storing larger values.
182
+ #
183
+ # <b>Upgrading the OpenSSL <em>pbkdf2_hmac</em> Behaviour</b>
184
+ #
185
+ # As soon as the new Ruby and OpenSSL libraries become commonplace this class should
186
+ # be upgraded to use the <b>new and improved {OpenSSL::KDF.pbkdf2_hmac} behaviour</b>
187
+ # rather than {OpenSSL::PKCS5.pbkdf2_hmac}.
188
+ #
189
+ # The difficulty is in detecting the operating system's C libraries that are directly
190
+ # accessed for OpenSSL functionality. If the distinction can be made accurately, those
191
+ # with newer libraries can reap the benefits immediately.
192
+ #
193
+ # @param human_secret [String]
194
+ # a robust human generated password with as much entropy as can
195
+ # be mustered. Remember that 40 characters spread randomly over
196
+ # the key space of about 95 characters and not relating to any
197
+ # dictionary word or name is the way to generate a powerful key
198
+ # that has embedded a near 100% entropy rating.
199
+ #
200
+ # @param pbkdf2_string [String]
201
+ # this is a relatively small iteration count multiplier separated
202
+ # from the main salt characters by a plus sign. The salt characters
203
+ # will consist of 32 base64 characters which can be stored and fed
204
+ # into the {generate_key}.
205
+ #
206
+ # The salt string presented here must have either been recently
207
+ # generated by {generate_pbkdf2salt} or read from a persistence
208
+ # store and resubmitted here in order to regenerate the same key.
209
+ #
210
+ # @return [Key]
211
+ # a key holder containing the key which can then be accessed via
212
+ # many different formats. The {Key} returned by this method
213
+ # encapsulates the derived key with the specified byte count.
214
+ def self.generate_key human_secret, pbkdf2_string
215
+
216
+ KeyError.not_new pbkdf2_string, "PBKDF2 Algorithm Salt"
217
+ multiplier = pbkdf2_string.split("+")[0].to_i
218
+ pbkdf2_salt = pbkdf2_string.split("+")[1]
219
+
220
+ mult_msg = "Iteration multiplier is an integer from 1 to 16,384 not [#{multiplier}]."
221
+ raise ArgumentError, mult_msg_msg unless( multiplier > 0 && multiplier < 16385 )
222
+ iteration_count = multiplier * ONE_HUNDRED_THOUSAND
223
+
224
+ binary_salt = Key.to_binary_from_bit_string( Key64.to_bits( pbkdf2_salt ) )
225
+ err_msg = "Expected salt of #{PBKDF2_SALT_LENGTH_BYTES} bytes not #{binary_salt.length}."
226
+ raise ArgumentError, err_msg unless binary_salt.length == PBKDF2_SALT_LENGTH_BYTES
227
+
228
+ pbkdf2_key = OpenSSL::PKCS5.pbkdf2_hmac(
229
+ human_secret,
230
+ binary_salt,
231
+ iteration_count,
232
+ PBKDF2_EXPORT_KEY_LENGTH,
233
+ OpenSSL::Digest::SHA384.new
234
+ )
235
+
236
+ return Key.from_binary( pbkdf2_key )
237
+
238
+ end
239
+
240
+
241
+ private
242
+
243
+
244
+ # ---
245
+ # --- Timings Code
246
+ # ---
247
+ # --- chopped_radix64_key = NIL
248
+ # --- require 'benchmark'
249
+ # --- timings = Benchmark.measure {
250
+ # ---
251
+ # --- -- wrapped up code block
252
+ # ---
253
+ # --- }
254
+ # ---
255
+ # --- log.info(x) { "PBKDF2 key generation timings ~> #{timings}" }
256
+ # ---
257
+
258
+
259
+ end
260
+
261
+
262
+ end
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/ruby
2
+ # coding: utf-8
3
+
4
+ module SafeDb
5
+
6
+
7
+ # SCrypt is a <b>Key Derivation Function (KDF)</b> with a reliable OpenSSL
8
+ # implementation that converts <b>low entropy</b> password-like text to a
9
+ # high entropy key that is computationally infeasible to acquire through brute
10
+ # force.
11
+ #
12
+ # SCrypt is incredibly resistant to attacks using dedicated hardware with
13
+ # massive memory to boot.
14
+ #
15
+ class KdfSCrypt
16
+
17
+ # SCrypt salts are recommended to contain 16 and 32 bytes
18
+ # inclusive. Here we opt for 24 bytes which unrolls out to
19
+ # 192 bits which serializes into 32 base64 characters.
20
+ SCRYPT_SALT_BYTE_LENGTH = 24
21
+
22
+ # The iteration count is determined using the powers of
23
+ # two so if the iteration integer is 12 there will be two
24
+ # to the power of 12 ( 2^12 ) giving 4096 iterations.
25
+ # The minimum number is 4 (16 iterations) and the max is 31.
26
+ # @example
27
+ # Configuring 16 into this directive results in
28
+ # 2^16 = 65,536 iterations
29
+ #
30
+ # This is a safe default and will slow the derivation time
31
+ # to about a second on a powerful 2020 laptop.
32
+ SCRYPT_ITERATION_INTEGER = 16
33
+
34
+ # The scrypt algorithm produces a key that is 181 bits in
35
+ # length. The algorithm then converts the binary 181 bits
36
+ # into a (6-bit) Radix64 character.
37
+ #
38
+ # 181 / 6 = 30 remainder 1 (so 31 characters are needed).
39
+ SCRYPT_KEY_LENGTH = 31
40
+
41
+
42
+ # When the key is transported using a 64 character set where
43
+ # each character is represented by 6 bits - the Scrypt key
44
+ # expands to 186 bits rather than the original 181 bits.
45
+ #
46
+ # This expansion is because of the remainder.
47
+ #
48
+ # 181 bits divided by 6 is 30 characters plus 1 character
49
+ # for the extra bit.
50
+ #
51
+ # The 31 transported characters then appear as
52
+ # 31 times 6 which equals 186 bits.
53
+ SCRYPT_KEY_TRANSPORT_LENGTH = 186
54
+
55
+ # The scrypt algorithm salt string should be 22 characters
56
+ # and may include forward slashes and periods.
57
+ SCRYPT_SALT_LENGTH = 22
58
+
59
+ # Scrypt outputs a single line of text that holds the prefix
60
+ # then the Radix64 encoded salt and finally the Radix64
61
+ # encoded hash key.
62
+ #
63
+ # The prefix consists of <b>two sections</b> sandwiched within
64
+ # two dollar <b>$</b> signs at the extremeties and a third dollar
65
+ # separating them.
66
+ #
67
+ # The two sections are the
68
+ # - Scrypt algorithm <b>version number</b> (2a or 2b) and
69
+ # - a power of 2 integer defining the no. of interations
70
+ SCRYPT_OUTPUT_TEXT_PREFIX = "$2a$#{SCRYPT_ITERATION_INTEGER}$"
71
+
72
+
73
+ # Generate a secure random and unpredictable salt suitable for
74
+ # the SCrypt algorithm. SCrypt salts are recommended to contain
75
+ # 16 and 32 bytes inclusive. Here we opt for 24 bytes which
76
+ # unrolls to 192 bits which in turn is 32 base64 characters.
77
+ #
78
+ # The {SafeDb::KdfSCrypt::SCRYPT_SALT_BYTE_LENGTH} constant
79
+ # defines the <b>number of random bytes</b> required for a robust
80
+ # SCrypt salt.
81
+ #
82
+ # The salt can be persisted and then resubmitted in order to
83
+ # regenerate the same key in the future.
84
+ #
85
+ # @return [String]
86
+ # the salt in a bit string format which can be converted to
87
+ # in order to feed the derivation function or indeed converted
88
+ # to base64 in order to persist it.
89
+ def self.generate_scrypt_salt
90
+ return Key.to_random_bits( SCRYPT_SALT_BYTE_LENGTH )
91
+ end
92
+
93
+
94
+
95
+ # Key generators should first use the {generate_salt} method to create
96
+ # a Scrypt salt string and then submit it to this method together with
97
+ # a human generated password in order to derive a key.
98
+ #
99
+ # The salt can be persisted and then resubmitted again to this method
100
+ # in order to regenerate the same key at any time in the future.
101
+ #
102
+ # Generate a binary key from the scrypt password derivation function.
103
+ #
104
+ # This differs from a server side password to hash usage in that we
105
+ # are interested in the 186bit key that scrypt produces. This method
106
+ # returns this reproducible key for use during symmetric encryption and
107
+ # decryption.
108
+ #
109
+ # @param secret_text [String]
110
+ # a robust human generated password with as much entropy as can
111
+ # be mustered. Remember that 40 characters spread randomly over
112
+ # the key space of about 90 characters and not relating to any
113
+ # dictionary word or name is the way to generate a powerful key
114
+ # that has embedded a near 100% entropy rating.
115
+ #
116
+ # @param scrypt_salt [String]
117
+ # the salt string that has either been recently generated via the
118
+ # {generate_salt} method or read from a persistence store and
119
+ # resubmitted here (in the future) to regenerate the same key.
120
+ #
121
+ # @return [Key]
122
+ # a key holder containing the key which can then be accessed via
123
+ # many different formats.
124
+ def self.generate_key secret_text, scrypt_salt
125
+
126
+ binary_salt = Key.to_binary_from_bit_string( scrypt_salt )
127
+
128
+ require "openssl"
129
+
130
+ puts ""
131
+ puts $LOADED_FEATURES.grep(/openssl/)
132
+ puts ""
133
+
134
+ scrypt_key = OpenSSL::KDF.scrypt(secret_text, salt: binary_salt, N: 2**SCRYPT_ITERATION_INTEGER, r: 8, p: 1, length: 33)
135
+
136
+
137
+
138
+ =begin
139
+ hashed_secret = Scrypt::Engine.hash_secret( secret_text, to_scrypt_salt(scrypt_salt) )
140
+ encoded64_key = Scrypt::Password.new( hashed_secret ).to_s
141
+ key_begin_index = SCRYPT_OUTPUT_TEXT_PREFIX.length + SCRYPT_SALT_LENGTH
142
+ radix64_key_str = encoded64_key[ key_begin_index .. -1 ]
143
+ key_length_mesg = "The scrypt key length should have #{SCRYPT_KEY_LENGTH} characters."
144
+ raise RuntimeError, key_length_mesg unless radix64_key_str.length == SCRYPT_KEY_LENGTH
145
+
146
+ return Key.new(radix64_key_str)
147
+ =end
148
+ return scrypt_key
149
+ end
150
+
151
+
152
+
153
+ private
154
+
155
+
156
+ def self.scrypt_test_method
157
+
158
+ puts ""
159
+ puts "##############################################################################"
160
+
161
+ key_count = 20
162
+ for n in 0 .. key_count
163
+ scrypt_saltbits = SafeDb::KdfSCrypt.generate_scrypt_salt
164
+ scrypt_key = SafeDb::KdfSCrypt.generate_key( "abonekanoby", scrypt_saltbits )
165
+ scrypt_saltchar = SafeDb::Key64.from_bits( scrypt_saltbits )
166
+ puts "#{n} Salt => #{scrypt_saltchar} (#{scrypt_saltchar.length}) => Key => #{scrypt_key} (#{scrypt_key.length})"
167
+ end
168
+
169
+ puts "##############################################################################"
170
+ puts ""
171
+
172
+ end
173
+
174
+
175
+
176
+ def self.to_scrypt_salt the_salt
177
+ return SCRYPT_OUTPUT_TEXT_PREFIX + the_salt
178
+ end
179
+
180
+ def self.assert_scrypt_salt the_salt
181
+ raise RuntimeError, "scrypt salt not expected to be nil." if the_salt.nil?
182
+ salt_length_msg = "A scrypt salt is expected to contain #{SCRYPT_SALT_LENGTH} characters."
183
+ raise RuntimeError, salt_length_msg unless the_salt.length == SCRYPT_SALT_LENGTH
184
+ end
185
+
186
+
187
+ end
188
+
189
+
190
+ end