opensecret 0.0.9925 → 0.0.9949

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +656 -40
  3. data/lib/configs/README.md +58 -0
  4. data/lib/extension/file.rb +67 -0
  5. data/lib/extension/string.rb +10 -0
  6. data/lib/factbase/facts.opensecret.io.ini +1 -0
  7. data/lib/interprete.rb +334 -61
  8. data/lib/keytools/PRODUCE_RAND_SEQ_USING_DEV_URANDOM.txt +0 -0
  9. data/lib/keytools/kdf.api.rb +9 -15
  10. data/lib/keytools/kdf.bcrypt.rb +69 -19
  11. data/lib/keytools/kdf.pbkdf2.rb +112 -23
  12. data/lib/keytools/key.api.rb +146 -36
  13. data/lib/keytools/key.db.rb +94 -29
  14. data/lib/keytools/key.id.rb +1 -1
  15. data/lib/keytools/key.ident.rb +243 -0
  16. data/lib/keytools/key.local.rb +62 -68
  17. data/lib/keytools/key.pass.rb +2 -2
  18. data/lib/keytools/key.rb +2 -28
  19. data/lib/modules/{cryptology.md → README.md} +0 -0
  20. data/lib/session/fact.finder.rb +65 -428
  21. data/lib/session/time.stamp.rb +1 -28
  22. data/lib/usecase/cmd.rb +127 -54
  23. data/lib/usecase/config/README.md +57 -0
  24. data/lib/usecase/docker/README.md +146 -0
  25. data/lib/usecase/docker/docker.rb +49 -0
  26. data/lib/usecase/edit/README.md +43 -0
  27. data/lib/usecase/edit/delete.rb +46 -0
  28. data/lib/usecase/export.rb +40 -0
  29. data/lib/usecase/files/README.md +37 -0
  30. data/lib/usecase/files/eject.rb +56 -0
  31. data/lib/usecase/files/file_me.rb +78 -0
  32. data/lib/usecase/files/read.rb +169 -0
  33. data/lib/usecase/files/write.rb +89 -0
  34. data/lib/usecase/goto.rb +57 -0
  35. data/lib/usecase/id.rb +1 -1
  36. data/lib/usecase/import.rb +13 -30
  37. data/lib/usecase/init.rb +2 -17
  38. data/lib/usecase/jenkins/README.md +146 -0
  39. data/lib/usecase/jenkins/crazy_ruby_post_attempt.OLD +234 -0
  40. data/lib/usecase/jenkins/jenkins.rb +208 -0
  41. data/lib/usecase/login.rb +6 -5
  42. data/lib/usecase/logout.rb +1 -3
  43. data/lib/usecase/open.rb +11 -66
  44. data/lib/usecase/print.rb +40 -0
  45. data/lib/usecase/put.rb +34 -156
  46. data/lib/usecase/set.rb +2 -4
  47. data/lib/usecase/show.rb +138 -0
  48. data/lib/usecase/terraform/README.md +91 -0
  49. data/lib/usecase/terraform/terraform.rb +121 -0
  50. data/lib/usecase/token.rb +4 -80
  51. data/lib/usecase/update/README.md +55 -0
  52. data/lib/usecase/update/rename.rb +180 -0
  53. data/lib/usecase/use.rb +1 -3
  54. data/lib/usecase/verse.rb +20 -0
  55. data/lib/usecase/view.rb +71 -0
  56. data/lib/usecase/vpn/README.md +150 -0
  57. data/lib/usecase/vpn/vpn.ini +31 -0
  58. data/lib/usecase/vpn/vpn.rb +54 -0
  59. data/lib/version.rb +1 -1
  60. data/opensecret.gemspec +3 -4
  61. metadata +34 -35
  62. data/.travis.yml +0 -5
  63. data/CODE_OF_CONDUCT.md +0 -74
  64. data/LICENSE.txt +0 -21
  65. data/bin/ops +0 -20
  66. data/lib/keytools/binary.map.rb +0 -294
  67. data/lib/keytools/doc.conversion.to.ones.and.zeroes.ruby +0 -179
  68. data/lib/keytools/doc.rsa.radix.binary-mapping.ruby +0 -190
  69. data/lib/keytools/doc.star.schema.strategy.txt +0 -77
  70. data/lib/keytools/doc.using.pbkdf2.kdf.ruby +0 -95
  71. data/lib/keytools/doc.using.pbkdf2.pkcs.ruby +0 -266
  72. data/lib/keytools/key.mach.rb +0 -248
  73. data/lib/keytools/keydebug.txt +0 -295
  74. data/lib/modules/cryptology/open.bcrypt.rb +0 -170
  75. data/lib/usecase/read.rb +0 -89
  76. data/lib/usecase/safe.rb +0 -92
