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/keytools/key.id.rb
DELETED
@@ -1,322 +0,0 @@
|
|
1
|
-
#!/usr/bin/ruby
|
2
|
-
# coding: utf-8
|
3
|
-
|
4
|
-
|
5
|
-
module SafeDb
|
6
|
-
|
7
|
-
|
8
|
-
# This class derives <b>non secret but unique identifiers</b> based on different
|
9
|
-
# combinations of the <b>application, shell and machine (compute element)</b>
|
10
|
-
# references.
|
11
|
-
#
|
12
|
-
# == Identifier Are Not Secrets
|
13
|
-
#
|
14
|
-
# <b>And their starting values are retrievable</b>
|
15
|
-
#
|
16
|
-
# Note that the principle and practise of <b>identifiers is not about keeping secrets</b>.
|
17
|
-
# An identifier can easily give up its starting value/s if and when brute force is
|
18
|
-
# applied. The properties of a good iidentifier (ID) are
|
19
|
-
#
|
20
|
-
# - non repeatability (also known as uniqueness)
|
21
|
-
# - non predictability (of the next identifier)
|
22
|
-
# - containing alphanumerics (for file/folder/url names)
|
23
|
-
# - human readable (hence hyphens and separators)
|
24
|
-
# - non offensive (no swear words popping out)
|
25
|
-
#
|
26
|
-
# == Story | Identifiers Speak Volumes
|
27
|
-
#
|
28
|
-
# I told a friend what the turnover of his company was and how many clients he had.
|
29
|
-
# He was shocked and wanted to know how I had gleened this information.
|
30
|
-
#
|
31
|
-
# The invoices he sent me (a year apart). Both his invoice IDs (identifiers) and his
|
32
|
-
# user IDs where integers that counted up. So I could determine how many new clients
|
33
|
-
# he had in the past year, how many clients he had when I got the invoice, and I
|
34
|
-
# determined the turnover by guesstimating the average invoice amount.
|
35
|
-
#
|
36
|
-
# Many successful website attacks are owed to a predictable customer ID or a counter
|
37
|
-
# type session ID within the cookies.
|
38
|
-
#
|
39
|
-
# == Good Identifiers Need Volumes
|
40
|
-
#
|
41
|
-
# IDs are not secrets - but even so, a large number of properties are required
|
42
|
-
# to produce a high quality ID.
|
43
|
-
#
|
44
|
-
class KeyId
|
45
|
-
|
46
|
-
|
47
|
-
# The identity chunk length is set at four (4) which means each of the
|
48
|
-
# fabricated identifiers comprises of four character segments divided by
|
49
|
-
# hyphens. Only the <b>62 alpha-numerics ( a-z, A-Z and 0-9 )</b> will
|
50
|
-
# appear within identifiers - which maintains simplicity and provides an
|
51
|
-
# opportunity to re-iterate that <b>identifiers</b> are designed to be
|
52
|
-
# <b>unpredictable</b>, but <b>not secret</b>.
|
53
|
-
IDENTITY_CHUNK_LENGTH = 4
|
54
|
-
|
55
|
-
|
56
|
-
# A hyphen is the chosen character for dividing the identifier strings
|
57
|
-
# into chunks of four (4) as per the {IDENTITY_CHUNK_LENGTH} constant.
|
58
|
-
SEGMENT_CHAR = "-"
|
59
|
-
|
60
|
-
|
61
|
-
# Get an identifier that is <b>always the same</b> for the parameter
|
62
|
-
# application reference <b>regardless of the machine or shell</b> or
|
63
|
-
# even the machine user, coming together to make the request.
|
64
|
-
#
|
65
|
-
# The returned identifier will consist only of alphanumeric characters
|
66
|
-
# and one hyphen, plus it always starts and ends with an alphanumeric.
|
67
|
-
#
|
68
|
-
# @param app_instance_ref [String]
|
69
|
-
# the string reference of the application instance (or shard) that
|
70
|
-
# is in play and needs to be digested into a unique but not-a-secret
|
71
|
-
# identifier.
|
72
|
-
#
|
73
|
-
# @return [String]
|
74
|
-
# An identifier that is guaranteed to be the same whenever the
|
75
|
-
# same application reference is provided on any machine, using any
|
76
|
-
# user through any shell interface or command prompt.
|
77
|
-
#
|
78
|
-
# It must be different for any other application reference.
|
79
|
-
def self.derive_app_instance_identifier( app_instance_ref )
|
80
|
-
return derive_identifier( app_instance_ref )
|
81
|
-
end
|
82
|
-
|
83
|
-
|
84
|
-
# Get an identifier that is <b>always the same</b> for the application
|
85
|
-
# instance (with reference given in parameter) on <b>this machine</b>
|
86
|
-
# and is always different when either/or or both the application ref
|
87
|
-
# and machine are different.
|
88
|
-
#
|
89
|
-
# The returned identifier will consist of only alphanumeric characters
|
90
|
-
# and hyphens - it will always start and end with an alphanumeric.
|
91
|
-
#
|
92
|
-
# This behaviour draws a fine line around the concept of machine, virtual
|
93
|
-
# machine, <b>workstation</b> and/or <b>compute element</b>.
|
94
|
-
#
|
95
|
-
# <b>(aka) The AIM ID</b>
|
96
|
-
#
|
97
|
-
# Returned ID is aka the <b>Application Instance Machine (AIM)</b> Id.
|
98
|
-
#
|
99
|
-
# @param app_ref [String]
|
100
|
-
# the string reference of the application instance (or shard) that
|
101
|
-
# is being used.
|
102
|
-
#
|
103
|
-
# @return [String]
|
104
|
-
# an identifier that is guaranteed to be the same whenever the
|
105
|
-
# same application reference is provided on this machine.
|
106
|
-
#
|
107
|
-
# it must be different on another machine even when the same
|
108
|
-
# application reference is provided.
|
109
|
-
#
|
110
|
-
# It will also be different on this workstation if the application
|
111
|
-
# instance identifier provided is different.
|
112
|
-
def self.derive_app_instance_machine_id( app_ref )
|
113
|
-
return derive_identifier( app_ref + derive_machine_identifier() )
|
114
|
-
end
|
115
|
-
|
116
|
-
|
117
|
-
# This method uses a one-way function to return a combinatorial digested
|
118
|
-
# machine identification string using a number of distinct input parameters
|
119
|
-
# to deliver the characteristic of producing the same identifier for the
|
120
|
-
# same machine, virtual machine, workstation and/or compute element, and
|
121
|
-
# reciprocally, a different one on a different machine.
|
122
|
-
#
|
123
|
-
# The userspace is also a key machine identifier so a different machine user
|
124
|
-
# generates a different identifier when all other things remain equal.
|
125
|
-
#
|
126
|
-
# @return [String]
|
127
|
-
# a one line textual machine workstation or compute element identifier
|
128
|
-
# that is (surprisingly) different when the machine user changes.
|
129
|
-
def self.derive_machine_identifier
|
130
|
-
|
131
|
-
require 'socket'
|
132
|
-
|
133
|
-
identity_text = [
|
134
|
-
Etc.getlogin,
|
135
|
-
get_machine_id(),
|
136
|
-
Socket.gethostname()
|
137
|
-
].join.reverse
|
138
|
-
|
139
|
-
return identity_text
|
140
|
-
|
141
|
-
end
|
142
|
-
|
143
|
-
|
144
|
-
# The machine identifier is a UUID based hash value that is tied to the
|
145
|
-
# CPU and motherboard of the machine. This read-only identifier can be
|
146
|
-
# accessed without sudoer permissions so is perfect for license generators
|
147
|
-
# and environment sensitive software.
|
148
|
-
#
|
149
|
-
# In the modern era of virtualization you should always check the behaviour
|
150
|
-
# of the above identifiers when used inside
|
151
|
-
#
|
152
|
-
# - docker containers
|
153
|
-
# - Amazon EC2 servers (or Azure or GCE)
|
154
|
-
# - vagrant (VirtualBox/VMWare)
|
155
|
-
# - Windows MSGYWIN (Ubuntu) environments
|
156
|
-
# - Kubernetes pods
|
157
|
-
#
|
158
|
-
# @return [String] the machine ID hash value
|
159
|
-
def self.get_machine_id
|
160
|
-
|
161
|
-
machine_id_cmd = "cat /etc/machine-id"
|
162
|
-
machine_id_str = %x[ #{machine_id_cmd} ]
|
163
|
-
return machine_id_str.chomp
|
164
|
-
|
165
|
-
end
|
166
|
-
|
167
|
-
|
168
|
-
# The <b>32 character</b> <b>universal identifier</b> bonds a digested
|
169
|
-
# <b>application state identifier</b> with the <b>shell identifier</b>.
|
170
|
-
# This method gives <b>dual double guarantees</b> to the effect that
|
171
|
-
#
|
172
|
-
# - a change in one, or in the other, or in both returns a different universal id
|
173
|
-
# - the same app state identifier in the same shell produces the same universal id
|
174
|
-
#
|
175
|
-
# <b>The 32 Character Universal Identifier</b>
|
176
|
-
#
|
177
|
-
# The universal identifier is an amalgam of two digests which can be individually
|
178
|
-
# retrieved from other methods in this class. An example is
|
179
|
-
#
|
180
|
-
# universal id => hg2x0-g3uslf-pa2bl5-09xvbd-n4wcq
|
181
|
-
# the shell id => g3uslf-pa2bl5-09xvbd
|
182
|
-
# app state id => hg2x0-n4wcq
|
183
|
-
#
|
184
|
-
# The 32 character universal identifier comprises of 18 session identifier
|
185
|
-
# characters (see {derive_session_id}) <b>sandwiched between</b>
|
186
|
-
# ten (10) digested application identifier characters, five (5) in front and
|
187
|
-
# five (5) at the back - all segmented by four (4) hyphens.
|
188
|
-
#
|
189
|
-
# @param app_reference [String]
|
190
|
-
# the chosen plaintext application reference identifier that
|
191
|
-
# is the input to the digesting (hashing) algorithm.
|
192
|
-
#
|
193
|
-
# @param session_token [String]
|
194
|
-
# a triply segmented (and one liner) text token instantiated by
|
195
|
-
# {KeyLocal.generate_shell_key_and_token} and provided
|
196
|
-
# here ad verbatim.
|
197
|
-
#
|
198
|
-
# @return [String]
|
199
|
-
# a 32 character string that cannot feasibly be repeated due to the use
|
200
|
-
# of one way functions within its derivation. The returned identifier bonds
|
201
|
-
# the application state reference with the present session.
|
202
|
-
def self.derive_universal_id( app_reference, session_token )
|
203
|
-
|
204
|
-
shellid = derive_session_id( session_token )
|
205
|
-
app_ref = derive_identifier( app_reference + shellid )
|
206
|
-
chunk_1 = app_ref[ 0 .. IDENTITY_CHUNK_LENGTH ]
|
207
|
-
chunk_3 = app_ref[ ( IDENTITY_CHUNK_LENGTH + 1 ) .. -1 ]
|
208
|
-
|
209
|
-
return "#{chunk_1}#{shellid}#{SEGMENT_CHAR}#{chunk_3}".downcase
|
210
|
-
|
211
|
-
end
|
212
|
-
|
213
|
-
|
214
|
-
# The session ID generated here is a derivative of the 150 character
|
215
|
-
# session token instantiated by {KeyLocal.generate_shell_key_and_token}
|
216
|
-
# and provided here <b>ad verbatim</b>.
|
217
|
-
#
|
218
|
-
# The algorithm for deriving the session ID is as follows.
|
219
|
-
#
|
220
|
-
# - convert the 150 characters to an alphanumeric string
|
221
|
-
# - convert the result to a bit string and then to a key
|
222
|
-
# - put the key's binary form through a 384 bit digest
|
223
|
-
# - convert the digest's output to 64 YACHT64 characters
|
224
|
-
# - remove the (on average 2) non-alphanumeric characters
|
225
|
-
# - cherry pick a spread out 12 characters from the pool
|
226
|
-
# - hiphenate the character positions five (5) and ten (10)
|
227
|
-
# - ensure the length of the resultant ID is fourteen (14)
|
228
|
-
#
|
229
|
-
# The resulting session id will look something like this
|
230
|
-
#
|
231
|
-
# g3sf-pab5-9xvd
|
232
|
-
#
|
233
|
-
# @param session_token [String]
|
234
|
-
# a triply segmented (and one liner) text token instantiated by
|
235
|
-
# {KeyLocal.generate_shell_key_and_token} and provided here ad
|
236
|
-
# verbatim.
|
237
|
-
#
|
238
|
-
# @return [String]
|
239
|
-
# a 14 character string that cannot feasibly be repeated
|
240
|
-
# within the keyspace of even a gigantic organisation.
|
241
|
-
#
|
242
|
-
# This method guarantees that the session id will always be the same when
|
243
|
-
# called by commands within the same shell in the same machine.
|
244
|
-
def self.derive_session_id( session_token )
|
245
|
-
|
246
|
-
assert_session_token_size( session_token )
|
247
|
-
random_length_id_key = Key.from_char64( session_token.to_alphanumeric )
|
248
|
-
a_384_bit_key = random_length_id_key.to_384_bit_key()
|
249
|
-
a_64_char_str = a_384_bit_key.to_char64()
|
250
|
-
base_64_chars = a_64_char_str.to_alphanumeric
|
251
|
-
|
252
|
-
id_chars_pool = KeyAlgo.cherry_picker( ID_TRI_CHUNK_LEN, base_64_chars )
|
253
|
-
id_hyphen_one = id_chars_pool.insert( IDENTITY_CHUNK_LENGTH, SEGMENT_CHAR )
|
254
|
-
id_characters = id_hyphen_one.insert( ( IDENTITY_CHUNK_LENGTH * 2 + 1 ), SEGMENT_CHAR )
|
255
|
-
|
256
|
-
err_msg = "Shell ID needs #{ID_TRI_TOTAL_LEN} not #{id_characters.length} characters."
|
257
|
-
raise RuntimeError, err_msg unless id_characters.length == ID_TRI_TOTAL_LEN
|
258
|
-
|
259
|
-
return id_characters.downcase
|
260
|
-
|
261
|
-
end
|
262
|
-
|
263
|
-
|
264
|
-
# This method returns a <b>10 character</b> digest of the parameter
|
265
|
-
# <b>reference</b> string.
|
266
|
-
#
|
267
|
-
# <b>How to Derive the 10 Character Identifier</b>
|
268
|
-
#
|
269
|
-
# So how are the 10 characters derived from the reference provided in
|
270
|
-
# the first parameter. The algorithm is this.
|
271
|
-
#
|
272
|
-
# - reverse the reference and feed it to a 256 bit digest
|
273
|
-
# - chop away the rightmost digits so that 252 bits are left
|
274
|
-
# - convert the one-zero bit str to 42 (YACHT64) characters
|
275
|
-
# - remove the (on average 1.5) non-alphanumeric characters
|
276
|
-
# - cherry pick and return <b>spread out 8 characters</b>
|
277
|
-
#
|
278
|
-
# @param reference [String]
|
279
|
-
# the plaintext reference input to the digest algorithm
|
280
|
-
#
|
281
|
-
# @return [String]
|
282
|
-
# a 10 character string that is a digest of the reference string
|
283
|
-
# provided in the parameter.
|
284
|
-
def self.derive_identifier( reference )
|
285
|
-
|
286
|
-
bitstr_256 = Key.from_binary( Digest::SHA256.digest( reference.reverse ) ).to_s
|
287
|
-
bitstr_252 = bitstr_256[ 0 .. ( BIT_LENGTH_252 - 1 ) ]
|
288
|
-
id_err_msg = "The ID digest needs #{BIT_LENGTH_252} not #{bitstr_252.length} chars."
|
289
|
-
raise RuntimeError, id_err_msg unless bitstr_252.length == BIT_LENGTH_252
|
290
|
-
|
291
|
-
id_chars_pool = Key64.from_bits( bitstr_252 ).to_alphanumeric
|
292
|
-
undivided_str = KeyAlgo.cherry_picker( ID_TWO_CHUNK_LEN, id_chars_pool )
|
293
|
-
id_characters = undivided_str.insert( IDENTITY_CHUNK_LENGTH, SEGMENT_CHAR )
|
294
|
-
|
295
|
-
min_size_msg = "Id length #{id_characters.length} is not #{(ID_TWO_CHUNK_LEN + 1)} chars."
|
296
|
-
raise RuntimeError, min_size_msg unless id_characters.length == ( ID_TWO_CHUNK_LEN + 1 )
|
297
|
-
|
298
|
-
return id_characters.downcase
|
299
|
-
|
300
|
-
end
|
301
|
-
|
302
|
-
|
303
|
-
private
|
304
|
-
|
305
|
-
|
306
|
-
ID_TWO_CHUNK_LEN = IDENTITY_CHUNK_LENGTH * 2
|
307
|
-
ID_TRI_CHUNK_LEN = IDENTITY_CHUNK_LENGTH * 3
|
308
|
-
ID_TRI_TOTAL_LEN = ID_TRI_CHUNK_LEN + 2
|
309
|
-
|
310
|
-
BIT_LENGTH_252 = 252
|
311
|
-
|
312
|
-
|
313
|
-
def self.assert_session_token_size session_token
|
314
|
-
err_msg = "Session token has #{session_token.length} and not #{KeyLocal::SESSION_TOKEN_SIZE} chars."
|
315
|
-
raise RuntimeError, err_msg unless session_token.length == KeyLocal::SESSION_TOKEN_SIZE
|
316
|
-
end
|
317
|
-
|
318
|
-
|
319
|
-
end
|
320
|
-
|
321
|
-
|
322
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
#!/usr/bin/ruby
|
2
|
-
|
3
|
-
module SafeDb
|
4
|
-
|
5
|
-
module ToolBelt
|
6
|
-
|
7
|
-
|
8
|
-
# This class knows how to amalgamate passwords, keys and string data in
|
9
|
-
# a manner that is the cryptographical equivalent of synergy.
|
10
|
-
#
|
11
|
-
# The amalgamated keys are synergially (cryptographically) greater than
|
12
|
-
# the sum of their parts.
|
13
|
-
class Amalgam
|
14
|
-
|
15
|
-
# Amalgamate the two parameter passwords in a manner that is the
|
16
|
-
# cryptographical equivalent of synergy. The amalgamated keys are
|
17
|
-
# synergially greater than the sum of their parts.
|
18
|
-
#
|
19
|
-
# -- Get a viable machine password taking into account the human
|
20
|
-
# -- password length and the specified mix_ratio.
|
21
|
-
#
|
22
|
-
#
|
23
|
-
# @param human_password [String] the password originating from a human
|
24
|
-
# @param machine_key [String] a machine engineered ascii password (key)
|
25
|
-
# @mixparam machine_key [String] a machine engineered ascii password (key)
|
26
|
-
#
|
27
|
-
# @return [String] the union of the two parameter passwords
|
28
|
-
#
|
29
|
-
# @raise [ArgumentError] when the size of the two passwords and the
|
30
|
-
# mix ratio do not conform to the constraint imposed by the below
|
31
|
-
# equation which must hold true.
|
32
|
-
# <tt>machine password length = human password length * mix_ratio - 1</tt>
|
33
|
-
#
|
34
|
-
def self.passwords human_password, machine_password, mix_ratio
|
35
|
-
|
36
|
-
size_error_msg = "Human pass length times mix_ratio must equal machine pass length."
|
37
|
-
lengths_are_perfect = human_password.length * mix_ratio == machine_password.length
|
38
|
-
raise ArgumentError.new size_error_msg unless lengths_are_perfect
|
39
|
-
|
40
|
-
machine_passwd_chunk = 0
|
41
|
-
amalgam_passwd_index = 0
|
42
|
-
amalgamated_password = ""
|
43
|
-
|
44
|
-
human_password.each_char do |passwd_char|
|
45
|
-
|
46
|
-
amalgamated_password[amalgam_passwd_index] = passwd_char
|
47
|
-
amalgam_passwd_index += 1
|
48
|
-
|
49
|
-
for i in 0..(mix_ratio-1) do
|
50
|
-
machine_pass_index = machine_passwd_chunk * mix_ratio + i
|
51
|
-
amalgamated_password[amalgam_passwd_index] = machine_password[machine_pass_index]
|
52
|
-
amalgam_passwd_index += 1
|
53
|
-
end
|
54
|
-
|
55
|
-
machine_passwd_chunk += 1
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
return amalgamated_password
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
|
70
|
-
end
|
@@ -1,99 +0,0 @@
|
|
1
|
-
#!/usr/bin/ruby
|
2
|
-
|
3
|
-
module SafeDb
|
4
|
-
|
5
|
-
module ToolBelt
|
6
|
-
|
7
|
-
|
8
|
-
require 'securerandom'
|
9
|
-
|
10
|
-
# This class will be refactored into an interface implemented by a set
|
11
|
-
# of plugins that will capture sensitive information from users from an
|
12
|
-
# Ubuntu, Windows, RHEL, CoreOS, iOS or CentOS command line interface.
|
13
|
-
#
|
14
|
-
# An equivalent REST API will also be available for bringing in sensitive
|
15
|
-
# information in the most secure (but simple) manner.
|
16
|
-
class Engineer
|
17
|
-
|
18
|
-
|
19
|
-
# --
|
20
|
-
# -- Get a viable machine password taking into account the human
|
21
|
-
# -- password length and the specified mix_ratio.
|
22
|
-
# --
|
23
|
-
# -- machine password length = human password length * mix_ratio - 1
|
24
|
-
# --
|
25
|
-
def self.machine_key human_password_length, mix_ratio
|
26
|
-
|
27
|
-
machine_raw_secret = strong_key( human_password_length * ( mix_ratio + 1) )
|
28
|
-
return machine_raw_secret[ 0..( human_password_length * mix_ratio - 1 ) ]
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
|
-
# --
|
34
|
-
# -- Engineer a raw password that is similar (approximate) in
|
35
|
-
# -- length to the integer parameter.
|
36
|
-
# --
|
37
|
-
def self.strong_key approx_length
|
38
|
-
|
39
|
-
non_alphanum = SecureRandom.urlsafe_base64(approx_length);
|
40
|
-
return non_alphanum.delete("-_")
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
# Amalgamate the parameter passwords using a specific mix ratio. This method
|
46
|
-
# produces cryptographically stronger secrets than algorithms that simply
|
47
|
-
# concatenate two string keys together. If knowledge of one key were gained, this
|
48
|
-
# amalgamation algorithm still provides extremely strong protection even when
|
49
|
-
# one of the keys has a single digit length.
|
50
|
-
#
|
51
|
-
# This +length constraint formula+ binds the two input strings together with
|
52
|
-
# the integer mix ratio.
|
53
|
-
#
|
54
|
-
# <tt>machine password length = human password length * mix_ratio - 1</tt>
|
55
|
-
#
|
56
|
-
# @param human_password [String] the first password (shorter one) to amalgamate
|
57
|
-
# @param machine_password [String] the second password (longer one) to amalgamate
|
58
|
-
# @param mix_ratio [Fixnum] the mix ratio that must be respected by the
|
59
|
-
# previous two parameters.
|
60
|
-
# @return [String] an amalgamated (reproducible) union of the 2 parameter passwords
|
61
|
-
#
|
62
|
-
# @raise [ArgumentError] if the length constraint assertion does not hold true
|
63
|
-
def self.get_amalgam_password human_password, machine_password, mix_ratio
|
64
|
-
|
65
|
-
size_error_msg = "Human pass length times mix_ratio must equal machine pass length."
|
66
|
-
lengths_are_perfect = human_password.length * mix_ratio == machine_password.length
|
67
|
-
raise ArgumentError.new size_error_msg unless lengths_are_perfect
|
68
|
-
|
69
|
-
machine_passwd_chunk = 0
|
70
|
-
amalgam_passwd_index = 0
|
71
|
-
amalgamated_password = ""
|
72
|
-
|
73
|
-
human_password.each_char do |passwd_char|
|
74
|
-
|
75
|
-
amalgamated_password[amalgam_passwd_index] = passwd_char
|
76
|
-
amalgam_passwd_index += 1
|
77
|
-
|
78
|
-
for i in 0..(mix_ratio-1) do
|
79
|
-
machine_pass_index = machine_passwd_chunk * mix_ratio + i
|
80
|
-
amalgamated_password[amalgam_passwd_index] = machine_password[machine_pass_index]
|
81
|
-
amalgam_passwd_index += 1
|
82
|
-
end
|
83
|
-
|
84
|
-
machine_passwd_chunk += 1
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
return amalgamated_password
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
|
93
|
-
end
|
94
|
-
|
95
|
-
|
96
|
-
end
|
97
|
-
|
98
|
-
|
99
|
-
end
|