safedb 0.01.0001

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.yardopts +3 -0
  4. data/Gemfile +10 -0
  5. data/LICENSE +21 -0
  6. data/README.md +793 -0
  7. data/Rakefile +16 -0
  8. data/bin/safe +5 -0
  9. data/lib/configs/README.md +58 -0
  10. data/lib/extension/array.rb +162 -0
  11. data/lib/extension/dir.rb +35 -0
  12. data/lib/extension/file.rb +123 -0
  13. data/lib/extension/hash.rb +33 -0
  14. data/lib/extension/string.rb +572 -0
  15. data/lib/factbase/facts.safedb.net.ini +38 -0
  16. data/lib/interprete.rb +462 -0
  17. data/lib/keytools/PRODUCE_RAND_SEQ_USING_DEV_URANDOM.txt +0 -0
  18. data/lib/keytools/kdf.api.rb +243 -0
  19. data/lib/keytools/kdf.bcrypt.rb +265 -0
  20. data/lib/keytools/kdf.pbkdf2.rb +262 -0
  21. data/lib/keytools/kdf.scrypt.rb +190 -0
  22. data/lib/keytools/key.64.rb +326 -0
  23. data/lib/keytools/key.algo.rb +109 -0
  24. data/lib/keytools/key.api.rb +1391 -0
  25. data/lib/keytools/key.db.rb +330 -0
  26. data/lib/keytools/key.docs.rb +195 -0
  27. data/lib/keytools/key.error.rb +110 -0
  28. data/lib/keytools/key.id.rb +271 -0
  29. data/lib/keytools/key.ident.rb +243 -0
  30. data/lib/keytools/key.iv.rb +107 -0
  31. data/lib/keytools/key.local.rb +259 -0
  32. data/lib/keytools/key.now.rb +402 -0
  33. data/lib/keytools/key.pair.rb +259 -0
  34. data/lib/keytools/key.pass.rb +120 -0
  35. data/lib/keytools/key.rb +585 -0
  36. data/lib/logging/gem.logging.rb +132 -0
  37. data/lib/modules/README.md +43 -0
  38. data/lib/modules/cryptology/aes-256.rb +154 -0
  39. data/lib/modules/cryptology/amalgam.rb +70 -0
  40. data/lib/modules/cryptology/blowfish.rb +130 -0
  41. data/lib/modules/cryptology/cipher.rb +207 -0
  42. data/lib/modules/cryptology/collect.rb +138 -0
  43. data/lib/modules/cryptology/crypt.io.rb +225 -0
  44. data/lib/modules/cryptology/engineer.rb +99 -0
  45. data/lib/modules/mappers/dictionary.rb +288 -0
  46. data/lib/modules/storage/coldstore.rb +186 -0
  47. data/lib/modules/storage/git.store.rb +399 -0
  48. data/lib/session/fact.finder.rb +334 -0
  49. data/lib/session/require.gem.rb +112 -0
  50. data/lib/session/time.stamp.rb +340 -0
  51. data/lib/session/user.home.rb +49 -0
  52. data/lib/usecase/cmd.rb +487 -0
  53. data/lib/usecase/config/README.md +57 -0
  54. data/lib/usecase/docker/README.md +146 -0
  55. data/lib/usecase/docker/docker.rb +49 -0
  56. data/lib/usecase/edit/README.md +43 -0
  57. data/lib/usecase/edit/delete.rb +46 -0
  58. data/lib/usecase/export.rb +40 -0
  59. data/lib/usecase/files/README.md +37 -0
  60. data/lib/usecase/files/eject.rb +56 -0
  61. data/lib/usecase/files/file_me.rb +78 -0
  62. data/lib/usecase/files/read.rb +169 -0
  63. data/lib/usecase/files/write.rb +89 -0
  64. data/lib/usecase/goto.rb +57 -0
  65. data/lib/usecase/id.rb +36 -0
  66. data/lib/usecase/import.rb +157 -0
  67. data/lib/usecase/init.rb +63 -0
  68. data/lib/usecase/jenkins/README.md +146 -0
  69. data/lib/usecase/jenkins/jenkins.rb +208 -0
  70. data/lib/usecase/login.rb +71 -0
  71. data/lib/usecase/logout.rb +28 -0
  72. data/lib/usecase/open.rb +71 -0
  73. data/lib/usecase/print.rb +40 -0
  74. data/lib/usecase/put.rb +81 -0
  75. data/lib/usecase/set.rb +44 -0
  76. data/lib/usecase/show.rb +138 -0
  77. data/lib/usecase/terraform/README.md +91 -0
  78. data/lib/usecase/terraform/terraform.rb +121 -0
  79. data/lib/usecase/token.rb +35 -0
  80. data/lib/usecase/update/README.md +55 -0
  81. data/lib/usecase/update/rename.rb +180 -0
  82. data/lib/usecase/use.rb +41 -0
  83. data/lib/usecase/verse.rb +20 -0
  84. data/lib/usecase/view.rb +71 -0
  85. data/lib/usecase/vpn/README.md +150 -0
  86. data/lib/usecase/vpn/vpn.ini +31 -0
  87. data/lib/usecase/vpn/vpn.rb +54 -0
  88. data/lib/version.rb +3 -0
  89. data/safedb.gemspec +34 -0
  90. metadata +193 -0