@@ -17,7 +17,6 @@ module OpenSession
17
17
 
18
18
  # Return two digit [mo] month index from 01 to 12.
19
19
  # @example 02 => in February
20
- #
21
20
  def self.mo
22
21
  return Stamp.instance.time_now.strftime "%m"
23
22
  end
@@ -25,47 +24,37 @@ module OpenSession
25
24
 
26
25
  # Return three character abbreviated month name.
27
26
  # @example feb => in February
28
- #
29
27
  def self.mmm
30
28
  return Stamp.instance.time_now.strftime( "%b" ).downcase
31
29
  end
32
30
 
33
31
 
34
- #
35
32
  # Return three character abbreviated day of week.
36
33
  # @example tue => on Tuesday
37
- #
38
34
  def self.ddd
39
35
  return Stamp.instance.time_now.strftime( "%a" ).downcase
40
36
  end
41
37
 
42
38
 
43
- #
44
39
  # Return two digit (character) hour of day from 00 to 23.
45
40
  # @example 22 => between 22.00.00 and 22.59.59 inclusive
46
- #
47
41
  def self.hh
48
42
  return Stamp.instance.time_now.strftime "%H"
49
43
  end
50
44
 
51
45
 
52
- #
53
46
  # Return two digit minute of hour from [00] to [59].
54
- #
55
47
  def self.mm
56
48
  return Stamp.instance.time_now.strftime "%M"
57
49
  end
58
50
 
59
51
 
60
- #
61
52
  # Return two digit second of minute from [00] to [59].
62
- #
63
53
  def self.ss
64
54
  return Stamp.instance.time_now.strftime "%S"
65
55
  end
66
56
 
67
57
 
68
- #
69
58
  # Return a [3 digit] second and tenth of second
70
59
  # representation.
71
60
  #
@@ -90,35 +79,27 @@ module OpenSession
90
79
  #
91
80
  # => 3 chars
92
81
  # => 495
93
- #
94
- #
95
82
  def self.sst
96
83
  millisec_string = Stamp.instance.time_now.strftime "%L"
97
84
  return "#{ss}#{millisec_string[0]}"
98
85
  end
99
86
 
100
87
 
101
- #
102
88
  # Return the [two] digit year (eg 19 for 2019).
103
89
  # that we are currently in.
104
- #
105
90
  def self.yy
106
91
  return Stamp.instance.time_now.strftime("%Y")[2..-1]
107
92
  end
108
93
 
109
94
 
110
- #
111
95
  # Return the [four] digit year (eg 2019)
112
96
  # that we are currently in.
113
- #
114
97
  def self.yyyy
115
98
  return Stamp.instance.time_now.strftime("%Y")
116
99
  end
117
100
 
118
101
 
119
- # ------------------------------------------------- -- #
120
- # Return 3 digit julian day of year [001] to [366]. -- #
121
- # ------------------------------------------------- -- #
102
+ # Return 3 digit julian day of year [001] to [366].
122
103
  def self.jjj
123
104
  return Stamp.instance.time_now.strftime "%j"
124
105
  end
@@ -140,7 +121,6 @@ module OpenSession
140
121
  end
