safedb 0.01.0001

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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