@@ -0,0 +1,326 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module SafeDb
4
+
5
+ # First use the class methods to source keys, then use a key's instance
6
+ # methods to access its properties and in concert with other symmetrical
7
+ # information, you can use the keys to lock (encrypt) or unlock (decrypt)
8
+ # other keys and objects.
9
+ #
10
+ # == Sourcing and Deriving Keys
11
+ #
12
+ # Keys can be
13
+ #
14
+ # - sourced from a secure random byte generating function
15
+ # - sourced from ciphertext and another (decryption) key
16
+ # - generated by passing a secret through key derivation functions
17
+ # - regenerated from a secret and previously stored salts
18
+ # - sourced from the current unique workstation shell environment
19
+ # - sourced from an environment variable containing ciphertext
20
+ #
21
+ #
22
+ # Keys need to be viewed (represented) in multiple ways and the essence
23
+ # of the key viewer is to input keys {as_bits}, {as_bytes} and {as_base64}
24
+ # and then output the same key (in as far as is possible) - as bits, as
25
+ # bytes and as base64.
26
+ #
27
+ # == Key | To and From Behaviour
28
+ #
29
+ # Use the <b>From</b> methods to create Keys from a variety of resources
30
+ # such as
31
+ #
32
+ # - a base64 encoded string
33
+ # - a binary byte string
34
+ # - a string of one and zero bits
35
+ # - a hexadecimal representation
36
+ #
37
+ # Once you have instantiated the key, you will then be able to convert it
38
+ # (within reason due to bit, byte and base64 lengths) to any of the above
39
+ # key representations.
40
+ #
41
+ # == Key | Bits Bytes and Base64
42
+ #
43
+ # The shoe doesn't always fit when its on the other foot and this is best
44
+ # illustratd with a table that maps bits to 8 bit bytes and 6 bit Base64
45
+ # characters.
46
+ #
47
+ # | --------- | -------- | ------------ | ------------------------------- |
48
+ # | Fit? | Bits | Bytes | (and) Base64 |
49
+ # | --------- | -------- | ------------ | ------------------------------- |
50
+ # | Perfect | 168 Bits | is 21 bytes | 28 Chars - bcrypt chops to this |
51
+ # | Perfect | 216 Bits | is 27 bytes | 36 Chars - |
52
+ # | Perfect | 264 Bits | is 33 bytes | 44 Chars - holder 4 256bit keys |
53
+ # | Perfect | 384 Bits | is 48 bytes | 64 Chars - 216 + 168 equals 384 |
54
+ # | --------- | -------- | ------------ | ------------------------------- |
55
+ # | Imperfect | 128 Bits | 16 precisely | 22 Chars - 21 + 2 remain bits |
56
+ # | Imperfect | 186 Bits | 23 remain 2 | 31 Characers precisely |
57
+ # | Imperfect | 256 Bits | 32 precisely | 43 Chars - 42 + 4 remain bits |
58
+ # | --------- | -------- | ------------ | ------------------------------- |
59
+ #
60
+ # Yes, the shoe doesn't always fit when it's on the other foot.
61
+ #
62
+ # == Schoolboy Error
63
+ #
64
+ # <b>The strategy is so simple, we call it a schoolboy error.</b>
65
+ #
66
+ # If we want to use a key with n bits and either n % 6 or n % 8 (or both)
67
+ # are not zero - <b>we instantiate a Key</b> with the lowest common
68
+ # denominator of 6 and 8 that exceeds n.
69
+ #
70
+ # So when we request a byte, or base64 representation the viewer will
71
+ # truncate (not round down) to the desired length.
72
+ #
73
+ #
74
+ # == YACHT 64 | Yet Another Character Table
75
+ #
76
+ # This binary key class is a dab hand at converting base64 strings
77
+ # into their 6-bit binary string equivalents.
78
+ #
79
+ # It can convert non-alphanumeric characters within either Base64 or
80
+ # Radix64 into the SafeDb YACHT64 standard which has a forward slash
81
+ # but neither a plus sign nor a period character.
82
+ #
83
+ # <b>The Big4 Character Sets | Base64 | UrlSafe64 | Radix64 | YACHT64</b>
84
+ #
85
+ # Base64 and Radix64 (from OpenBSD) differ in both the order of characters
86
+ # and their choice of the two non-alphanumeric characters. Base64 can also
87
+ # contain line breaks and equal signs for padding. UrlSafe base64 has different
88
+ # choices for the two non alphanum characters in keeping with URL standards.
89
+ #
90
+ # The character sets for each of the four 64 fomats are as follows.
91
+ #
92
+ # - Base-64 is <b>A to Z</b> then <b>a to z</b> then <b>0 to 9</b> then <b>+</b> then <b>/</b>
93
+ # - Radix64 is <b>.</b> then <b>/</b> then <b>0 to 9</b> then <b>A to Z</b> then <b>a to z</b>
94
+ # - UrlSafeBase64 is Base64 but chars 63/64 are an <b>underscore (_)</b> and <b>hyphen (-)</b>
95
+ # - UrlSafeBase64 <b>does not have line breaks and carriage returns</b> (unlike Base64)
96
+ # - <b>SafeDb 64 (YACHT64)</b> uses the same 62 characters plus an @ sign and a forward slash
97
+ # - The 64 <b>SafeDb 64</b> characters are <b>obfuscated into a random order</b>
98
+ #
99
+ # == 4 Non-AlphaNumerics | Base64 | Radix64 | YACHT64
100
+ #
101
+ # The behaviour here is happy to convert base64 strings produced by either
102
+ # Radix64 or Base64 or UrlSafe Base64. Howeverr it aware of the
103
+ # <b>non alpha-numeric characters</b> and converts them before processing
104
+ # with the modus operandi that says
105
+ #
106
+ # - ignore the forward slash in <b>YACHT64, Base64 and Radix64</b>
107
+ # - convert the <b>plus (+)</b> in Base64 to the <b>@ symbol</b> in YACHT64
108
+ # - convert the <b>period (.)</b> in <b>Radix64</b> to the @ symbol in YACHT64
109
+ # - convert <b>hyphen (-)</b> in <b>Url Safe Base64</b> into a fwd slash
110
+ # - convert <b>underscore (_)</b> in <b>Url Safe Base64</b> to an @ sign
111
+ # - <b>delete the (=) equals</b> padding character used by Base64
112
+ #
113
+ # Neither the OpenBSD backed Radix64 nor the SafeDb (YACHT64) entertain the
114
+ # concept of padding.
115
+ #
116
+ # == Mapping Each Character to 6 Binary Bits
117
+ #
118
+ # We need 6 binary bits to represent a base64 character (and 4
119
+ # bits for hexadecimal). Here is an example mapping between
120
+ # a base 64 character, an integer and the six bit binary.
121
+ #
122
+ # Character Integer Binary (6 Bit)
123
+ #
124
+ # a 0 000000
125
+ # b 1 000001
126
+ # c 2 000010
127
+ #
128
+ # y 25 011001
129
+ # z 26 011010
130
+ # A 27 011011
131
+ # B 28 011100
132
+ #
133
+ # 8 60 111100
134
+ # 9 61 111101
135
+ # / 62 111110
136
+ # + 63 111111
137
+ #
138
+ class Key64
139
+
140
+ # YACHT stands for <b>Yet Another Character Table</b> and it
141
+ # can map binary sequences onto 64 well chosen characters.
142
+ #
143
+ # The 64 character sets are all similar in that they hold 64
144
+ # characters and they define two non alphanumeric characters
145
+ # because the 26 lowercase, 26 uppercase and 10 digits only
146
+ # adds up to an <b><em>agonisingly close</em></b> 62 characters.
147
+ #
148
+ YACHT64_CHARACTER_SET = [
149
+ "a", "9", "W", "B", "f", "K", "O", "z",
150
+ "3", "s", "1", "5", "c", "n", "E", "J",
151
+ "L", "A", "l", "6", "I", "w", "o", "g",
152
+ "k", "N", "t", "Y", "S", "%", "T", "b",
153
+ "V", "R", "H", "0", "@", "Z", "8", "F",
154
+ "G", "j", "u", "m", "M", "h", "4", "p",
155
+ "q", "d", "7", "v", "e", "2", "U", "X",
156
+ "r", "C", "y", "Q", "D", "x", "P", "i"
157
+ ]
158
+
159
+
160
+ # Radix64 strings can contain period characters in their midst.
161
+ PERIOD = "."
162
+
163
+ # Radix64 strings can contain forward slashes in their midst.
164
+ FORWARD_SLASH = "/"
165
+
166
+ # YACHT64 strings can contain at symbols in their midst.
167
+ AT_SYMBOL = "@"
168
+
169
+ # YACHT64 strings can contain percent signs in their midst.
170
+ PERCENT_SIGN = "%"
171
+
172
+
173
+ # Convert the parameter string of ones and zeroes into an
174
+ # internal base64 character set known as YACHT for yet another
175
+ # character table.
176
+ #
177
+ # @param bit_string [String]
178
+ # a string of ones and zeroes that can be sliced into
179
+ # six character chunks with each chunk then being mapped
180
+ # to a YACHT64 character.
181
+ #
182
+ # @return [String]
183
+ # printable characters from a set of 62 alpha-numerics
184
+ # plus an @ symbol and a percent % sign.
185
+ #
186
+ # @raise ArgumentError
187
+ # If the bit string is nil.
188
+ # Or if the bit string length is not a multiple of six.
189
+ # Or if it contains any character that is not a 1 or 0.
190
+ def self.from_bits bit_string
191
+
192
+ nil_err_msg = "The parameter bit string cannot be nil."
193
+ raise ArgumentError, nil_err_msg if bit_string.nil?
194
+
195
+ bit_size_msg = "The bit string length is not a multiple of #{SIX}."
196
+ raise ArgumentError, bit_size_msg unless bit_string.length % SIX == 0
197
+
198
+ num_unknowns = bit_string.delete("10").length
199
+ unknowns_msg = "The bit string has #{num_unknowns} characters that are not 1 or 0."
200
+ raise ArgumentError, unknowns_msg if num_unknowns > 0
201
+
202
+ characters64 = ""
203
+ char_count = bit_string.length / SIX
204
+ for n in 0 .. (char_count-1)
205
+ six_bit_chunk = bit_string[ (n*SIX), SIX ]
206
+ six_bit_index = six_bit_chunk.to_i(2)
207
+ characters64 += Key64.character(six_bit_index)
208
+ end
209
+
210
+ code_size_msg = "Length is #{characters64.length} but #{char_count} is expected."
211
+ raise RuntimeError, code_size_msg unless characters64.length == char_count
212
+
213
+ return characters64
214
+
215
+ end
216
+
217
+
218
+ # Convert the parameter characters based on an internal base64
219
+ # character set (known as YACHT) into a <b>bit string</b> of ones
220
+ # and zeroes.
221
+ #
222
+ # @param char64_string [String]
223
+ # The base64 character sequence which which will be used to
224
+ # derive the returned bit string. Naturally this character
225
+ # sequencee cannot be nil, nor can it contain any characters
226
+ # that are not present in {Key64::YACHT64_CHARACTER_SET}.
227
+ #
228
+ # @return [String]
229
+ # a string of ones and zeroes that have been strung out
230
+ # from each YACHT64 character. The returned string length of
231
+ # ones and zeroes will be exactly 6 times the length of the
232
+ # input parameter.
233
+ #
234
+ # @raise [ArgumentError]
235
+ # If a nil or zero length character string is received.
236
+ # Or if the character sequence contains a character not present
237
+ # in the {Key64::YACHT64_CHARACTER_SET}.
238
+ #
239
+ # @raise [RuntimeError]
240
+ # if the conversion does not result in 6 bits for every character
241
+ # in the parameter string.
242
+ def self.to_bits char64_string
243
+
244
+ bit_string = ""
245
+ char64_string.each_char do |the_char|
246
+
247
+ yacht64_index = YACHT64_CHARACTER_SET.index(the_char)
248
+ assert_yacht64_index( the_char, yacht64_index )
249
+ bit_string += "%06d" % [ yacht64_index.to_s(2) ]
250
+
251
+ end
252
+
253
+ assert_bit_lengths char64_string, bit_string
254
+ return bit_string
255
+
256
+ end
257
+
258
+
259
+ # Convert a string of Radix64 characters into a bit representation which
260
+ # will be 6 times longer than the input parameter. This method first
261
+ # converts the string into the internal YACHT64 format and then converts
262
+ # that to a bit string using the {Key64.to_bits} method.
263
+ #
264
+ # @param radix64_string [String]
265
+ # the radix64 string to convert into bits. This string will be a subset
266
+ # of the usual 62 character suspects together with period and forward
267
+ # slash characters.
268
+ #
269
+ # This parameter should not contain newlines nor carriage returns.
270
+ #
271
+ # @return [String]
272
+ # a string of ones and zeroes that represent the bits converted from the
273
+ # radix64 input. The return value will be exactly 6 times the number of
274
+ # input characters.
275
+ def self.from_radix64_to_bits radix64_string
276
+
277
+ yacht64_chars = radix64_string.gsub( PERIOD, AT_SYMBOL ).gsub( FORWARD_SLASH, PERCENT_SIGN )
278
+ out_bitstring = to_bits( yacht64_chars )
279
+ assert_bit_lengths( radix64_string, out_bitstring )
280
+ return out_bitstring
281
+
282
+ end
283
+
284
+
285
+
286
+ private
287
+
288
+
289
+
290
+ SIX = 6
291
+
292
+ def self.character char_index
293
+
294
+ index_oob_msg = "The character index must be between 0 and 63 inclusive."
295
+ index_is_oob = char_index < 0 || char_index > 63
296
+ raise ArgumentError, index_oob_msg if index_is_oob
297
+ return YACHT64_CHARACTER_SET[ char_index ]
298
+
299
+ end
300
+
301
+ def self.assert_bit_lengths( in_string, out_string )
302
+
303
+ in_length = in_string.length
304
+ out_length = out_string.length
305
+ good_ratio = out_length == in_length * SIX
306
+ size_msg = "Bit string length [#{out_length}] not 6 times more than [#{in_length}]."
307
+ raise RuntimeError, size_msg unless good_ratio
308
+
309
+ end
310
+
311
+ def self.assert_yacht64_index the_char, yacht64_index
312
+
313
+ nil_msg = "Character [ #{the_char} ] not in YACHT character set."
314
+ raise ArgumentError, nil_msg if yacht64_index.nil?
315
+
316
+ index_msg = "Index of character [ #{the_char} ] not within expected bounds."
317
+ all_good = ( yacht64_index >= 0 ) && ( yacht64_index <= 63 )
318
+ raise ArgumentError, index_msg unless all_good
319
+
320
+ end
321
+
322
+
323
+ end
324
+
325
+
326
+ end
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/ruby
2
+ # coding: utf-8
3
+
4
+ module SafeDb
5
+
6
+ # Algorithms that are quality catalysts in the derivation and entropy spread
7
+ # of keys, identifiers and base64 character numbers.
8
+ class KeyAlgo
9
+
10
+
11
+ # Cherry pick a given number of characters from the character pool
12
+ # so that a good spread is achieved. This picker is the anti-pattern
13
+ # of just axing the first 5 characters from a 100 character string
14
+ # essentially wasting over 90% of the available entropy.
15
+ #
16
+ # This is the <b>algorithem to cherry pick</b> a spread of characters
17
+ # from the pool in the second parameter.
18
+ #
19
+ # - if the character pool length is a multiple of num_chars all is good otherwise
20
+ # - constrict to the <b>highest multiple of the pick size below</b> the pool length
21
+ # - divide that number by num_chars to get the first offset and character spacing
22
+ # - if spacing is 3, the first character is the 3rd, the second the 6th and so on
23
+ # - then return the cherry picked characters
24
+ #
25
+ # @param pick_size [FixNum] the number of characters to cherry pick
26
+ # @param char_pool [String] a pool of characters to cherry pick from
27
+ # @return [String]
28
+ # a string whose length is the one indicated by the first parameter
29
+ # and whose characters contain a predictable, repeatable spread from
30
+ # the character pool parameter
31
+ def self.cherry_picker( pick_size, char_pool )
32
+
33
+ hmb_limit = highest_multiple_below( pick_size, char_pool.length )
34
+ jump_size = hmb_limit / pick_size
35
+ read_point = jump_size
36
+ picked_chars = ""
37
+ loop do
38
+ picked_chars += char_pool[ read_point - 1 ]
39
+ read_point += jump_size
40
+ break if read_point > hmb_limit
41
+ end
42
+
43
+ err_msg = "Expected cherry pick size to be #{pick_size} but it was #{picked_chars.length}."
44
+ raise RuntimeError, err_msg unless picked_chars.length == pick_size
45
+
46
+ return picked_chars
47
+
48
+ end
49
+
50
+
51
+ # Affectionately known as <b>a hmb</b>, this method returns the
52
+ # <b>highest multiple</b> of the first parameter that is below
53
+ # <b>(either less than or equal to)</b> the second parameter.
54
+ #
55
+ # - -------- - ------- - ----------------- -
56
+ # | Small | Big | Highest Multiple |
57
+ # | Number | Number | Below Big Num |
58
+ # | -------- - ------- - ----------------- |
59
+ # | 5 | 25 | 25 |
60
+ # | 3 | 20 | 18 |
61
+ # | 8 | 63 | 56 |
62
+ # | 1 | 1 | 1 |
63
+ # | 26 | 28 | 26 |
64
+ # | 1 | 7 | 7 |
65
+ # | 16 | 16 | 16 |
66
+ # | -------- - ------- - ----------------- |
67
+ # | 10 | 8 | ERROR |
68
+ # | -4 | 17 | ERROR |
69
+ # | 4 | -17 | ERROR |
70
+ # | 0 | 32 | ERROR |
71
+ # | 29 | 0 | ERROR |
72
+ # | -4 | 0 | ERROR |
73
+ # | -------- - ------- - ----------------- |
74
+ # - -------- - ------- - ----------------- -
75
+ #
76
+ # Zeroes and negative numbers cannot be entertained, nor can the
77
+ # small number be larger than the big one.
78
+ #
79
+ # @param small_num [FixNum]
80
+ # the highest multiple of this number below the one in the
81
+ # next parameter is what will be returned.
82
+ #
83
+ # @param big_num [FixNum]
84
+ # returns either this number or the nearest below it that is
85
+ # a multiple of the number in the first parameter.
86
+ #
87
+ # @raise [ArgumentError]
88
+ # if the first parameter is greater than the second
89
+ # if either or both parameters are zero or negative
90
+ def self.highest_multiple_below small_num, big_num
91
+
92
+ arg_issue = (small_num > big_num) || small_num < 1 || big_num < 1
93
+ err_msg = "Invalid args #{small_num} and #{big_num} to HMB function."
94
+ raise ArgumentError, err_msg if arg_issue
95
+
96
+ for index in 0 .. ( big_num - 1 )
97
+ invex = big_num - index # an [invex] is an inverted index
98
+ return invex if invex % small_num == 0
99
+ end
100
+
101
+ raise ArgumentError, "Could not find a multiple of #{small_num} lower than #{big_num}"
102
+
103
+ end
104
+
105
+
106
+ end
107
+
108
+
109
+ end