141
122
 
142
123
 
143
- #
144
124
  # Given two integer parameters (month index and 4 digit year) representing
145
125
  # the month in question this method returns the [PREVIOUS MONTHS] character
146
126
  # amalgam in the format [yymo_mmm] where
@@ -165,7 +145,6 @@ module OpenSession
165
145
  # returns char => 1812.dec
166
146
  # 4 parameters => 1, 2019
167
147
  # representing => January, 2019
168
- #
169
148
  def self.previous_month_chars this_month_index, this_4digit_year
170
149
 
171
150
  prev_month_index = this_month_index == 1 ? 12 : ( this_month_index - 1 )
@@ -178,7 +157,6 @@ module OpenSession
178
157
 
179
158
  end
180
159
 
181
- #
182
160
  # Using the current class time this method returns
183
161
  # the character amalgam for the [PREVIOUS MONTH] in
184
162
  # the format [yymo_mmm] where
@@ -201,7 +179,6 @@ module OpenSession
201
179
  #
202
180
  # returns => 1812.dec
203
181
  # if this month is => January 2019
204
- #
205
182
  def self.yymo_mmm_prev
206
183
  return previous_month_chars mo.to_i, yyyy.to_i
207
184
  end
@@ -220,13 +197,11 @@ module OpenSession
220
197
  # @example
221
198
  # => 1525
222
199
  # => 03:25 pm
223
- #
224
200
  def self.hhmm
225
201
  return "#{hh}#{mm}"
226
202
  end
227
203
 
228
204
 
229
- #
230
205
  # Return the time of day to a TENTH of a second accuracy.
231
206
  # [8] characters will always be returned with the 5th one
232
207
  # being the (period) separator.
@@ -246,7 +221,6 @@ module OpenSession
246
221
  #
247
222
  # => 8 chars
248
223
  # => 1723.495
249
- #
250
224
  def self.hhmm_sst
251
225
  return "#{hhmm}.#{sst}"
252
226
  end
@@ -281,7 +255,6 @@ module OpenSession
281
255
  #
282
256
  # => 8 chars
283
257
  # => 1723.495
284
- #
285
258
  def self.yyjjj_hhmm_sst
286
259
  return "#{yyjjj}.#{hhmm}.#{sst}"
287
260
  end
@@ -10,7 +10,7 @@ module OpenSecret
10
10
  #
11
11
  # == Common Use Case Behaviour
12
12
  #
13
- # This {OpenSecret::Command} use case is designed to be extended and does preparatory
13
+ # This {OpenSecret::UseCase} use case is designed to be extended and does preparatory
14
14
  # work to create favourable and useful conditions to make use cases readable,
15
15
  # less repetitive, simpler and concise.
16
16
  #
@@ -26,21 +26,50 @@ module OpenSecret
26
26
  # - {stash} put directive key/value pair in default section
27
27
  # - {read} read the value at key_name from the parameter section
28
28
  # - {write} put directive key/value pair in parameter section
