opensecret 0.0.962 → 0.0.988

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -10
  3. data/bin/opensecret +3 -4
  4. data/bin/ops +5 -0
  5. data/lib/extension/string.rb +114 -0
  6. data/lib/factbase/facts.opensecret.io.ini +9 -21
  7. data/lib/interprete/begin.rb +232 -0
  8. data/lib/interprete/cmd.rb +621 -0
  9. data/lib/{plugins/usecases/unlock.rb → interprete/export.rb} +25 -70
  10. data/lib/interprete/init.rb +205 -0
  11. data/lib/interprete/key.rb +119 -0
  12. data/lib/interprete/open.rb +148 -0
  13. data/lib/{plugins/usecases → interprete}/put.rb +19 -6
  14. data/lib/{plugins/usecases → interprete}/safe.rb +2 -1
  15. data/lib/{plugins/usecases/lock.rb → interprete/seal.rb} +24 -34
  16. data/lib/interprete/set.rb +46 -0
  17. data/lib/interprete/use.rb +43 -0
  18. data/lib/interpreter.rb +165 -0
  19. data/lib/keytools/binary.map.rb +245 -0
  20. data/lib/keytools/digester.rb +245 -0
  21. data/lib/keytools/doc.conversion.to.ones.and.zeroes.ruby +179 -0
  22. data/lib/keytools/doc.rsa.radix.binary-mapping.ruby +190 -0
  23. data/lib/keytools/doc.star.schema.strategy.txt +77 -0
  24. data/lib/keytools/doc.using.pbkdf2.kdf.ruby +95 -0
  25. data/lib/keytools/doc.using.pbkdf2.pkcs.ruby +266 -0
  26. data/lib/keytools/kdf.bcrypt.rb +180 -0
  27. data/lib/keytools/kdf.pbkdf2.rb +164 -0
  28. data/lib/keytools/key.data.rb +227 -0
  29. data/lib/keytools/key.derivation.rb +341 -0
  30. data/lib/keytools/key.module.rb +140 -0
  31. data/lib/keytools/key.rb +481 -0
  32. data/lib/logging/gem.logging.rb +1 -2
  33. data/lib/modules/cryptology.md +43 -0
  34. data/lib/{plugins/ciphers → modules/cryptology}/aes-256.rb +6 -0
  35. data/lib/{crypto → modules/cryptology}/amalgam.rb +6 -0
  36. data/lib/modules/cryptology/blowfish.rb +130 -0
  37. data/lib/modules/cryptology/cipher.rb +207 -0
  38. data/lib/modules/cryptology/collect.rb +118 -0
  39. data/lib/{plugins → modules/cryptology}/crypt.io.rb +5 -0
  40. data/lib/{crypto → modules/cryptology}/engineer.rb +7 -1
  41. data/lib/{crypto → modules/cryptology}/open.bcrypt.rb +0 -0
  42. data/lib/modules/mappers/collateral.rb +282 -0
  43. data/lib/modules/mappers/dictionary.rb +288 -0
  44. data/lib/modules/mappers/envelope.rb +127 -0
  45. data/lib/modules/mappers/settings.rb +170 -0
  46. data/lib/modules/storage/coldstore.rb +186 -0
  47. data/lib/{opensecret/plugins.io/git/git.flow.rb → modules/storage/git.store.rb} +11 -0
  48. data/lib/notepad/scratch.pad.rb +17 -0
  49. data/lib/session/fact.finder.rb +13 -0
  50. data/lib/session/require.gem.rb +5 -0
  51. data/lib/store-commands.txt +180 -0
  52. data/lib/version.rb +1 -1
  53. data/opensecret.gemspec +5 -6
  54. metadata +74 -29
  55. data/lib/crypto/blowfish.rb +0 -85
  56. data/lib/crypto/collect.rb +0 -140
  57. data/lib/crypto/verify.rb +0 -33
  58. data/lib/opensecret.rb +0 -236
  59. data/lib/plugins/cipher.rb +0 -203
  60. data/lib/plugins/ciphers/blowfish.rb +0 -126
  61. data/lib/plugins/coldstore.rb +0 -181
  62. data/lib/plugins/envelope.rb +0 -116
  63. data/lib/plugins/secrets.uc.rb +0 -94
  64. data/lib/plugins/usecase.rb +0 -239
  65. data/lib/plugins/usecases/init.rb +0 -145
  66. data/lib/plugins/usecases/open.rb +0 -108
  67. data/lib/session/attributes.rb +0 -279
  68. data/lib/session/dictionary.rb +0 -191
  69. data/lib/session/file.path.rb +0 -53
  70. data/lib/session/session.rb +0 -80
