opensecret 0.0.962 → 0.0.988

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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