29
- class Command
30
- =begin
31
- # ---> rename from [Command] to [UseCase]
32
- # ---> rename from [Command] to [UseCase]
33
- # ---> rename from [Command] to [UseCase]
34
- # ---> rename from [Command] to [UseCase]
35
- # ---> rename from [Command] to [UseCase]
36
- # ---> rename from [Command] to [UseCase]
37
- =end
29
+ class UseCase
30
+
31
+ # This variable should be set to true if the use case call
32
+ # originates from a shell different from the one through which
33
+ # the login ocurred.
34
+ #
35
+ # To proceed, the shell that hosted the safe login must be a
36
+ # parent or at least an ancestor of this shell.
37
+ #
38
+ # This variable need not be set if the login shell is the direct
39
+ # parent of this one (the every day manual usage scenario).
40
+ #
41
+ # If however the login occurred from a grand or great grandparent
42
+ # shell (as is the case when nested scripts make an agent-like call),
43
+ # this variable must be set to true.
44
+ attr_writer :from_script
45
+
46
+ # This prefix denotes keys and their values should be posted as environment
47
+ # variables within the context (for example terraform) before instigating the
48
+ # main action like terraform apply.
49
+ ENV_VAR_PREFIX_A = "evar."
50
+ ENV_VAR_PREFIX_B = "@evar."
51
+
52
+ # This prefix precedes keynames whose map value represents a file object.
53
+ FILE_KEY_PREFIX = "file::"
54
+
55
+ # The base64 encoded representation of the file content is placed into
56
+ # a map with this keyname.
57
+ FILE_CONTENT_KEY = "content64"
58
+
59
+ # The file base name is placed into a map with this keyname.
60
+ FILE_NAME_KEY = "filename"
61
+
62
+
63
+ # This is the root command typed into the shell to invoke one of the
64
+ # opensecret use cases.
65
+ COMMANDMENT = "safe"
66
+
38
67
 
39
68
  # The name of the environment variable that will hold the session token
40
69
  # generated by {self.generate_session_token}. This environment variable
41
70
  # is typically instantiated either manually (for ad-hoc use) or through
42
71
  # media such as dot profile.
43
- ENV_VAR_KEY_NAME = "OPEN_SESSION_TOKEN"
72
+ ENV_VAR_KEY_NAME = "SAFE_TTY_TOKEN"
44
73
 
45
74
 
46
75
  # If and when this command line credentials management app needs to write
@@ -48,6 +77,33 @@ module OpenSecret
48
77
  # constant to denote the (off-home) directory name.
49
78
  APP_DIR_NAME = "opensecret.io"
50
79
 
80
+
81
+ # Get the master database. This behaviour can only complete
82
+ # correctly if a successful login precedes this call either
83
+ # in this or an ancestral shell environment.
84
+ #
85
+ # @return [Hash]
86
+ # the hash data structure returned represents the master
87
+ # database.
88
+ def get_master_database
89
+
90
+ begin
91
+
92
+ log.info(x) { "Request for master db with from_script set to #{@from_script}" }
93
+ return OpenKey::KeyApi.read_master_db( @from_script )
94
+
95
+ rescue OpenSSL::Cipher::CipherError => e
96
+
97
+ log.fatal(x) { "Exception getting master db for the safe book." }
98
+ log.fatal(x) { "The from_script parameter came set as [ #{@from_script} ]" }
99
+ log.fatal(x) { "The exception message is ~> [[ #{e.message} ]]" }
100
+ e.backtrace.log_lines
101
+ abort e.message
102
+
103
+ end
104
+
105
+ end
106
+
51
107
  # The path to the initial configuration file below the user's home
52
108
  # directory. The directory name the configuration file sits in is
53
109
  # a dot prefixed context name derived from the value inside the
@@ -96,7 +152,6 @@ module OpenSecret
96
152
  # set a human readable string and then throw an exception.
97
153
  def check_pre_conditions
98
154
 
99
-
100
155
  begin
101
156
 
102
157
  pre_validation
@@ -112,6 +167,11 @@ module OpenSecret
112
167
  abort e.message
113
168
  end
114
169
 
170
+ end
171
+
172
+
173
+ # Override me if you need to
174
+ def pre_validation
115
175
 
116
176
  end
117
177
 
@@ -177,23 +237,20 @@ module OpenSecret
177
237
  # use case classes.
178
238
  def initialize
179
239
 
240
+ class_name = self.class.name.split(":").last.downcase
241
+ is_no_token_usecase = [ "token", "init", "id" ].include? class_name
242
+ return if is_no_token_usecase
180
243
 
181
- class_name = self.class.name.downcase.split(":").last
182
- is_pre_init_usecase = [ "safe", "store", "email" ].include? class_name
183
- return if is_pre_init_usecase
244
+ exit(100) unless ops_key_exists?
184
245
 
