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
data/lib/model/branch.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module SafeDb
|
4
|
+
|
5
|
+
# The shell can access the 152 characters of crypt and salt text
|
6
|
+
# that was set (exported) at the beginning when the shell woke up and typically
|
7
|
+
# executed its .bash_aliases script.
|
8
|
+
class Branch
|
9
|
+
|
10
|
+
def self.to_token()
|
11
|
+
|
12
|
+
raw_env_var_value = ENV[Indices::TOKEN_VARIABLE_NAME]
|
13
|
+
raise_token_error( Indices::TOKEN_VARIABLE_NAME, "not present") unless raw_env_var_value
|
14
|
+
|
15
|
+
env_var_value = raw_env_var_value.strip
|
16
|
+
raise_token_error( Indices::TOKEN_VARIABLE_NAME, "consists only of whitespace") if raw_env_var_value.empty?
|
17
|
+
|
18
|
+
size_msg = "length should contain exactly #{Indices::TOKEN_VARIABLE_SIZE} characters"
|
19
|
+
raise_token_error( Indices::TOKEN_VARIABLE_NAME, size_msg ) unless env_var_value.length == Indices::TOKEN_VARIABLE_SIZE
|
20
|
+
|
21
|
+
return env_var_value
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
|
29
|
+
def self.raise_token_error env_var_name, message
|
30
|
+
|
31
|
+
puts ""
|
32
|
+
puts "#{Indices::TOKEN_VARIABLE_NAME} environment variable #{message}."
|
33
|
+
puts "To instantiate it you can use the below command."
|
34
|
+
puts ""
|
35
|
+
puts "$ export #{Indices::TOKEN_VARIABLE_NAME}=`safe token`"
|
36
|
+
puts ""
|
37
|
+
puts "ps => those are backticks around `safe token` (not apostrophes)."
|
38
|
+
puts ""
|
39
|
+
|
40
|
+
raise RuntimeError, "#{Indices::TOKEN_VARIABLE_NAME} environment variable #{message}."
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
## The typical shells
|
3
|
+
|
4
|
+
Learn to run emacs commands in a batch so that we can open the below in an automated fashion. Learn to robotically communicate with and manipulate emacs. This will improve your efficiency many many fold.
|
5
|
+
|
6
|
+
.% CORE [dir] 856 Dired by name /home/apollo/projects/safedb.net/lib/core/
|
7
|
+
* SEARCH [shell] 36 Shell:run /home/apollo/projects/safedb.net/
|
8
|
+
* RAKE [shell] 94 Shell:run /home/apollo/projects/safedb.net/
|
9
|
+
% USECASE [dir] 1080 Dired by name /home/apollo/projects/safedb.net/lib/usecase/
|
10
|
+
% safedb.net 924 Dired by name /home/apollo/projects/safedb.net/
|
11
|
+
* SAFE 2 [shell] 16 Shell:run /home/apollo/
|
12
|
+
* SAFE 1 [shell] 16 Shell:run /home/apollo/
|
13
|
+
|
14
|
+
# Feature Checkin
|
15
|
+
|
16
|
+
## In one shell
|
17
|
+
|
18
|
+
safe init boys
|
19
|
+
safe login boys
|
20
|
+
safe import ~/safedb.test.data.json
|
21
|
+
safe view
|
22
|
+
safe show (failure because no open chapter has been set)
|
23
|
+
safe goto 3
|
24
|
+
safe checkin
|
25
|
+
|
26
|
+
|
27
|
+
## In Another shell
|
28
|
+
|
29
|
+
safe login boys
|
30
|
+
|
31
|
+
Failure occurs
|
32
|
+
|
33
|
+
R{\370\204m\265^v}\276\223^RZ(\320^N\333e.time":"Wed Apr 10 09:06:37 2019","book.name":"boys","book.init.version":"safedb-v0.3.1012","book.chapter.keys":{"dbms.accounts":{"content.id":"00cxarwaia0s4g","content.iv":"VzbG5IBQEuFdpRFerzGqHPejVKdKekcl","chapter.key.crypt":"Rx5BWXXM9uK5cbiH006WupaHVciXL8q%XooFdogSazMdHnqlJHuulMoeBtZxxJse"},"aws.console.accounts":{"content.id":"r6sc5ope3n3sfi","content.iv":"Jgh4c2aeh2Qjwt@ZaTEJxfK@6A%dzUoz","chapter.key.crypt":"9t5xxjDgyN4jQGQyw%9CHvTzGqJU@MiOWFGFKpGAuz@@fT8FJVO2fjoQIHEjTDfa"},"ops":{"content.id":"uk2u9bnzpynizc","content.iv":"AnvTgyJPbZpBju8kSsT8es0NmHlv2j9d","chapter.key.crypt":"TYyASQ71sgMbzNOxGVgojdb28M1%4iPDDsSDQz8TevjABYY887hqoPTRpvx18xUT"},"git":{"content.id":"r3dso6qr88l5lm","content.iv":"I9hykwLIGrvgp0j2jMQyMJC3QhWg0xSD","chapter.key.crypt":"0QLO7FawspMzEpRnB%6Wb3dVyjiJ36IX5SRp7QNOkU5ut@sMy9%KNYQ42XKA8yTj"}},"book.open.chapter":"aws.console.accounts","book.open.verse":"aimbrain.prod"}
|
@@ -5,7 +5,7 @@ Safe's behaviour can (by default) be modified in a manner that is scoped in 4 wa
|
|
5
5
|
|
6
6
|
1. a **book global** scope
|
7
7
|
2. a **machine local** scope
|
8
|
-
3. a **shell
|
8
|
+
3. a **shell** scope and
|
9
9
|
4. a **machine global** scope
|
10
10
|
|
11
11
|
The scoping concept is similar to Git's --local and --global but it works in a different way.
|
@@ -33,11 +33,11 @@ If a directive with a book global scope says "Yes" and the same directive exists
|
|
33
33
|
A book global directive overrides its machine local twin.
|
34
34
|
|
35
35
|
|
36
|
-
## 3. Shell
|
36
|
+
## 3. Shell Scope
|
37
37
|
|
38
|
-
The self explanatory **shell
|
38
|
+
The self explanatory **shell scoped** directives override their siblings be they book global or machine local.
|
39
39
|
|
40
|
-
Alas, their elevated privileges are countered by relatively short lifespans.
|
40
|
+
Alas, their elevated privileges are countered by relatively short lifespans. shell directives only last until either a logout is issued or the shell comes to an end.
|
41
41
|
|
42
42
|
|
43
43
|
## 4. Default | Machine Global Scope
|
@@ -0,0 +1,214 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module SafeDb
|
4
|
+
|
5
|
+
# This class both locks content, writing the ciphertext to a file, and
|
6
|
+
# unlocks content after reading ciphertext from a file.
|
7
|
+
#
|
8
|
+
# It supports the encryption of large bodies of text or binary because
|
9
|
+
# it uses the efficient and effective AES asymmetric algorithm.
|
10
|
+
#
|
11
|
+
class Content
|
12
|
+
|
13
|
+
|
14
|
+
# Lock the content body provided - place the resulting ciphertext
|
15
|
+
# inside a file named by a random identifier, then write this identifier
|
16
|
+
# along wih the initialization and encryption key into the provided
|
17
|
+
# key-value map (hash).
|
18
|
+
#
|
19
|
+
# The content ciphertext derived from encrypting the body is stored
|
20
|
+
# in a file underneath the provided content header.
|
21
|
+
#
|
22
|
+
# @param book_id [String] used to determine the book's master crypt folder
|
23
|
+
# @param crypt_key [Key] the key used to (symmetrically) encrypt the content provided
|
24
|
+
# @param data_store [DataMap] either DataMap or DataStore containing the content id and random iv
|
25
|
+
# @param content_body [String] content to encryt and the ciphertext will be stored
|
26
|
+
def self.lock_master( book_id, crypt_key, data_store, content_body )
|
27
|
+
|
28
|
+
content_id = Identifier.get_random_identifier( Indices::CONTENT_ID_LENGTH )
|
29
|
+
data_store.set( Indices::CONTENT_IDENTIFIER, content_id )
|
30
|
+
master_crypt_path = FileTree.master_crypts_filepath( book_id, content_id )
|
31
|
+
iv_base64 = KeyIV.new().for_storage()
|
32
|
+
data_store.set( Indices::CONTENT_RANDOM_IV, iv_base64 )
|
33
|
+
random_iv = KeyIV.in_binary( iv_base64 )
|
34
|
+
|
35
|
+
lock_it( master_crypt_path, crypt_key, random_iv, content_body, TextChunk.crypt_header( book_id ) )
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
# Lock the content body provided - place the resulting ciphertext
|
42
|
+
# inside a file named by a random identifier, then write this identifier
|
43
|
+
# along wih the initialization and encryption key into the provided
|
44
|
+
# key-value map (hash).
|
45
|
+
#
|
46
|
+
# The content ciphertext derived from encrypting the body is stored
|
47
|
+
# in a file.
|
48
|
+
#
|
49
|
+
# @param data_store [DataMap] either DataMap or DataStore containing the content id and random iv
|
50
|
+
# @param content_body [String] content to encryt and the ciphertext will be stored
|
51
|
+
def self.lock_chapter( data_store, content_body )
|
52
|
+
|
53
|
+
branch_id = Identifier.derive_branch_id( Branch.to_token() )
|
54
|
+
branch_indices_file = FileTree.branch_indices_filepath( branch_id )
|
55
|
+
book_id = DataMap.new( branch_indices_file ).read( Indices::BRANCH_DATA, Indices::CURRENT_BRANCH_BOOK_ID )
|
56
|
+
|
57
|
+
old_content_id = data_store[ Indices::CONTENT_IDENTIFIER ] if data_store.has_key?(Indices::CONTENT_IDENTIFIER)
|
58
|
+
|
59
|
+
new_content_id = Identifier.get_random_identifier( Indices::CONTENT_ID_LENGTH )
|
60
|
+
data_store.store( Indices::CONTENT_IDENTIFIER, new_content_id )
|
61
|
+
|
62
|
+
new_chapter_crypt_path = FileTree.branch_crypts_filepath( book_id, branch_id, new_content_id )
|
63
|
+
|
64
|
+
iv_base64 = KeyIV.new().for_storage()
|
65
|
+
data_store.store( Indices::CONTENT_RANDOM_IV, iv_base64 )
|
66
|
+
random_iv = KeyIV.in_binary( iv_base64 )
|
67
|
+
|
68
|
+
crypt_key = Key.from_random()
|
69
|
+
data_store.store( Indices::CRYPT_CIPHER_TEXT, crypt_key.to_char64() )
|
70
|
+
|
71
|
+
lock_it( new_chapter_crypt_path, crypt_key, random_iv, content_body, TextChunk.crypt_header( book_id ) )
|
72
|
+
|
73
|
+
unless old_content_id.nil?
|
74
|
+
old_chapter_crypt_path = FileTree.branch_crypts_filepath( book_id, branch_id, old_content_id )
|
75
|
+
File.delete( old_chapter_crypt_path )
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
# Lock the content body provided - place the resulting ciphertext
|
83
|
+
# inside a file named by a random identifier, then write this identifier
|
84
|
+
# along wih the initialization and encryption key into the provided
|
85
|
+
# key-value map (hash).
|
86
|
+
#
|
87
|
+
# The content ciphertext derived from encrypting the body is stored
|
88
|
+
# in a file underneath the provided content header.
|
89
|
+
#
|
90
|
+
# This method returns the highly random key instantiated for the purposes
|
91
|
+
# of encrypting the content.
|
92
|
+
#
|
93
|
+
# @param crypt_path [File] path to the crypt file holding the encrypted ciphertext
|
94
|
+
# @param crypt_key [Key] the key used to (symmetrically) encrypt the content provided
|
95
|
+
# @param random_iv [String] the random initialization vector for the encryption
|
96
|
+
# @param content_body [String] content to encryt and the ciphertext will be stored
|
97
|
+
# @param crypt_header [String] string that tops and tails the content's ciphertext
|
98
|
+
def self.lock_it( crypt_path, crypt_key, random_iv, content_body, crypt_header )
|
99
|
+
|
100
|
+
binary_ctext = crypt_key.do_encrypt_text( random_iv, content_body )
|
101
|
+
binary_to_write( crypt_path, crypt_header, binary_ctext )
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
# Use the content's external id to find the ciphertext file that is to be unlocked.
|
108
|
+
# Then use the unlock key from the parameter along with the random IV that is inside
|
109
|
+
# the {DataMap} or {DataStore} to decrypt and return the ciphertext.
|
110
|
+
#
|
111
|
+
# @param unlock_key [Key] symmetric key that was used to encrypt the ciphertext
|
112
|
+
# @param data_store [DataMap] either {DataMap} or {DataStore} containing content id and random iv
|
113
|
+
# @return [String] the resulting decrypted text that was encrypted with the parameter key
|
114
|
+
def self.unlock_master( unlock_key, data_store )
|
115
|
+
|
116
|
+
book_id = data_store.section()
|
117
|
+
crypt_path = FileTree.master_crypts_filepath( book_id, data_store.get( Indices::CONTENT_IDENTIFIER ) )
|
118
|
+
random_iv = KeyIV.in_binary( data_store.get( Indices::CONTENT_RANDOM_IV ) )
|
119
|
+
return unlock_it( crypt_path, unlock_key, random_iv )
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
# Use the content's external id to find the ciphertext file that is to be unlocked.
|
126
|
+
# Then use the unlock key from the parameter along with the random IV that is inside
|
127
|
+
# the {DataMap} or {DataStore} to decrypt and return the ciphertext.
|
128
|
+
#
|
129
|
+
# @param data_store [DataMap] either {DataMap} or {DataStore} containing content id and random iv
|
130
|
+
# @return [String] the resulting decrypted text that was encrypted with the parameter key
|
131
|
+
def self.unlock_branch_chapter( data_store )
|
132
|
+
|
133
|
+
branch_id = Identifier.derive_branch_id( Branch.to_token() )
|
134
|
+
branch_indices_file = FileTree.branch_indices_filepath( branch_id )
|
135
|
+
book_id = DataMap.new( branch_indices_file ).read( Indices::BRANCH_DATA, Indices::CURRENT_BRANCH_BOOK_ID )
|
136
|
+
|
137
|
+
content_id = data_store[ Indices::CONTENT_IDENTIFIER ]
|
138
|
+
crypt_key = Key.from_char64( data_store[ Indices::CRYPT_CIPHER_TEXT ] )
|
139
|
+
random_iv = KeyIV.in_binary( data_store[ Indices::CONTENT_RANDOM_IV ] )
|
140
|
+
|
141
|
+
crypt_path = FileTree.branch_crypts_filepath( book_id, branch_id, content_id )
|
142
|
+
return DataStore.from_json( unlock_it( crypt_path, crypt_key, random_iv ) )
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
# Use the content's external id to find the ciphertext file that is to be unlocked.
|
149
|
+
# Then use the unlock key from the parameter along with the random IV that is inside
|
150
|
+
# the {DataMap} or {DataStore} to decrypt and return the ciphertext.
|
151
|
+
#
|
152
|
+
# @param book_id [String] ID of the book to unlock the chapter of
|
153
|
+
# @param data_store [DataMap] either {DataMap} or {DataStore} containing content id and random iv
|
154
|
+
# @return [String] the resulting decrypted text that was encrypted with the parameter key
|
155
|
+
def self.unlock_master_chapter( book_id, data_store )
|
156
|
+
|
157
|
+
random_iv = KeyIV.in_binary( data_store[ Indices::CONTENT_RANDOM_IV ] )
|
158
|
+
crypt_key = Key.from_char64( data_store[ Indices::CRYPT_CIPHER_TEXT ] )
|
159
|
+
content_id = data_store[ Indices::CONTENT_IDENTIFIER ]
|
160
|
+
crypt_path = FileTree.master_crypts_filepath( book_id, content_id )
|
161
|
+
return DataStore.from_json( unlock_it( crypt_path, crypt_key, random_iv ) )
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
# Use the content's external id to find the ciphertext file that is to be unlocked.
|
168
|
+
# Then use the unlock key from the parameter along with the random IV that is inside
|
169
|
+
# the {DataMap} or {DataStore} to decrypt and return the ciphertext.
|
170
|
+
#
|
171
|
+
# @param crypt_path [File] path to the crypt file holding the encrypted ciphertext
|
172
|
+
# @param unlock_key [Key] symmetric key that was used to encrypt the ciphertext
|
173
|
+
# @param random_iv [String] the random initialization vector for the encryption
|
174
|
+
# @return [String] the resulting decrypted text that was encrypted with the parameter key
|
175
|
+
def self.unlock_it( crypt_path, unlock_key, random_iv )
|
176
|
+
|
177
|
+
return unlock_key.do_decrypt_text( random_iv, binary_from_read( crypt_path ) )
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
|
185
|
+
def self.binary_to_write( to_filepath, crypt_header, binary_ciphertext )
|
186
|
+
|
187
|
+
base64_ciphertext = Base64.encode64( binary_ciphertext )
|
188
|
+
|
189
|
+
content_to_write =
|
190
|
+
crypt_header +
|
191
|
+
Indices::CONTENT_BLOCK_DELIMITER +
|
192
|
+
Indices::CONTENT_BLOCK_START_STRING +
|
193
|
+
base64_ciphertext +
|
194
|
+
Indices::CONTENT_BLOCK_END_STRING +
|
195
|
+
Indices::CONTENT_BLOCK_DELIMITER
|
196
|
+
|
197
|
+
File.write( to_filepath, content_to_write )
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
def self.binary_from_read( from_filepath )
|
203
|
+
|
204
|
+
file_text = File.read( from_filepath )
|
205
|
+
core_data = file_text.in_between( Indices::CONTENT_BLOCK_START_STRING, Indices::CONTENT_BLOCK_END_STRING ).strip
|
206
|
+
return Base64.decode64( core_data )
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module SafeDb
|
4
|
+
|
5
|
+
# Indices are key/value pairs that serve within the safe database index
|
6
|
+
# files for denoting, pinpointing, writing and retrieving data values as
|
7
|
+
# well as for naming of files folders and other artifacts.
|
8
|
+
class Indices
|
9
|
+
|
10
|
+
# The command used to invoke the safe database
|
11
|
+
COMMANDER = "safe"
|
12
|
+
|
13
|
+
# The short url name of the safe personal database.
|
14
|
+
SAFE_URL_NAME = "safedb.net"
|
15
|
+
|
16
|
+
# The desired length of a safe book ergonomic identifier.
|
17
|
+
SAFE_BOOK_ID_LENGTH = 12
|
18
|
+
|
19
|
+
# The fully qualified domain name of the safedb home website
|
20
|
+
SAFE_GEM_WEBSITE = "https://www.#{SAFE_URL_NAME}"
|
21
|
+
|
22
|
+
# The safe database github clonable url for the ruby software
|
23
|
+
SAFE_GITHUB_URL = "https://github.com/devops4me/#{SAFE_URL_NAME}"
|
24
|
+
|
25
|
+
# The name ofthe master crypts folder.
|
26
|
+
MASTER_CRYPTS_FOLDER_NAME = "safedb-master-crypts"
|
27
|
+
|
28
|
+
# The name ofthe branch indices folder.
|
29
|
+
BRANCH_INDICES_FOLDER_NAME = "safedb-branch-indices"
|
30
|
+
|
31
|
+
# The name ofthe branch crypts folder.
|
32
|
+
BRANCH_CRYPTS_FOLDER_NAME = "safedb-branch-crypts"
|
33
|
+
|
34
|
+
# The file-system location of the safe database tree
|
35
|
+
SAFE_DATABASE_FOLDER = File.join( Dir.home, ".#{SAFE_URL_NAME}" )
|
36
|
+
|
37
|
+
# The path to the master indices file
|
38
|
+
MASTER_INDICES_FILEPATH = File.join( SAFE_DATABASE_FOLDER, "safedb-master-indices.ini" )
|
39
|
+
|
40
|
+
# The desired length of a content identifier
|
41
|
+
CONTENT_ID_LENGTH = 14
|
42
|
+
|
43
|
+
# Content identifiers act to name chapter and/or index database files.
|
44
|
+
CONTENT_IDENTIFIER = "content.id"
|
45
|
+
|
46
|
+
# The AES symmetric encryption initialization vector
|
47
|
+
CONTENT_RANDOM_IV = "content.iv"
|
48
|
+
|
49
|
+
# The commit identifiers of the master and branch are compared to ascertain eligibility for checkins
|
50
|
+
COMMIT_IDENTIFIER = "commit.identifier"
|
51
|
+
|
52
|
+
# The bootup id is set on machine boot and lasts until the reboot or shutdown.
|
53
|
+
BOOTUP_IDENTIFIER = "bootup.identifier"
|
54
|
+
|
55
|
+
# The key ciphertext that sits against the trio of either master, branch or chapter
|
56
|
+
CRYPT_CIPHER_TEXT = "crypt.cipher"
|
57
|
+
|
58
|
+
# This is the global section header of the branch book index file
|
59
|
+
BRANCH_DATA = "branch.data"
|
60
|
+
|
61
|
+
# The time of the first book login within this shell
|
62
|
+
BRANCH_INITIAL_LOGIN_TIME = "branch.initial.login.time"
|
63
|
+
|
64
|
+
# The most recent time that any book of this branch was accessed
|
65
|
+
BRANCH_LAST_ACCESSED_TIME = "branch.last.accessed.time"
|
66
|
+
|
67
|
+
# The ID of the book being currently used by this branch
|
68
|
+
CURRENT_BRANCH_BOOK_ID = "current.branch.book.id"
|
69
|
+
|
70
|
+
# The time this book was first logged into during this branch
|
71
|
+
BOOK_BRANCH_LOGIN_TIME = "book.branch.login.time"
|
72
|
+
|
73
|
+
# The time this book was last accessed during this branch
|
74
|
+
BOOK_LAST_ACCESSED_TIME = "book.last.accessed.time"
|
75
|
+
|
76
|
+
# The start of the content block laid out in a crypt file
|
77
|
+
CONTENT_BLOCK_START_STRING = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789ab\n"
|
78
|
+
|
79
|
+
# The end of the content block laid out in a crypt file
|
80
|
+
CONTENT_BLOCK_END_STRING = "ba9876543210fedcba9876543210fedcba9876543210fedcba9876543210\n"
|
81
|
+
|
82
|
+
# The delimeter used to separate headers from ciphertext in a crypt file
|
83
|
+
CONTENT_BLOCK_DELIMITER = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
|
84
|
+
|
85
|
+
# The name of the safe tty token environment variable
|
86
|
+
TOKEN_VARIABLE_NAME = "SAFE_TTY_TOKEN"
|
87
|
+
|
88
|
+
# The expected length of the tty token environment variable
|
89
|
+
TOKEN_VARIABLE_SIZE = 152
|
90
|
+
|
91
|
+
# Character (randomly) repeated to mask credentials
|
92
|
+
# Asterices, hyphens, plus and equal signs are common alternatives.
|
93
|
+
SECRET_MASK_STRING = "*" * rand( 7 .. 17 )
|
94
|
+
|
95
|
+
# The birthday (initialization time) of this safe book.
|
96
|
+
SAFE_BOOK_INITIALIZE_TIME = "book.init.time"
|
97
|
+
|
98
|
+
# The name of this safe book.
|
99
|
+
SAFE_BOOK_NAME = "book.name"
|
100
|
+
|
101
|
+
# The application version that oversaw this book's initialization.
|
102
|
+
SAFE_BOOK_INIT_VERSION = "book.init.version"
|
103
|
+
|
104
|
+
# The application version that oversaw this book's initialization.
|
105
|
+
SAFE_BOOK_CURRENT_VERSION = "book.current.version"
|
106
|
+
|
107
|
+
# The handle to the chapter keys inside the book index.
|
108
|
+
SAFE_BOOK_CHAPTER_KEYS = "book.chapter.keys"
|
109
|
+
|
110
|
+
# The opened chapter id/name in the current book
|
111
|
+
OPENED_CHAPTER_NAME = "book.open.chapter"
|
112
|
+
|
113
|
+
# The opened verse id/name in the current book
|
114
|
+
OPENED_VERSE_NAME = "book.open.verse"
|
115
|
+
|
116
|
+
# The application version that oversaw this book's initialization.
|
117
|
+
SAFE_VERSION_STRING = "safedb-v#{SafeDb::VERSION}"
|
118
|
+
|
119
|
+
# Handle to the key name of the ingested file in the submap verse
|
120
|
+
INGESTED_FILE_LINE_NAME_KEY = "safedb.file::"
|
121
|
+
|
122
|
+
# Handle to the file base64 content within the submap verse
|
123
|
+
INGESTED_FILE_CONTENT64_KEY = "file.content"
|
124
|
+
|
125
|
+
# Handle to the simple name of the ingested file in the submap verse
|
126
|
+
INGESTED_FILE_BASE_NAME_KEY = "file.name"
|
127
|
+
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
end
|