@@ -1,239 +0,0 @@
1
- #!/usr/bin/ruby
2
- # coding: utf-8
3
-
4
- # opensession contains basic behaviour for managing a client only
5
- # (serverless) session. Configuration directives are read and written
6
- # from an INI off the home directory that is created when the session
7
- # is first initiated.
8
- #
9
- # The session is expected to be formally closed down and that is
10
- # reflected by explicitly deleting the configuration file. If this
11
- # "session over" command is not issued a reasonable time limit is
12
- # then invoked when the next session command is issued.
13
- #
14
- # This "session awakening" wipes the slate clean and starts afresh
15
- # with regard to the two dimensional array of configuration directive
16
- # pointers.
17
- module OpenSession
18
-
19
-
20
- # An opensession use case is designed to be extended and does preparatory
21
- # work to create favourable and useful conditions to make use cases readable,
22
- # less repetitive, simpler and concise.
23
- class UseCase
24
-
25
-
26
- # Execute the use cases's flow from beginning when
27
- # you validate the input and parameters through the
28
- # memorize, execute and the final cleanup.
29
- def flow_of_events
30
-
31
- check_pre_conditions
32
- pre_memorize
33
- execute
34
- post_memorize
35
- cleanup
36
- check_post_conditions
37
-
38
- end
39
-
40
-
41
-
42
- # Validate the input parameters and check that the current
43
- # state is perfect for executing the use case.
44
- #
45
- # If either of the above fail - the validation function should
46
- # set a human readable string and then throw an exception.
47
- def check_pre_conditions
48
-
49
-
50
- begin
51
-
52
- pre_validation
53
-
54
- rescue OpenError::CliError => e
55
-
56
- puts ""
57
- puts "Your command did not complete successfully."
58
- puts "Pre validation checks failed."
59
- puts ""
60
- puts " => #{e.message}"
61
- puts ""
62
- abort e.message
63
- end
64
-
65
-
66
- end
67
-
68
-
69
- # After the main flow of events certain state conditions
70
- # must hold true thus demonstrating that the observable
71
- # value has indeed ben delivered.
72
- #
73
- # Child classes should subclass this method and place any
74
- # post execution (post condition) checks in it and then
75
- # make a call to this method through the "super" keyword.
76
- def check_post_conditions
77
-
78
- begin
79
-
80
- post_validation
81
-
82
- rescue OpenError::CliError => e
83
-
84
- puts ""
85
- puts "Your command did not complete successfully."
86
- puts "Post validation checks failed."
87
- puts ""
88
- puts " => #{e.message}"
89
- #### puts " => #{e.culprit}"
90
- puts ""
91
- abort e.message
92
- end
93
-
94
- end
95
-
96
-
97
- # Child classes should subclass this method and place any
98
- # post execution (post condition) checks in it and then
99
- # make a call to this method through the "super" keyword if
100
- # this method gets any global behaviour in it worth calling.
101
- def post_validation
102
-
103
- end
104
-
105
-
106
-
107
- # (Pre) memorize adds to permanent storage a configuration
108
- # directive and its value <tt>provided by the user</tt>
109
- # primarily because it avoids repitition in subsequent
110
- # use case commands.
111
- def pre_memorize
112
-
113
- end
114
-
115
-
116
-
117
- # Execute the main flow of events of the use case. Any
118
- # exceptions thrown are captured and if the instance
119
- # variale [@human_readable_message] is set - tell the
120
- # user about it. Without any message - just tell the
121
- # user something went wrong and tell them where the logs
122
- # are that might carry more information.
123
- def execute
124
-
125
- end
126
-
127
-
128
-
129
- # (Post) memorize will add to permanent storage) any
130
- # key/values that have been derived or looked up during
131
- # use case execution. This allows subsequent use case
132
- # commands to
133
- #
134
- # - capitalize on
135
- # - take direction from
136
- # - and/or simply use
137
- #
138
- # the value in later use cases or processing.
139
- def post_memorize
140
-
141
- end
142
-
143
-
144
-
145
- # If the use case validation went well, the memorization
146
- # went well the
147
- def cleanup
148
-
149
- end
150
-
151
-
152
-
153
- # Resolve +two attached fact files+ with the first being general and
154
- # relevant to every use case in the parameter specified domain, and
155
- # the second being specific to this use case.
156
- #
157
- # The <b><em>general factfile</em></b> is expected to be on the class (load) path
158
- # and below are paths for a generic domain name and for an example domain
159
- # name of *openpost.io*
160
- #
161
- # - <tt>factbase/facts.<<domain>>.ini</tt>
162
- # - <tt>factbase/facts.openpost.io.ini</tt>
163
- #
164
- # The <b><em>use case specific factfile</em></b> is also _expected_ to be on the class
165
- # (load) path and below is a generic and a use case specific path using
166
- # the example <tt>deliver</tt> use case.
167
- #
168
- # - <tt>factbase/facts.<<uc-name>>.usecase.ini</tt>
169
- # - <tt>factbase/facts.deliver.usecase.ini</tt>
170
- #
171
- # The domain name is delivered in the parameter whilst the use case
172
- # name is derived from the (extension) class name.
173
- #
174
- # @param fact_domain [String] domain of the general attached factfile
175
- # @return [Hash] a 2d (two-dimensional) hash of keys and their corresponding values
176
- def attached_facts fact_domain
177
-
178
- end
179
-
180
-
181
-
182
-
183
- ### def path_to_resources
184
- ### File.join(File.dirname(File.expand_path(__FILE__)), '../path/to/resources')
185
- ### end
186
-
187
- # This use case is initialized primary by resolving the configured
188
- # +general and use case specific facts+. To access the general facts,
189
- # a domain name is expected in the parameter delegated by the extension
190
- # use case classes.
191
- def initialize
192
-
193
-
194
- class_name = self.class.name.downcase.split(":").last
195
- is_pre_init_usecase = [ "safe", "store", "email" ].include? class_name
196
- return if is_pre_init_usecase
197
-
198
- @ucid_str = self.class.name.do_flatten
199
- log.info(x) { "Usecase class [self.class.name] converted to => #{@ucid_str}" }
200
- @ucid_sym = @ucid_str.gsub(".", "_").to_sym
201
-
202
- OpenSession::FactFind.instance.instantiate @ucid_str
203
- OpenSession::FactFind.instance.assimilate "facts.opensecret.io.ini"
204
-
205
- @c = OpenSession::FactFind.instance.f
206
- @i = OpenSession::FactFind.instance.i
207
- @p = OpenSession::FactFind.instance.f[@ucid_sym]
208
-
209
- log.info(x) { "assimilated [#{@p.length}] facts specific to the [#{@ucid_str}] use case." }
210
-
211
- ############ @time_stamp = OpenSession::Stamp.instance
212
-
213
- =begin
214
- @eco_id_str = SnapFlat.do self.class.name
215
- @eco_id_sym = @eco_id_str.gsub(".", "_").to_sym
216
- @plugin_path = plugin_src_dir
217
-
218
- FactTree.instance.instantiate @eco_id_str, @plugin_path
219
- FactTree.instance.assimilate_instance_facts
220
-
221
- instantiate_runtime FactTree.instance.f
222
-
223
- FactTree.instance.identify_my_workstation
224
- FactTree.instance.assimilate_station_facts
225
- FactTree.instance.assimilate_plugin_facts
226
- FactTree.instance.assimilate_general_facts
227
-
228
- @c = FactTree.instance.f
229
- @i = FactTree.instance.i
230
- @p = FactTree.instance.f[@eco_id_sym]
231
- =end
232
-
233
- end
234
-
235
-
236
- end
237
-
238
-
239
- end
@@ -1,145 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- module OpenSecret
4
-
5
- require 'openssl'
6
-
7
- # The <b>init use case</b> initializes opensecret thus preparing it
8
- # for the ability to lock secrets, unlock them, transport their keys and
9
- # much more.
10
- #
11
- # Like all use cases, +init+ validates to ensure that the pre-conditions
12
- # have been met and then proceeds to execute its core offering and deliver
13
- # observable value.
14
- #
15
- # == Observable Value
16
- #
17
- # The observable value from the <b>init use case</b> init boils down to
18
- #
19
- # - the public key and <b>8192 bit encrypted private key</b> in the safe
20
- # - the <b>encrypted workstation key</b> in the user's configuration file
21
- # - the <b>encrypted public key signature</b> in the user's configuration file
22
- # - a robust password (for unlocking secrets) +stashed in a human brain+
23
- # - successful test of the open, put, list, lock, read and tell use cases
24
- #
25
- # No cloud or other external access occurs as per the opensecret policy.
26
- #
27
- # == Thwart Public Key Switch Attacks
28
- #
29
- # A <b><em>public key switch attack</em></b> tries to access <b>future secrets</b>
30
- # (not the ones already encrypted) via unwitting encryption using a public key
31
- # the attacker controls.
32
- #
33
- # <b>opensecret</b> thwarts this by continual verification against an
34
- # encrypted <em>public key signature</em> aboard the workstation.
35
- class Init < SecretsUseCase
36
-
37
- attr_writer :safe_path, :email_addr, :store_url
38
- @@context_name = "opensecret"
39
-
40
-
41
- # The init use case prepares <b>opensecret</b> so that you can <b>open</b> a packet,
42
- # <b>put</b> secrets into it and then <b>lock</b> it, effectively writing the crypt
43
- # material into the backend store.
44
- #
45
- # <b>Main Flow of Events</b>
46
- #
47
- # So to prepare for the <b><em>modus operandi</em></b> that encrypts, decrypts and if
48
- # required transports secrets, we
49
- #
50
- # - collect the human password (twice) and verify its robustness
51
- # - manufacture workstation key that will be encrypted b4 it rests on machine
52
- # - create amalgamated human/workstation password for locking the private key
53
- # - create a long cryptographically strong symmetric encryption key
54
- # - encrypt workstation key and put crypt into the opensecret configuration file
55
- # - create a super sized 8192 bit private key (and its asymmetric public key)
56
- # - write the AES 256bit encrypted private key into safe-store's master keys
57
- # - create a text bundle for signing composed of the keys, email and date/time
58
- # - sign the bundle and save the signature in the master keys store
59
- # - put the public key in the configuration file (off the homedirectory)
60
- # - test the core open, put, list, lock, read and tell use case commands
61
- #
62
- # <b>Observable Value</b>
63
- #
64
- # The <tt>init use case</tt> observable value post-conditions are
65
- #
66
- # - the <b>8192 bit encrypted private key</b> in the master keys safe
67
- # - the <b>public key</b>, time stamp and encrypted workstation key in config
68
- # - the <b>encrypted workstation key</b> in the user's configuration file
69
- # - the <b>asymmetric keys, time stamp and email</b> signature in master keys safe
70
- # - a robust password (for unlocking secrets) +stashed in a human brain+
71
- def execute
72
-
73
- human_password = Collect.secret_text(
74
- @c[:global][:min_passwd_len],
75
- true,
76
- @c[:global][:prompt_1],
77
- @c[:global][:prompt_2]
78
- )
79
-
80
- machine_key = Engineer.machine_key human_password.length, @c[:global][:ratio]
81
- amalgam_key = Amalgam.passwords human_password, machine_key, @c[:global][:ratio]
82
- asymmetric_keys = OpenSSL::PKey::RSA.new @c[:global][:bit_key_size]
83
- secured_keytext = asymmetric_keys.export @c[:global][:key_cipher], amalgam_key
84
-
85
- crypt_key_segments = [ human_password, @c[:global][:separator_a], @email_addr, @c[:global][:separator_a], @c[:global][:stamp_23] ]
86
-
87
- machine_key_crypt_key = crypt_key_segments.alphanumeric_union.concat_length
88
- machine_key_x = Base64.urlsafe_encode64(
89
- Blowfish.new.encryptor(machine_key, machine_key_crypt_key)
90
- )
91
-
92
- OpenSession::Attributes.stash @c[:global][:name], @c[:global][:name], @c[:global][:machine_key_x], machine_key_x
93
- OpenSession::Attributes.stash @c[:global][:name], @c[:global][:name], @c[:global][:stamp_key], @c[:global][:stamp_23]
94
-
95
-
96
- ## Change and write the public key to own file (see paper notes for naming direction)
97
- ## Change and write the public key to own file (see paper notes for naming direction)
98
- ## Change and write the public key to own file (see paper notes for naming direction)
99
- public_key_64 = Base64.urlsafe_encode64 asymmetric_keys.public_key.to_pem
100
- OpenSession::Attributes.stash @c[:global][:name], @c[:global][:name], @c[:global][:publickey_id], public_key_64
101
-
102
- ## not needed - produce public key from private key then validate with key in configuration.
103
- ## not needed - produce public key from private key then validate with key in configuration.
104
- ## not needed - produce public key from private key then validate with key in configuration.
105
- to_sign_segments = [ secured_keytext, public_key_64, @email_addr, @c[:global][:stamp_23] ]
106
- to_sign_packet = to_sign_segments.alphanumeric_union.concat_length
107
- signature_string = Base64.urlsafe_encode64( asymmetric_keys.sign( OpenSSL::Digest::SHA256.new, to_sign_packet ) )
108
-
109
- FileUtils.mkdir_p @c[:global][:master_dirpath]
110
- File.write @c[:global][:master_prv_key], secured_keytext
111
- File.write @c[:global][:master_sig_path], signature_string
112
-
113
- end
114
-
115
-
116
- # Perform pre-conditional validations in preparation to executing the main flow
117
- # of events for this use case. This method may throw the below exceptions.
118
- #
119
- # @raise [SafeDirNotConfigured] if the safe's url has not been configured
120
- # @raise [EmailAddrNotConfigured] if the email address has not been configured
121
- # @raise [StoreUrlNotConfigured] if the crypt store url is not configured
122
- def pre_validation
123
-
124
- @safe_path = OpenSession::Attributes.instance.get_value @@context_name, @@context_name, "safe"
125
- safe_configured = File.exists?( @safe_path ) && File.directory?( @safe_path )
126
- @err_msg = "[safe] storage not yet configured. Try =>] opensecret safe /folder/path"
127
- raise SafeDirNotConfigured.new @err_msg, @safe_path unless safe_configured
128
-
129
- @email_addr = OpenSession::Attributes.instance.get_value @@context_name, @@context_name, "email"
130
- email_configured = !@email_addr.nil? && !@email_addr.empty? && @email_addr.length > 4
131
- @err_msg = "viable [email address] not configured. Try =>] opensecret email joe@example.com"
132
- raise EmailAddrNotConfigured.new @err_msg, @email_addr unless email_configured
133
-
134
- @store_url = OpenSession::Attributes.instance.get_value @@context_name, @@context_name, "store"
135
- store_configured = !@store_url.nil? && !@store_url.empty? && @store_url.length > 0
136
- @err_msg = "crypt [store url] not configured. Try =>] opensecret store /path/to/crypt"
137
- raise StoreUrlNotConfigured.new @err_msg, @store_url unless store_configured
138
-
139
- end
140
-
141
-
142
- end
143
-
144
-
145
- end
@@ -1,108 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- module OpenSecret
4
-
5
- require 'openssl'
6
-
7
- # The <tt>open use case</tt> allows us to add (put), subtract (del)ete and list
8
- # the secrets in a file (whether it exists or not). The file can then be locked.
9
- # Lookout for the reopen command.
10
- #
11
- # If the file to open already exists a --with option (giving the master-secret)
12
- # must be provided.
13
- #
14
- # == Observable Value
15
- #
16
- # $ opensecret open home/wifi
17
- #
18
- # The observable value delivered by +[open]+ boils down to
19
- #
20
- # - an openkey (eg asdfx1234) and corresponding open encryption key
21
- # - open encryption key written to <tt>~/.opensecret/open.keys/asdfx1234.x.txt</tt>
22
- # - the opened path (ending in filename) written to session.cache base in [safe]
23
- # - the INI string (were the file to be decrypted) would look like the below
24
- #
25
- # [session]
26
- # base.path = home/wifi
27
- #
28
- class Open < SecretsUseCase
29
-
30
- attr_writer :outer_path
31
- @@context_name = "opensecret"
32
-
33
- # Execute the <tt>open use case</tt> activities which precedes the ability to
34
- # to add (put), subtract (del)ete and list the secrets into the opened session file.
35
- # The file can then be locked (committed and pushed to permanent crypted stores).
36
- #
37
- # If the file to open already exists a --with option (giving the master-secret)
38
- # must be provided.
39
- #
40
- # <b>Observable Value [Open Use Case]</b>
41
- #
42
- # $ opensecret open home/wifi
43
- #
44
- # The observable value delivered by +[open]+ boils down to
45
- #
46
- # - a provisioned openkey (eg asdfx1234) and corresponding open encryption key
47
- # - open encryption key written to <tt>~/.opensecret/open.keys/asdfx1234.x.txt</tt>
48
- # - the opened path (ending in filename) written to session.cache base in [safe]
49
- # - the INI string (were the file to be decrypted) would look like the below
50
- #
51
- # [session]
52
- # session.key = EQFe4TKMWyrlyD59NRWWJYVue8xsTnKAnuXtsZ6NRoVXMeqFRj
53
- # session.path = home/wifi.1vz16m5Zl47w.x.os.txt
54
- #
55
- # @example
56
- # home/wifi can be simply populated like this.
57
- #
58
- # $ opensecret put bt/ssid g034gdf3455
59
- # $ opensecret put bt/password HRAsyf324g4DF
60
- #
61
- # $ opensecret put virgin.media/ssid 345SDFS
62
- # $ opensecret put virgin.media/password HlksHRd043NjPO
63
- #
64
- # $ opensecret file virgin.media/contract /home/joe/downloads/vm.contract.pdf
65
- #
66
- # To encrypt (lock-down) these secrets we simply issue
67
- #
68
- # $ opensecret close
69
- #
70
- def execute
71
-
72
- last_fwdslash_index = @outer_path.rindex "/"
73
- folder_path = @outer_path[0 .. last_fwdslash_index]
74
- file_word = @outer_path[last_fwdslash_index .. -1]
75
-
76
- session_folder_path = File.join @p[:open_dirpath], folder_path
77
-
78
- FileUtils.mkdir_p session_folder_path
79
- open_id = Engineer.strong_key @p[:open_idlen]
80
- open_key = Engineer.strong_key @p[:open_keylen]
81
-
82
- file_name = file_word + ".#{open_id}.os.txt"
83
- ####################### file_path = File.join session_folder_path, file_name
84
- file_key = File.join folder_path, file_name
85
-
86
- OpenSession::Attributes.stash @@context_name, @p[:open_name], @p[:open_idname], open_id
87
- OpenSession::Attributes.stash @@context_name, @p[:open_name], @p[:open_keyname], open_key
88
- OpenSession::Attributes.stash @@context_name, @p[:open_name], @p[:open_pathname], file_key
89
-
90
- end
91
-
92
-
93
- # Perform pre-conditional validations in preparation to executing the main flow
94
- # of events for this use case. This method may throw the below exceptions.
95
- #
96
- # @raise [SafeDirNotConfigured] if the safe's url has not been configured
97
- # @raise [EmailAddrNotConfigured] if the email address has not been configured
98
- # @raise [StoreUrlNotConfigured] if the crypt store url is not configured
99
- def pre_validation
100
-
101
-
102
- end
103
-
104
-
105
- end
106
-
107
-
108
- end