185
- @ucid_str = self.class.name.do_flatten
186
- log.info(x) { "Usecase class [self.class.name] converted to => #{@ucid_str}" }
187
- @ucid_sym = @ucid_str.gsub(".", "_").to_sym
246
+ fact_filepath = File.sister_filepath( self, "ini", :execute )
247
+ log.info(x) { "Search location for INI factfile is [#{fact_filepath}]" }
248
+ return unless File.exists?( fact_filepath )
188
249
 
189
- OpenSession::FactFind.instance.instantiate @ucid_str
190
- OpenSession::FactFind.instance.assimilate "facts.opensecret.io.ini"
191
-
192
- @c = OpenSession::FactFind.instance.f
193
- @i = OpenSession::FactFind.instance.i
194
- @p = OpenSession::FactFind.instance.f[@ucid_sym]
195
-
196
- log.info(x) { "assimilated [#{@p.length}] facts specific to the [#{@ucid_str}] use case." }
250
+ @facts = FactFind.new()
251
+ add_secret_facts @facts
252
+ @facts.assimilate_ini_file( fact_filepath )
253
+ @dictionary = @facts.f[ @facts.to_symbol( class_name ) ]
197
254
 
198
255
  end
199
256
 
@@ -232,6 +289,22 @@ module OpenSecret
232
289
  APPLICATION_GITHUB_URL = "https://github.io/opensecret.io"
233
290
 
234
291
 
292
+ def add_secret_facts fact_db
293
+
294
+ master_db = get_master_database()
295
+ raise ArgumentError.new "There is no open chapter here." if unopened_envelope?( master_db )
296
+ chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
297
+ verse_id = master_db[ KEY_PATH ]
298
+ chapter_data = OpenKey::KeyDb.from_json( OpenKey::KeyApi.content_unlock( master_db[ chapter_id ] ) )
299
+ mini_dictionary = chapter_data[ master_db[ KEY_PATH ] ]
300
+
301
+ mini_dictionary.each do | key_str, value_str|
302
+ fact_db.assimilate_fact( "secrets", key_str, value_str )
303
+ end
304
+
305
+ end
306
+
307
+
235
308
  def create_header()
236
309
 
