opensecret 0.0.9925 → 0.0.9949
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.
- checksums.yaml +4 -4
- data/README.md +656 -40
- data/lib/configs/README.md +58 -0
- data/lib/extension/file.rb +67 -0
- data/lib/extension/string.rb +10 -0
- data/lib/factbase/facts.opensecret.io.ini +1 -0
- data/lib/interprete.rb +334 -61
- data/lib/keytools/PRODUCE_RAND_SEQ_USING_DEV_URANDOM.txt +0 -0
- data/lib/keytools/kdf.api.rb +9 -15
- data/lib/keytools/kdf.bcrypt.rb +69 -19
- data/lib/keytools/kdf.pbkdf2.rb +112 -23
- data/lib/keytools/key.api.rb +146 -36
- data/lib/keytools/key.db.rb +94 -29
- data/lib/keytools/key.id.rb +1 -1
- data/lib/keytools/key.ident.rb +243 -0
- data/lib/keytools/key.local.rb +62 -68
- data/lib/keytools/key.pass.rb +2 -2
- data/lib/keytools/key.rb +2 -28
- data/lib/modules/{cryptology.md → README.md} +0 -0
- data/lib/session/fact.finder.rb +65 -428
- data/lib/session/time.stamp.rb +1 -28
- data/lib/usecase/cmd.rb +127 -54
- data/lib/usecase/config/README.md +57 -0
- data/lib/usecase/docker/README.md +146 -0
- data/lib/usecase/docker/docker.rb +49 -0
- data/lib/usecase/edit/README.md +43 -0
- data/lib/usecase/edit/delete.rb +46 -0
- data/lib/usecase/export.rb +40 -0
- data/lib/usecase/files/README.md +37 -0
- data/lib/usecase/files/eject.rb +56 -0
- data/lib/usecase/files/file_me.rb +78 -0
- data/lib/usecase/files/read.rb +169 -0
- data/lib/usecase/files/write.rb +89 -0
- data/lib/usecase/goto.rb +57 -0
- data/lib/usecase/id.rb +1 -1
- data/lib/usecase/import.rb +13 -30
- data/lib/usecase/init.rb +2 -17
- data/lib/usecase/jenkins/README.md +146 -0
- data/lib/usecase/jenkins/crazy_ruby_post_attempt.OLD +234 -0
- data/lib/usecase/jenkins/jenkins.rb +208 -0
- data/lib/usecase/login.rb +6 -5
- data/lib/usecase/logout.rb +1 -3
- data/lib/usecase/open.rb +11 -66
- data/lib/usecase/print.rb +40 -0
- data/lib/usecase/put.rb +34 -156
- data/lib/usecase/set.rb +2 -4
- data/lib/usecase/show.rb +138 -0
- data/lib/usecase/terraform/README.md +91 -0
- data/lib/usecase/terraform/terraform.rb +121 -0
- data/lib/usecase/token.rb +4 -80
- data/lib/usecase/update/README.md +55 -0
- data/lib/usecase/update/rename.rb +180 -0
- data/lib/usecase/use.rb +1 -3
- data/lib/usecase/verse.rb +20 -0
- data/lib/usecase/view.rb +71 -0
- data/lib/usecase/vpn/README.md +150 -0
- data/lib/usecase/vpn/vpn.ini +31 -0
- data/lib/usecase/vpn/vpn.rb +54 -0
- data/lib/version.rb +1 -1
- data/opensecret.gemspec +3 -4
- metadata +34 -35
- data/.travis.yml +0 -5
- data/CODE_OF_CONDUCT.md +0 -74
- data/LICENSE.txt +0 -21
- data/bin/ops +0 -20
- data/lib/keytools/binary.map.rb +0 -294
- data/lib/keytools/doc.conversion.to.ones.and.zeroes.ruby +0 -179
- data/lib/keytools/doc.rsa.radix.binary-mapping.ruby +0 -190
- data/lib/keytools/doc.star.schema.strategy.txt +0 -77
- data/lib/keytools/doc.using.pbkdf2.kdf.ruby +0 -95
- data/lib/keytools/doc.using.pbkdf2.pkcs.ruby +0 -266
- data/lib/keytools/key.mach.rb +0 -248
- data/lib/keytools/keydebug.txt +0 -295
- data/lib/modules/cryptology/open.bcrypt.rb +0 -170
- data/lib/usecase/read.rb +0 -89
- data/lib/usecase/safe.rb +0 -92
data/lib/session/time.stamp.rb
CHANGED
@@ -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
|
data/lib/usecase/cmd.rb
CHANGED
@@ -10,7 +10,7 @@ module OpenSecret
|
|
10
10
|
#
|
11
11
|
# == Common Use Case Behaviour
|
12
12
|
#
|
13
|
-
# This {OpenSecret::
|
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
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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 = "
|
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
|
-
|
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
|
-
|
186
|
-
log.info(x) { "
|
187
|
-
|
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
|
-
|
190
|
-
|
191
|
-
|
192
|
-
@
|
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
|
334
|
+
puts " export #{ENV_VAR_KEY_NAME}=`#{COMMANDMENT} token`"
|
262
335
|
puts ""
|
263
|
-
puts "Those are backticks surrounding
|
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 "
|
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 "
|
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 "
|
315
|
-
puts "
|
316
|
-
puts "
|
317
|
-
puts "
|
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 "
|
394
|
+
puts " #{COMMANDMENT} get password"
|
322
395
|
puts ""
|
323
396
|
puts " then close the path."
|
324
397
|
puts ""
|
325
|
-
puts "
|
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 "
|
337
|
-
puts "
|
338
|
-
puts "
|
339
|
-
puts "
|
340
|
-
puts "
|
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 "
|
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 "
|
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 "
|
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 "
|
390
|
-
puts "
|
391
|
-
puts "
|
392
|
-
puts "
|
393
|
-
puts "
|
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 "
|
405
|
-
puts "
|
406
|
-
puts "
|
407
|
-
puts "
|
408
|
-
puts "
|
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
|
+
|