opensecret 0.0.9925 → 0.0.9949
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|