safedb 0.3.1011 → 0.4.1002
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +56 -19
- data/README.md +15 -15
- data/Rakefile +7 -0
- data/bin/safe +2 -2
- data/lib/{interprete.rb → cli.rb} +168 -121
- data/lib/controller/admin/README.md +47 -0
- data/lib/controller/admin/access.rb +47 -0
- data/lib/controller/admin/checkin.rb +83 -0
- data/lib/controller/admin/checkout.rb +57 -0
- data/lib/controller/admin/diff.rb +75 -0
- data/lib/{usecase → controller/admin}/export.rb +15 -14
- data/lib/controller/admin/goto.rb +52 -0
- data/lib/controller/admin/import.rb +54 -0
- data/lib/controller/admin/init.rb +113 -0
- data/lib/controller/admin/login.rb +88 -0
- data/lib/{usecase → controller/admin}/logout.rb +0 -0
- data/lib/controller/admin/open.rb +39 -0
- data/lib/{usecase → controller/admin}/token.rb +2 -2
- data/lib/controller/admin/tree.md +54 -0
- data/lib/{usecase → controller/admin}/use.rb +0 -0
- data/lib/controller/admin/view.rb +61 -0
- data/lib/{usecase → controller/api}/docker/README.md +0 -0
- data/lib/{usecase → controller/api}/docker/docker.rb +1 -1
- data/lib/{usecase → controller/api}/jenkins/README.md +0 -0
- data/lib/{usecase → controller/api}/jenkins/jenkins.rb +1 -1
- data/lib/{usecase → controller/api}/terraform/README.md +1 -1
- data/lib/{usecase → controller/api}/terraform/terraform.rb +1 -1
- data/lib/{usecase → controller/api}/vpn/README.md +1 -1
- data/lib/{usecase → controller/api}/vpn/vpn.ini +0 -0
- data/lib/{usecase → controller/api}/vpn/vpn.rb +0 -0
- data/lib/{usecase → controller}/config/README.md +0 -0
- data/lib/{usecase → controller}/edit/README.md +0 -0
- data/lib/controller/edit/editverse.rb +48 -0
- data/lib/controller/edit/put.rb +35 -0
- data/lib/controller/edit/remove.rb +29 -0
- data/lib/{usecase/update/README.md → controller/edit/rename.md} +0 -0
- data/lib/{usecase → controller}/files/README.md +1 -1
- data/lib/controller/files/read.rb +36 -0
- data/lib/{usecase/files/eject.rb → controller/files/write.rb} +15 -20
- data/lib/{usecase → controller}/id.rb +0 -0
- data/lib/controller/query/print.rb +26 -0
- data/lib/controller/query/queryverse.rb +39 -0
- data/lib/controller/query/show.rb +50 -0
- data/lib/{session/require.gem.rb → controller/requirer.rb} +13 -9
- data/lib/{usecase → controller}/set.rb +4 -4
- data/lib/controller/usecase.rb +244 -0
- data/lib/{usecase → controller}/verse.rb +0 -0
- data/lib/{usecase → controller}/visit/README.md +0 -0
- data/lib/{usecase → controller}/visit/visit.rb +0 -0
- data/lib/factbase/facts.safedb.net.ini +7 -7
- data/lib/{keytools/key.docs.rb → model/README.md} +102 -66
- data/lib/model/book.rb +484 -0
- data/lib/model/branch.rb +48 -0
- data/lib/model/checkin.feature +33 -0
- data/lib/{configs/README.md → model/configs.md} +4 -4
- data/lib/model/content.rb +214 -0
- data/lib/model/indices.rb +132 -0
- data/lib/model/safe_tree.rb +51 -0
- data/lib/model/state.inspect.rb +221 -0
- data/lib/model/state.migrate.rb +334 -0
- data/lib/model/text_chunk.rb +68 -0
- data/lib/{extension → utils/extend}/array.rb +0 -0
- data/lib/{extension → utils/extend}/dir.rb +0 -0
- data/lib/{extension → utils/extend}/file.rb +0 -0
- data/lib/utils/extend/hash.rb +76 -0
- data/lib/{extension → utils/extend}/string.rb +6 -6
- data/lib/{session/fact.finder.rb → utils/facts/fact.rb} +0 -0
- data/lib/utils/identity/identifier.rb +356 -0
- data/lib/{keytools/key.ident.rb → utils/identity/machine.id.rb} +67 -4
- data/lib/utils/inspect/inspector.rb +81 -0
- data/lib/{keytools/kdf.bcrypt.rb → utils/kdfs/bcrypt.rb} +0 -0
- data/lib/{keytools → utils/kdfs}/kdf.api.rb +16 -16
- data/lib/{keytools/key.local.rb → utils/kdfs/kdfs.rb} +40 -40
- data/lib/{keytools/kdf.pbkdf2.rb → utils/kdfs/pbkdf2.rb} +0 -0
- data/lib/{keytools/kdf.scrypt.rb → utils/kdfs/scrypt.rb} +0 -0
- data/lib/{keytools → utils}/key.error.rb +2 -2
- data/lib/{keytools → utils}/key.pass.rb +2 -2
- data/lib/{keytools → utils/keys}/key.64.rb +0 -0
- data/lib/{keytools → utils/keys}/key.rb +6 -2
- data/lib/{keytools/key.iv.rb → utils/keys/random.iv.rb} +0 -0
- data/lib/{logging/gem.logging.rb → utils/logs/logger.rb} +6 -5
- data/lib/{keytools/key.pair.rb → utils/store/datamap.rb} +48 -30
- data/lib/{keytools/key.db.rb → utils/store/datastore.rb} +38 -104
- data/lib/utils/store/merge-boys-school.json +40 -0
- data/lib/utils/store/merge-girls-school.json +48 -0
- data/lib/utils/store/merge-merged-data.json +56 -0
- data/lib/utils/store/struct.rb +75 -0
- data/lib/utils/store/test-commands.sh +24 -0
- data/lib/{keytools/key.now.rb → utils/time/timestamp.rb} +32 -21
- data/lib/version.rb +1 -1
- metadata +86 -73
- data/lib/extension/hash.rb +0 -33
- data/lib/keytools/key.algo.rb +0 -109
- data/lib/keytools/key.api.rb +0 -1326
- data/lib/keytools/key.id.rb +0 -322
- data/lib/modules/cryptology/amalgam.rb +0 -70
- data/lib/modules/cryptology/engineer.rb +0 -99
- data/lib/modules/mappers/dictionary.rb +0 -288
- data/lib/session/time.stamp.rb +0 -340
- data/lib/session/user.home.rb +0 -49
- data/lib/usecase/cmd.rb +0 -471
- data/lib/usecase/edit/delete.rb +0 -46
- data/lib/usecase/files/file_me.rb +0 -78
- data/lib/usecase/files/read.rb +0 -169
- data/lib/usecase/files/write.rb +0 -89
- data/lib/usecase/goto.rb +0 -57
- data/lib/usecase/import.rb +0 -157
- data/lib/usecase/init.rb +0 -61
- data/lib/usecase/login.rb +0 -72
- data/lib/usecase/open.rb +0 -71
- data/lib/usecase/print.rb +0 -40
- data/lib/usecase/put.rb +0 -81
- data/lib/usecase/show.rb +0 -138
- data/lib/usecase/update/rename.rb +0 -180
- data/lib/usecase/view.rb +0 -71
@@ -26,11 +26,62 @@ module SafeDb
|
|
26
26
|
#
|
27
27
|
# macaddr.rb:86 from_getifaddrs undefined method pfamily (NoMethodError)
|
28
28
|
#
|
29
|
-
class
|
29
|
+
class MachineId
|
30
|
+
|
31
|
+
# This method uses a one-way function to return a combinatorial digested
|
32
|
+
# machine identification string using a number of distinct input parameters
|
33
|
+
# to deliver the characteristic of producing the same identifier for the
|
34
|
+
# same machine, virtual machine, workstation and/or compute element, and
|
35
|
+
# reciprocally, a different one on a different machine.
|
36
|
+
#
|
37
|
+
# The userspace is also a key machine identifier so a different machine user
|
38
|
+
# generates a different identifier when all other things remain equal.
|
39
|
+
#
|
40
|
+
# @return [String]
|
41
|
+
# a one line textual machine workstation or compute element identifier
|
42
|
+
# that is (surprisingly) different when the machine user changes.
|
43
|
+
def self.derive_user_machine_id
|
44
|
+
|
45
|
+
require 'socket'
|
46
|
+
|
47
|
+
identity_text = [
|
48
|
+
Etc.getlogin,
|
49
|
+
get_machine_id(),
|
50
|
+
Socket.gethostname()
|
51
|
+
].join.reverse
|
52
|
+
|
53
|
+
return identity_text
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# The machine identifier is a UUID based hash value that is tied to the
|
59
|
+
# CPU and motherboard of the machine. This read-only identifier can be
|
60
|
+
# accessed without sudoer permissions so is perfect for license generators
|
61
|
+
# and environment sensitive software.
|
62
|
+
#
|
63
|
+
# In the modern era of virtualization you should always check the behaviour
|
64
|
+
# of the above identifiers when used inside
|
65
|
+
#
|
66
|
+
# - docker containers
|
67
|
+
# - Amazon EC2 servers (or Azure or GCE)
|
68
|
+
# - vagrant (VirtualBox/VMWare)
|
69
|
+
# - Windows MSGYWIN (Ubuntu) environments
|
70
|
+
# - Kubernetes pods
|
71
|
+
#
|
72
|
+
# @return [String] the machine ID hash value
|
73
|
+
def self.get_machine_id
|
74
|
+
|
75
|
+
machine_id_cmd = "cat /etc/machine-id"
|
76
|
+
machine_id_str = %x[ #{machine_id_cmd} ]
|
77
|
+
return machine_id_str.chomp
|
78
|
+
|
79
|
+
end
|
80
|
+
|
30
81
|
|
31
82
|
# This method returns a plaintext string hat is guaranteed to be the same
|
32
83
|
# whenever called within the same shell for the same user on the same
|
33
|
-
# workstation, virtual machine, container or SSH
|
84
|
+
# workstation, virtual machine, container or SSH branch and different whenever
|
34
85
|
# a new shell is acquired.
|
35
86
|
#
|
36
87
|
# What is really important is that the <b>shell identity string changes</b> when
|
@@ -47,7 +98,7 @@ module SafeDb
|
|
47
98
|
#
|
48
99
|
# - the <b>user returns to a command shell</b>
|
49
100
|
# - the user <b>switches back to using a domain</b>
|
50
|
-
# - the user exits their <b>remote SSH
|
101
|
+
# - the user exits their <b>remote SSH branch</b>
|
51
102
|
# - <b>sudo is used</b> to execute the commands
|
52
103
|
# - the user comes back to their <b>workstation</b>
|
53
104
|
# - the clock ticks into another day, month, year ...
|
@@ -91,7 +142,7 @@ module SafeDb
|
|
91
142
|
# - Kubernetes pods
|
92
143
|
#
|
93
144
|
# @return [String] the bootup ID hash value
|
94
|
-
def self.get_bootup_id
|
145
|
+
def self.get_bootup_id()
|
95
146
|
|
96
147
|
bootup_id_cmd = "cat /proc/sys/kernel/random/boot_id"
|
97
148
|
bootup_id_str = %x[ #{bootup_id_cmd} ]
|
@@ -100,6 +151,18 @@ module SafeDb
|
|
100
151
|
end
|
101
152
|
|
102
153
|
|
154
|
+
# Logs a list of the last few times that this machine has rebooted.
|
155
|
+
# This log can be useful when used in conjunction with the behaviour
|
156
|
+
# that gets the bootup identifier.
|
157
|
+
def self.log_reboot_times()
|
158
|
+
|
159
|
+
the_cmd = "last reboot"
|
160
|
+
the_str = %x[ #{the_cmd} ]
|
161
|
+
the_str.log_lines()
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
|
103
166
|
# Return an ancestor process ID meaning return either the parent process
|
104
167
|
# ID or the grandparent process ID. The one returned depends on the paremeter
|
105
168
|
# boolean value.
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
|
5
|
+
# To use this inspector copy and paste this code into any class at any position.
|
6
|
+
|
7
|
+
|
8
|
+
# It will print out
|
9
|
+
#
|
10
|
+
# - the global variables
|
11
|
+
# - the class constants
|
12
|
+
# - the loaded features
|
13
|
+
# - the local variables
|
14
|
+
# - the last exception
|
15
|
+
# - the command line variables
|
16
|
+
#
|
17
|
+
# This is extremely handly for troubleshooting
|
18
|
+
|
19
|
+
|
20
|
+
=begin
|
21
|
+
|
22
|
+
puts ""
|
23
|
+
puts "QQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
24
|
+
puts "QQQ ~~~~~~~~~~~~~ Global Variable Array List ~~~~~~~~~~~~~~~~ QQQQQ"
|
25
|
+
puts "QQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
26
|
+
|
27
|
+
puts global_variables().inspect
|
28
|
+
|
29
|
+
puts "QQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
30
|
+
puts "QQQ ~~~~~~~~~~~~~ Global Variable Values Printed ~~~~~~~~~~~~~~~~ QQQQQ"
|
31
|
+
puts "QQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
32
|
+
|
33
|
+
global_variables().sort.each do |name|
|
34
|
+
|
35
|
+
puts "<<< ------------------------------------------------------------------->>>"
|
36
|
+
puts "<<< #{name.to_s} >>>"
|
37
|
+
puts "<<< ------------------------------------------------------------------->>>"
|
38
|
+
next if name.to_s.eql?( "$FILENAME" )
|
39
|
+
global_variable_value = eval "#{name}.inspect"
|
40
|
+
puts "<<< #{global_variable_value}"
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
puts ""
|
45
|
+
puts "QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
46
|
+
puts "QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
47
|
+
puts ""
|
48
|
+
puts "QQQQQQQQQQQ QQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
49
|
+
puts "QQQQQQQQQQQ Bug Finder QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
50
|
+
puts "QQQQQQQQQQQ QQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
51
|
+
puts ""
|
52
|
+
self.instance_variables().map do |attribute|
|
53
|
+
puts "=============================================="
|
54
|
+
puts "----------------------------------------------"
|
55
|
+
puts attribute
|
56
|
+
pp self.instance_variable_get(attribute)
|
57
|
+
end
|
58
|
+
puts "=============================================="
|
59
|
+
puts "QQQQQQQQQQQ QQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
60
|
+
puts "QQQQQQQQQQQ QQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
61
|
+
puts ""
|
62
|
+
puts "### ------------------------------------"
|
63
|
+
puts "### Inspect View"
|
64
|
+
puts "### ------------------------------------"
|
65
|
+
pp self.inspect
|
66
|
+
puts "### ------------------------------------"
|
67
|
+
puts "QQQQQQQQQQQ QQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
68
|
+
puts "QQQQQQQQQQQ Local Variables QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
69
|
+
puts "QQQQQQQQQQQ QQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
70
|
+
|
71
|
+
local_variables().map do |attribute|
|
72
|
+
puts "=============================================="
|
73
|
+
puts "----------------------------------------------"
|
74
|
+
puts attribute
|
75
|
+
pp binding().local_variable_get(attribute.to_sym)
|
76
|
+
end
|
77
|
+
puts "QQQQQQQQQQQ QQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"
|
78
|
+
|
79
|
+
puts ""
|
80
|
+
|
81
|
+
=end
|
File without changes
|
@@ -82,12 +82,12 @@ module SafeDb
|
|
82
82
|
#
|
83
83
|
# <b>Example | Derive Key from Password</b>
|
84
84
|
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
# human_key = KdfApi.generate_from_password( "my_s3cr3t",
|
85
|
+
# data_store = DataMap.new( "/path/to/kdf-salt-data.ini" )
|
86
|
+
# data_store.use( "peter-pan" )
|
87
|
+
# human_key = KdfApi.generate_from_password( "my_s3cr3t", data_store )
|
88
88
|
#
|
89
89
|
# strong_key = Key.from_random()
|
90
|
-
# human_key.encrypt_key( strong_key,
|
90
|
+
# human_key.encrypt_key( strong_key, data_store )
|
91
91
|
#
|
92
92
|
# strong_key.encrypt_file "/path/to/file-to-encrypt.pdf"
|
93
93
|
# strong_key.encrypt_text "I am the text to encrypt."
|
@@ -149,22 +149,22 @@ module SafeDb
|
|
149
149
|
# dictionary word or name is the way to generate a powerful key
|
150
150
|
# that has embedded a near 100% entropy rating.
|
151
151
|
#
|
152
|
-
# @param
|
153
|
-
# The
|
154
|
-
# section specified using {
|
152
|
+
# @param data_map [DataMap]
|
153
|
+
# The DataMap storage service must have been initialized and a
|
154
|
+
# section specified using {DataMap.use} thus allowing this method
|
155
155
|
# to <b>write key-value pairs</b> representing the BCrypt and
|
156
|
-
# PBKDF2 salts through the {
|
156
|
+
# PBKDF2 salts through the {DataMap.set} behaviour.
|
157
157
|
#
|
158
158
|
# @return [Key]
|
159
159
|
# the 256 bit symmetric encryption key derived from a human password
|
160
160
|
# and passed through two cryptographic workhorses.
|
161
|
-
def self.generate_from_password human_secret,
|
161
|
+
def self.generate_from_password human_secret, data_map
|
162
162
|
|
163
163
|
bcrypt_salt = KdfBCrypt.generate_bcrypt_salt
|
164
164
|
pbkdf2_salt = KeyPbkdf2.generate_pbkdf2_salt
|
165
165
|
|
166
|
-
|
167
|
-
|
166
|
+
data_map.set( BCRYPT_SALT_KEY_NAME, bcrypt_salt )
|
167
|
+
data_map.set( PBKDF2_SALT_KEY_NAME, pbkdf2_salt )
|
168
168
|
|
169
169
|
return derive_and_amalgamate( human_secret, bcrypt_salt, pbkdf2_salt )
|
170
170
|
|
@@ -175,18 +175,18 @@ module SafeDb
|
|
175
175
|
# generated in the past and with the same salts that were used during
|
176
176
|
# the original key derivation process.
|
177
177
|
#
|
178
|
-
# @param
|
178
|
+
# @param data_map [Hash]
|
179
179
|
# an instantiated and populated hash object containing the salts
|
180
180
|
# which were created in the past during the generation. These are
|
181
181
|
# now vital for a successful regeneration.
|
182
182
|
#
|
183
183
|
# @return [Key]
|
184
184
|
# the 256 bit symmetric encryption key that was previously generated
|
185
|
-
# from the secret and the cryptographic salts within the
|
186
|
-
def self.regenerate_from_salts human_secret,
|
185
|
+
# from the secret and the cryptographic salts within the data_map.
|
186
|
+
def self.regenerate_from_salts human_secret, data_map
|
187
187
|
|
188
|
-
bcrypt_salt =
|
189
|
-
pbkdf2_salt =
|
188
|
+
bcrypt_salt = data_map.get( BCRYPT_SALT_KEY_NAME )
|
189
|
+
pbkdf2_salt = data_map.get( PBKDF2_SALT_KEY_NAME )
|
190
190
|
|
191
191
|
return derive_and_amalgamate( human_secret, bcrypt_salt, pbkdf2_salt )
|
192
192
|
|
@@ -5,21 +5,21 @@ module SafeDb
|
|
5
5
|
|
6
6
|
# The command line interface has a high entropy randomly generated
|
7
7
|
# key whose purpose is to <b>lock the application's data key</b> for
|
8
|
-
# the duration of the
|
8
|
+
# the duration of the branch which is between a login and a logout.
|
9
9
|
#
|
10
|
-
# These keys are unique to only one shell
|
10
|
+
# These keys are unique to only one shell on one workstation
|
11
11
|
# and they live lives that are no longer (and mostly shorter) than
|
12
12
|
# the life of the parent shell.
|
13
13
|
#
|
14
14
|
# == The 4 CLI Shell Entities
|
15
15
|
#
|
16
|
-
# The four (4) important entities within the shell
|
16
|
+
# The four (4) important entities within the shell are
|
17
17
|
#
|
18
|
-
# - an obfuscator key for locking the shell key during a
|
18
|
+
# - an obfuscator key for locking the shell key during a branch
|
19
19
|
# - a high entropy randomly generated shell key for locking the app data key
|
20
20
|
# - one environment variable whose value embodies three (3) data segments
|
21
|
-
# - a
|
22
|
-
class
|
21
|
+
# - a branch id derived by pushing the env var through a one-way function
|
22
|
+
class KeyDerivation
|
23
23
|
|
24
24
|
|
25
25
|
# The number of Radix64 characters that make up a valid BCrypt salt.
|
@@ -32,33 +32,33 @@ module SafeDb
|
|
32
32
|
BCRYPT_ITER_COUNT_SIZE = 2
|
33
33
|
|
34
34
|
|
35
|
-
# The
|
35
|
+
# The shell token comprises of 3 segments with fixed lengths.
|
36
36
|
# This triply segmented text token that can be used to decrypt
|
37
37
|
# and deliver the shell key.
|
38
|
-
|
38
|
+
SHELL_TOKEN_SIZE = 128 + 22 + BCRYPT_ITER_COUNT_SIZE
|
39
39
|
|
40
40
|
|
41
|
-
# Given a 152 character
|
41
|
+
# Given a 152 character shell token, what is the index that pinpoints
|
42
42
|
# the beginning of the 22 character BCrypt salt? The answer is given
|
43
43
|
# by this BCRYPT_SALT_START_INDEX constant.
|
44
|
-
BCRYPT_SALT_START_INDEX =
|
44
|
+
BCRYPT_SALT_START_INDEX = SHELL_TOKEN_SIZE - BCRYPT_SALT_LENGTH - BCRYPT_ITER_COUNT_SIZE
|
45
45
|
|
46
46
|
|
47
47
|
# What index pinpoints the end of the BCrypt salt itself.
|
48
48
|
# This is easy as the final 2 characters are the iteration count
|
49
49
|
# so the end index is the length subtract 1 subtract 2.
|
50
|
-
BCRYPT_SALT_END_INDEX =
|
50
|
+
BCRYPT_SALT_END_INDEX = SHELL_TOKEN_SIZE - 1
|
51
51
|
|
52
52
|
|
53
|
-
# Initialize the
|
53
|
+
# Initialize the branch by generating a random high entropy shell token
|
54
54
|
# and then generate an obfuscator key which we use to lock the shell
|
55
55
|
# key and return a triply segmented text token that can be used to decrypt
|
56
56
|
# and deliver the shell key as long as the same shell on the same machine
|
57
57
|
# is employed to make the call.
|
58
58
|
#
|
59
|
-
# <b>The 3
|
59
|
+
# <b>The 3 Shell Token Segments</b>
|
60
60
|
#
|
61
|
-
# The
|
61
|
+
# The shell token is divided up into 3 segments with a total of 150
|
62
62
|
# characters.
|
63
63
|
#
|
64
64
|
# | -------- | ------------ | ------------------------------------- |
|
@@ -68,7 +68,7 @@ module SafeDb
|
|
68
68
|
# | 2 | 80 bytes | Cipher text from Random Key AES crypt |
|
69
69
|
# | 3 | 22 chars | Salt for obfuscator key derivation |
|
70
70
|
# | -------- | ------------ | ------------------------------------- |
|
71
|
-
# | Total | 150 chars |
|
71
|
+
# | Total | 150 chars | Shell Token in Environment Variable |
|
72
72
|
# | -------- | ------------ | ------------------------------------- |
|
73
73
|
#
|
74
74
|
# Why is the <b>16 byte salt and the 80 byte BCrypt ciphertext</b> represented
|
@@ -80,17 +80,17 @@ module SafeDb
|
|
80
80
|
#
|
81
81
|
# @return [String]
|
82
82
|
# return a triply segmented text token that can be used to decrypt
|
83
|
-
# and redeliver the high entropy
|
83
|
+
# and redeliver the high entropy branch shell key on the same machine
|
84
84
|
# and within the same shell on the same machine.
|
85
85
|
def self.generate_shell_key_and_token
|
86
86
|
|
87
87
|
bcrypt_salt_key = KdfBCrypt.generate_bcrypt_salt
|
88
|
-
obfuscator_key =
|
88
|
+
obfuscator_key = derive_branch_crypt_key( bcrypt_salt_key )
|
89
89
|
random_key_ciphertext = obfuscator_key.do_encrypt_key( Key.from_random() )
|
90
|
-
|
91
|
-
|
90
|
+
shell_token = random_key_ciphertext + bcrypt_salt_key.reverse
|
91
|
+
assert_shell_token_size( shell_token )
|
92
92
|
|
93
|
-
return
|
93
|
+
return shell_token
|
94
94
|
|
95
95
|
end
|
96
96
|
|
@@ -100,16 +100,16 @@ module SafeDb
|
|
100
100
|
#
|
101
101
|
# To successfully reacquire the randomly generated (and then locked)
|
102
102
|
# shell key we must be provided with five (5) data points, four (4)
|
103
|
-
# of which are embalmed within the 150 character
|
103
|
+
# of which are embalmed within the 150 character shell token
|
104
104
|
# parameter.
|
105
105
|
#
|
106
106
|
# <b>What we need to Regenerate the Shell Key</b>
|
107
107
|
#
|
108
108
|
# Regenerating the shell key is done in two steps when given the
|
109
|
-
# four (4) <b>
|
109
|
+
# four (4) <b>shell token segments</b> described below, and the
|
110
110
|
# shell identity key described in the {SafeDb::Identifier} class.
|
111
111
|
#
|
112
|
-
# The
|
112
|
+
# The shell token is divided up into 4 segments with a total of 152
|
113
113
|
# characters.
|
114
114
|
#
|
115
115
|
# | -------- | ------------ | ------------------------------------- |
|
@@ -120,25 +120,25 @@ module SafeDb
|
|
120
120
|
# | 3 | 22 chars | Salt 4 shell identity key derivation |
|
121
121
|
# | 4 | 2 chars | BCrypt iteration parameter (10 to 16) |
|
122
122
|
# | -------- | ------------ | ------------------------------------- |
|
123
|
-
# | Total | 152 chars |
|
123
|
+
# | Total | 152 chars | Shell Token in Environment Variable |
|
124
124
|
# | -------- | ------------ | ------------------------------------- |
|
125
125
|
#
|
126
|
-
# @param
|
126
|
+
# @param shell_token [String]
|
127
127
|
# a triply segmented (and one liner) text token instantiated by
|
128
128
|
# {self.instantiate_shell_key_and_generate_token} and provided
|
129
129
|
# here ad verbatim.
|
130
130
|
#
|
131
131
|
# @return [SafeDb::Key]
|
132
132
|
# an extremely high entropy 256 bit key derived (digested) from 48
|
133
|
-
# random bytes at the beginning of the shell (cli)
|
134
|
-
def self.regenerate_shell_key(
|
133
|
+
# random bytes at the beginning of the shell (cli) branch.
|
134
|
+
def self.regenerate_shell_key( shell_token )
|
135
135
|
|
136
|
-
|
137
|
-
bcrypt_salt =
|
136
|
+
assert_shell_token_size( shell_token )
|
137
|
+
bcrypt_salt = shell_token[ BCRYPT_SALT_START_INDEX .. BCRYPT_SALT_END_INDEX ].reverse
|
138
138
|
assert_bcrypt_salt_size( bcrypt_salt )
|
139
139
|
|
140
|
-
key_ciphertext =
|
141
|
-
obfuscator_key =
|
140
|
+
key_ciphertext = shell_token[ 0 .. ( BCRYPT_SALT_START_INDEX - 1 ) ]
|
141
|
+
obfuscator_key = derive_branch_crypt_key( bcrypt_salt )
|
142
142
|
regenerated_key = obfuscator_key.do_decrypt_key( key_ciphertext )
|
143
143
|
|
144
144
|
return regenerated_key
|
@@ -146,7 +146,7 @@ module SafeDb
|
|
146
146
|
end
|
147
147
|
|
148
148
|
|
149
|
-
# Derive a <b>short term (
|
149
|
+
# Derive a <b>short term (branch scoped) encryption key</b> from the
|
150
150
|
# surrounding shell and workstation (machine) environment with an
|
151
151
|
# important same/different guarantee.
|
152
152
|
#
|
@@ -157,7 +157,7 @@ module SafeDb
|
|
157
157
|
# - <b>different</b> when the shell and/or workstation are different
|
158
158
|
#
|
159
159
|
# This method uses a one-way function to return a combinatorial digested
|
160
|
-
#
|
160
|
+
# branch identification string using a number of distinct parameters that
|
161
161
|
# deliver the important behaviours of changing in certain circumstances
|
162
162
|
# and remaining unchanged in others.
|
163
163
|
#
|
@@ -180,7 +180,7 @@ module SafeDb
|
|
180
180
|
# <b>unchanged</b> when
|
181
181
|
#
|
182
182
|
# - the <b>user returns to a command shell</b>
|
183
|
-
# - the user exits their <b>remote SSH
|
183
|
+
# - the user exits their <b>remote SSH branch</b>
|
184
184
|
# - <b>sudo is used</b> to execute the commands
|
185
185
|
# - the user comes back to their <b>workstation</b>
|
186
186
|
# - the clock ticks into another day, month, year ...
|
@@ -191,12 +191,12 @@ module SafeDb
|
|
191
191
|
# previously generated salt which must hold 22 printable characters.
|
192
192
|
#
|
193
193
|
# @return [SafeDb::Key]
|
194
|
-
# a digested key suitable for short term (
|
194
|
+
# a digested key suitable for short term (branch scoped) use with the
|
195
195
|
# guarantee that the same key will be returned whenever called from within
|
196
196
|
# the same executing shell environment and a different key when not.
|
197
|
-
def self.
|
197
|
+
def self.derive_branch_crypt_key bcrypt_salt_key
|
198
198
|
|
199
|
-
shell_id_text =
|
199
|
+
shell_id_text = MachineId.derive_shell_identifier()
|
200
200
|
truncate_text = shell_id_text.length > KdfBCrypt::BCRYPT_MAX_IN_TEXT_LENGTH
|
201
201
|
shell_id_trim = shell_id_text unless truncate_text
|
202
202
|
shell_id_trim = shell_id_text[ 0 .. ( KdfBCrypt::BCRYPT_MAX_IN_TEXT_LENGTH - 1 ) ] if truncate_text
|
@@ -222,9 +222,9 @@ module SafeDb
|
|
222
222
|
# 000000000000000000000000000000000000000000000000000000000000000
|
223
223
|
|
224
224
|
|
225
|
-
def self.
|
226
|
-
err_msg = "
|
227
|
-
raise RuntimeError, err_msg unless
|
225
|
+
def self.assert_shell_token_size shell_token
|
226
|
+
err_msg = "shell token has #{shell_token.length} and not #{SHELL_TOKEN_SIZE} chars."
|
227
|
+
raise RuntimeError, err_msg unless shell_token.length == SHELL_TOKEN_SIZE
|
228
228
|
end
|
229
229
|
|
230
230
|
|