237
310
  return OpenKey::KeyApi.format_header(
@@ -258,9 +331,9 @@ module OpenSecret
258
331
  puts "To automate this step see the documentation."
259
332
  puts "To create the key run the below command."
260
333
  puts ""
261
- puts " export OPEN_SESSION_TOKEN=`ops token`"
334
+ puts " export #{ENV_VAR_KEY_NAME}=`#{COMMANDMENT} token`"
262
335
  puts ""
263
- puts "Those are backticks surrounding `ops token`"
336
+ puts "Those are backticks surrounding `#{COMMANDMENT} token`"
264
337
  puts "Not apostrophes."
265
338
  puts ""
266
339
 
@@ -304,25 +377,25 @@ module OpenSecret
304
377
  def print_unopened_envelope()
305
378
 
306
379
  puts ""
307
- puts "Oops - before creating, reading or changing data you"
380
+ puts "Problem - before creating, reading or changing data you"
308
381
  puts "must first open a path to it like this."
309
382
  puts ""
310
- puts " ops open email.accounts joe@gmail.com"
383
+ puts " #{COMMANDMENT} open email.accounts joe@gmail.com"
311
384
  puts ""
312
385
  puts " then you put data at that path"
313
386
  puts ""
314
- puts " ops put username joebloggs"
315
- puts " ops put password jo3s-s3cr3t"
316
- puts " ops put phone-no 07123456789"
317
- puts " ops put question \"Mums maiden name\""
387
+ puts " #{COMMANDMENT} put username joebloggs"
388
+ puts " #{COMMANDMENT} put password jo3s-s3cr3t"
389
+ puts " #{COMMANDMENT} put phone-no 07123456789"
390
+ puts " #{COMMANDMENT} put question \"Mums maiden name\""
318
391
  puts ""
319
392
  puts " and why not read it back"
320
393
  puts ""
321
- puts " ops get password"
394
+ puts " #{COMMANDMENT} get password"
322
395
  puts ""
323
396
  puts " then close the path."
324
397
  puts ""
325
- puts " ops close"
398
+ puts " #{COMMANDMENT} close"
326
399
  puts ""
327
400
 
328
401
  end
@@ -333,11 +406,11 @@ module OpenSecret
333
406
  puts ""
334
407
  puts "We are already logged in. Open a secret envelope, put, then seal."
335
408
  puts ""
336
- puts " ops open aws.credentials:s3reader"
337
- puts " ops put access_key ABCD1234"
338
- puts " ops put secret_key FGHIJ56789"
339
- puts " ops put region_key eu-central-1"
340
- puts " ops seal"
409
+ puts " #{COMMANDMENT} open aws.credentials:s3reader"
410
+ puts " #{COMMANDMENT} put access_key ABCD1234"
411
+ puts " #{COMMANDMENT} put secret_key FGHIJ56789"
412
+ puts " #{COMMANDMENT} put region_key eu-central-1"
413
+ puts " #{COMMANDMENT} seal"
341
414
  puts ""
342
415
 
343
416
  end
@@ -350,7 +423,7 @@ module OpenSecret
350
423
  puts "Your domain [#{@domain_name}] is already setup."
351
424
  puts "You should already know the password."
352
425
  puts ""
353
- puts " ops login #{@domain_name}"
426
+ puts " #{COMMANDMENT} login #{@domain_name}"
354
427
  puts ""
355
428
 
356
429
  end
@@ -363,7 +436,7 @@ module OpenSecret
363
436
  puts "The protector keys for [#{@domain_name}] have been setup."
364
437
  puts "From now on you simply login to use this domain."
365
438
  puts ""
366
- puts " ops login #{@domain_name}"
439
+ puts " #{COMMANDMENT} login #{@domain_name}"
367
440
  puts ""
368
441
 
369
442
  end
@@ -375,7 +448,7 @@ module OpenSecret
375
448
  puts "Please initialize the app domain on this machine."
376
449
  puts "Give a domain name and a folder for key storage."
377
450
  puts ""
378
- puts " ops init <domain_name> \"$HOME/open.world\""
451
+ puts " #{COMMANDMENT} init <domain_name> \"$HOME/open.world\""
379
452
  puts ""
380
453
 
381
454
  end
@@ -386,11 +459,11 @@ module OpenSecret
386
459
  puts ""
387
460
  puts "Success - now open a secret envelope, put, then seal."
388
461
  puts ""
389
- puts " ops open aws.credentials:s3reader"
390
- puts " ops put access_key ABCD1234"
391
- puts " ops put secret_key FGHIJ56789"
392
- puts " ops put region_key eu-central-1"
393
- puts " ops seal"
462
+ puts " #{COMMANDMENT} open aws.credentials:s3reader"
463
+ puts " #{COMMANDMENT} put access_key ABCD1234"
464
+ puts " #{COMMANDMENT} put secret_key FGHIJ56789"
465
+ puts " #{COMMANDMENT} put region_key eu-central-1"
466
+ puts " #{COMMANDMENT} seal"
394
467
  puts ""
395
468
 
396
469
  end
@@ -401,11 +474,11 @@ module OpenSecret
401
474
  puts ""
402
475
  puts "Success - you are logged in."
403
476
  puts ""
404
- puts " ops open aws.credentials:s3reader"
405
- puts " ops put access_key ABCD1234"
406
- puts " ops put secret_key FGHIJ56789"
407
- puts " ops put region_key eu-central-1"
408
- puts " ops seal"
477
+ puts " #{COMMANDMENT} open aws.credentials:s3reader"
478
+ puts " #{COMMANDMENT} put access_key ABCD1234"
479
+ puts " #{COMMANDMENT} put secret_key FGHIJ56789"
480
+ puts " #{COMMANDMENT} put region_key eu-central-1"
481
+ puts " #{COMMANDMENT} seal"
409
482
  puts ""
410
483
 
411
484
  end
@@ -0,0 +1,57 @@
1
+
2
+ # Safe | Increasing Key Derivation Function Cost
3
+
4
+ Safe uses two **key derivation functions** (**BCrypt** and **PBKDF2**) to transform the human sourced password into a key. The only role the resulting key plays is the encryption and decryption of a large **highly random computer generated key** which in turn protects the **master database**.
5
+
6
+ ### Why are two (2) key derivation algorithms used?
7
+
8
+ Your credentials are still safe even in the rare case of a successful analytical attack being discovered on one of the algorithms.
9
+
10
+ ## Why High Computational Costs are Desirable?
11
+
12
+ Unlike most algorithms, key derivation functions **work best when they run slowly!** This protects against brute force attacks where attackers use "rainbow tables" or try to iterate over common passwords in an attempt to rederive the key.
13
+
14
+ Your responsibility is to make **safe as slow as is tolerable** by increasing the number of iterations required to derive each key.
15
+
16
+ ## Safe | Increasing the Cost of Both Key Derivation Functions
17
+
18
+ You should increase the cost of **safe's** key derivation functions until safe commands run as slow as is tolerably and no less!
19
+
20
+ ```bash
21
+ safe cost bcrypt 3
22
+ safe cost pbkdf2 4
23
+ ```
24
+
25
+ Both algorithms can be configured with a cost parameter from 1 to 7 inclusive. The default cost is 1 for both and is moderately secure and runs as slowly as is tolerable on an IBM ThinkPad laptop with an Intel Pentium i5 processor with 16G of RAM.
26
+
27
+ Note that PBKDF2 has no maximum. BCrypt limits the cost to 2^16.
28
+
29
+ <pre>
30
+ -------- - ------------ - --------------- - --------------------- - ---------------- -
31
+ | Cost | BCrypt | BCrypt | PBKDF2 | PBKDF2 |
32
+ | | Cost | Iterations | Cost | Iterations |
33
+ | ------ - ------------ - --------------- - --------------------- - ---------------- |
34
+ | 1 | 2^10 | 1,024 | 3^0 x 100,000 | 100,000 |
35
+ | 2 | 2^11 | 2,048 | 3^1 x 100,000 | 300,000 |
36
+ | 3 | 2^12 | 4,096 | 3^2 x 100,000 | 900,000 |
37
+ | 4 | 2^13 | 8,192 | 3^3 x 100,000 | 2,700,000 |
38
+ | 5 | 2^14 | 16,384 | 3^4 x 100,000 | 8,100,000 |
39
+ | 6 | 2^15 | 32,768 | 3^5 x 100,000 | 24,300,000 |
40
+ | 7 | 2^16 | 65,536 | 3^6 x 100,000 | 72,900,000 |
41
+ -------- - ------------ - --------------- - --------------------- - ---------------- -
42
+ </pre>
43
+
44
+ When you increase the cost **safe will become perceivably slower**. With a cost of 7, a laptop takes many minutes but an AWS cloud compute optimized M5 server crunches through in mere seconds.
45
+
46
+ ## What is Your Data Worth?
47
+
48
+ Attackers can bring a significant amount of modern data centre hardware to the table in order to access your credentials.
49
+
50
+ However, these computing resources cost money and the amount of money an attacker spends will be proportional to the perceived gains from a successfully attack. The bigger the dollar signs in their eyes, the more they will spend.
51
+
52
+ The default settings coupled with a **12 character password** takes (on average) 50 years to crack with computing resources that will cost $1,000 every single day.
53
+
54
+ ### Twenty Million Dollars
55
+
56
+ If what you are protecting is worth more than **$(50 x 366 x 1,000)**, you should use an at least 16 character password and increase the computational cost parameters for both key derivation functions.
57
+