opensecret 0.0.988 → 0.0.9925

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 (62) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +56 -159
  3. data/bin/opensecret +2 -2
  4. data/bin/ops +17 -2
  5. data/lib/extension/string.rb +14 -16
  6. data/lib/{interpreter.rb → interprete.rb} +53 -29
  7. data/lib/keytools/binary.map.rb +49 -0
  8. data/lib/keytools/kdf.api.rb +249 -0
  9. data/lib/keytools/kdf.bcrypt.rb +64 -29
  10. data/lib/keytools/kdf.pbkdf2.rb +92 -83
  11. data/lib/keytools/kdf.scrypt.rb +190 -0
  12. data/lib/keytools/key.64.rb +326 -0
  13. data/lib/keytools/key.algo.rb +109 -0
  14. data/lib/keytools/key.api.rb +1281 -0
  15. data/lib/keytools/key.db.rb +265 -0
  16. data/lib/keytools/{key.module.rb → key.docs.rb} +55 -0
  17. data/lib/keytools/key.error.rb +110 -0
  18. data/lib/keytools/key.id.rb +271 -0
  19. data/lib/keytools/key.iv.rb +107 -0
  20. data/lib/keytools/key.local.rb +265 -0
  21. data/lib/keytools/key.mach.rb +248 -0
  22. data/lib/keytools/key.now.rb +402 -0
  23. data/lib/keytools/key.pair.rb +259 -0
  24. data/lib/keytools/key.pass.rb +120 -0
  25. data/lib/keytools/key.rb +428 -298
  26. data/lib/keytools/keydebug.txt +295 -0
  27. data/lib/logging/gem.logging.rb +3 -3
  28. data/lib/modules/cryptology/collect.rb +20 -0
  29. data/lib/session/require.gem.rb +1 -1
  30. data/lib/usecase/cmd.rb +417 -0
  31. data/lib/usecase/id.rb +36 -0
  32. data/lib/usecase/import.rb +174 -0
  33. data/lib/usecase/init.rb +78 -0
  34. data/lib/usecase/login.rb +70 -0
  35. data/lib/usecase/logout.rb +30 -0
  36. data/lib/usecase/open.rb +126 -0
  37. data/lib/{interprete → usecase}/put.rb +100 -47
  38. data/lib/usecase/read.rb +89 -0
  39. data/lib/{interprete → usecase}/safe.rb +0 -0
  40. data/lib/{interprete → usecase}/set.rb +0 -0
  41. data/lib/usecase/token.rb +111 -0
  42. data/lib/{interprete → usecase}/use.rb +0 -0
  43. data/lib/version.rb +1 -1
  44. data/opensecret.gemspec +4 -3
  45. metadata +39 -33
  46. data/lib/exception/cli.error.rb +0 -53
  47. data/lib/exception/errors/cli.errors.rb +0 -31
  48. data/lib/interprete/begin.rb +0 -232
  49. data/lib/interprete/cmd.rb +0 -621
  50. data/lib/interprete/export.rb +0 -163
  51. data/lib/interprete/init.rb +0 -205
  52. data/lib/interprete/key.rb +0 -119
  53. data/lib/interprete/open.rb +0 -148
  54. data/lib/interprete/seal.rb +0 -129
  55. data/lib/keytools/digester.rb +0 -245
  56. data/lib/keytools/key.data.rb +0 -227
  57. data/lib/keytools/key.derivation.rb +0 -341
  58. data/lib/modules/mappers/collateral.rb +0 -282
  59. data/lib/modules/mappers/envelope.rb +0 -127
  60. data/lib/modules/mappers/settings.rb +0 -170
  61. data/lib/notepad/scratch.pad.rb +0 -224
  62. data/lib/store-commands.txt +0 -180
@@ -1,163 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- module OpenSecret
4
-
5
- require 'openssl'
6
-
7
- # The <tt>export use case</tt> moves doubly encrypted material <b>from the frozen</b>
8
- # (key and crypt) stores, <b>into an (encrypted) session envelope</b>.
9
- #
10
- # Material within the auspices of the session envelope can be manipulated by commands
11
- # like {OpenSecret::Put} and remove and also read by commands like peep, look and update.
12
- #
13
- # <b>Export | Pre-Conditions</b>
14
- #
15
- # To deliver on its core promise of moving the encrypted (key and crypt) stores
16
- # to an encrypted session envelope, <b>export</b> expects
17
- #
18
- # - the local key and crypt stores to be pulled (refreshed) from remote
19
- # - the destination session path to either be empty (or)
20
- # - a populated session path containing equivalent data (ie cannot be overwritten)
21
- # - both the human (agent) password and workstation key to be correct
22
- #
23
- # <b>Export | Alternate Flows</b>
24
- #
25
- # This use case requires the human (agent) password unless the <tt>--no-human-password</tt>
26
- # flag was posted along with the <tt>init</tt> command. In this instance an agent password
27
- # will have been generated and encrypted with the user's home tree.
28
- #
29
- # <b>Export | Observable Value</b>
30
- #
31
- # The observable value proffered by export is
32
- #
33
- # - validating the existence of the requested secret path
34
- # - validation of the human password and workstation key
35
- # - the keys and crypt at the paths are decrypted
36
- # - the session envelope is stuffed with the crypted material
37
- # - an encrypted session envelope (post-stuffing)
38
- #
39
- # @example
40
- #
41
- # These use case steps are implemented and ready to go.
42
- #
43
- # $ opensecret open geo/countries
44
- # $ opensecret put uganda/capital kampala
45
- # $ opensecret put kenya/capital nairobi
46
- # $ opensecret put france/capital paris
47
- # $ opensecret put france/population 23000000
48
- # $ opensecret lock
49
- # $ opensecret export geo/countries --with=asdfasdf
50
- #
51
- # Below are future examples with use cases like list and print
52
- # which curently have not been implemented.
53
- #
54
- # $ opensecret init bobby@example.com --with="hUM4n-0pen$3cr3t"
55
- #
56
- # $ opensecret open my/gadgets
57
- #
58
- # $ opensecret put laptop/login/username bob
59
- # $ opensecret put laptop/login/password bob$_p455w0rd
60
- # $ opensecret put iphone/pin 8529
61
- #
62
- # $ opensecret lock
63
- # $ opensecret list
64
- #
65
- # $ opensecret export my/gadgets --with="hUM4n-0pen$3cr3t"
66
- # $ opensecret print
67
- #
68
- # $ opensecret put wifi/ssid Virgin-HGPAS
69
- # $ opensecret put wifi/password SDBLJHGPASDFA1234ZNF
70
- #
71
- # $ opensecret print
72
- # $ opensecret lock
73
- #
74
- class Export < Command
75
-
76
- attr_writer :outer_path, :master_p4ss
77
-
78
-
79
- # The <tt>lock use case</tt> is called after {OpenSecret::Open} and {OpenSecret::Put}
80
- # and its effect is to dispatch the doubly encrypted materrial to the configured storage
81
- # platform, be it Git, S3, SSH or just an accessible file-system.
82
- #
83
- # <b>Main Flow of Events</b>
84
- #
85
- # To seal the envelope built up by put, file and add amongst others requires
86
- # that we
87
- #
88
- # - get the encrypted envelope
89
- # - create a strong asymmetric key
90
- # - lock the envelope using opensecret's double encrypt modus operandi
91
- # - place the doubly encrypted result into the crypt store
92
- # - lock the asymmetric key again with opensecret's double encrypt modus operandi
93
- # - place the doubly encrypted result into the key store
94
- #
95
- # The second double lock of the crypted envelope is done with the public key
96
- # aspect of an asymmetric key created here.
97
- #
98
- # The second double lock of the crypted private key (created here) is done with
99
- # the master public key created in the {Init.execute} use case main flow.
100
- #
101
- # <b>Lock | Observable Value</b>
102
- #
103
- # The observable value after the lock use case has completed entails
104
- #
105
- # - a doubly encrypted data envelope placed in the backend store
106
- # - a doubly encrypted private key placed in the frontend store
107
- # - both stores sync'd with off-machine Git (S3, ...) mirrors
108
- # - deletion of the (encrypted) envelope {Open}ed and stuffed with {Put}
109
- # - deletion of {Open}ed session data to locate and decrypt envelope
110
- def execute
111
-
112
- instantiate_collateral
113
-
114
- keys_store = Store::ColdStore.new( @collateral.frontend_keystore_path )
115
- main_store = Store::ColdStore.new( @collateral.backend_cryptstore_path )
116
-
117
- keys_crypt = keys_store.read @outer_path
118
- main_crypt = main_store.read @outer_path
119
-
120
- unless @master_p4ss
121
- @master_p4ss = ToolBelt::Collect.secret_text(
122
- @c[:global][:min_passwd_len],
123
- false,
124
- "Enter Master Password "
125
- )
126
- end
127
-
128
- workstation_rawkey = Mapper::Settings.read @collateral.domain_name, @c[:global][:machine_key_id]
129
- original_timestamp = Mapper::Settings.read @collateral.domain_name, @c[:global][:time_stamp_id]
130
- workstation_cipher = Base64.urlsafe_decode64( workstation_rawkey )
131
- crypt_key_segments = [ @master_p4ss, @c[:global][:separator_a], original_timestamp ]
132
- workstation_lock_x = crypt_key_segments.alphanumeric_union.concat_length
133
-
134
- workstation_string = ToolBelt::Blowfish.decryptor workstation_cipher, workstation_lock_x
135
- private_key_lock_x = ToolBelt::Amalgam.passwords @master_p4ss, workstation_string, @c[:global][:ratio]
136
- private_key_cipher = @collateral.read_private_key
137
- private_key_object = unlock_private_key( private_key_cipher, private_key_lock_x )
138
-
139
- string_private_key = ToolBelt::Cipher.decrypt_it( private_key_object, keys_crypt )
140
- plain_message_text = ToolBelt::Cipher.decrypt_it( to_private_key(string_private_key), main_crypt )
141
-
142
- puts
143
- puts JSON.pretty_generate( JSON.parse( plain_message_text ) )
144
- puts
145
-
146
- end
147
-
148
-
149
- # Perform pre-conditional validations in preparation to executing the main flow
150
- # of events for this use case. This method may throw the below exceptions.
151
- #
152
- # @raise [SafeDirNotConfigured] if the safe's url has not been configured
153
- # @raise [EmailAddrNotConfigured] if the email address has not been configured
154
- # @raise [StoreUrlNotConfigured] if the crypt store url is not configured
155
- def pre_validation
156
-
157
- end
158
-
159
-
160
- end
161
-
162
-
163
- end
@@ -1,205 +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
- # == RAGE | Resource Allocation Geography
16
- #
17
- # Resources are situated in a manner that delivers the maximum possible
18
- # security, with as much usability and simplicity that can be accomodated
19
- # and all the while ensuring the owner retains access to the secrets in
20
- # the face of multiple disasters befalling the environment.
21
- #
22
- # The session concept married with public/private key cryptology are the
23
- # main vehicles for delivering both simplicity and security. A system that
24
- # enables one to lock away secrets without exposing the master password
25
- # is more secure than those that don't.
26
- #
27
- #
28
- # == Frontend Store | USB Connected Device ( eg Keys, Phones )
29
- #
30
- # The frontend store (usually on a USB or other external but filesystem accessible
31
- # drive) contains the
32
- #
33
- # - encrypted private key | created by {Init}, updated by {ReKey}, read by {Open} {Export}
34
- # - public key | created by {Init}, updated by {ReKey}, read by {Seal} {Post} {Open}
35
- # - encrypted open envelopes tree | created/read/updated by {Put} {Add}, deleted by {Discard}
36
- # - encrypted libary keys tree | created by {Seal}, updated by {ReKey}, read by {Open} {Export}
37
- #
38
- #
39
- # == Workstation Configuration File
40
- #
41
- # The global configuration filepath is <tt>~/.opensecret.io/opensecret.io.configuration.ini</tt>
42
- #
43
- # The global configuration file is managed through the {OpenSecret::Mapper::Settings} and
44
- # the {OpenSecret::Mapper::Collateral.config_file} classes and points to the
45
- #
46
- # - current domain | created/updated by {Init}, updated by {Set}, read by most
47
- # - domain frontend path | created by {Init}, updated by {Set} and read by most
48
- # - domain store id | created/updated by {Set}, read by {Post}
49
- # - the domain's initialization time stamp | created by {Init}, read by {Seal}
50
- # - the encrypted machine (workstation) key | created by {Init}, read by {Seal}
51
- #
52
- # As well as the global config file, the workstation store contains the logs and most
53
- # importantly the mirrored departures/arrival lounge.
54
- #
55
- #
56
- # == Workstation Departure/Arrival Lounge
57
- #
58
- # The departures and arrivals lounge holds sealed envelopes that are either
59
- #
60
- # - waiting to (depart) be posted to the remote mirror
61
- # - waiting to be read/updated after (arrival) from the remote mirror
62
- # - posing as the remote mirror whilst no backend store exists
63
- #
64
- # The contents of the backend mirror (aka departure/arrival lounge) are
65
- #
66
- # - created by {Seal} and two-way {Post}
67
- # - read by {Open}
68
- # - deleted by {Delete}
69
- #
70
- #
71
- # == Workstation | Share and Transfers Lounge
72
- #
73
- # The self-evident power of opensecret blooms when you share secrets with others in
74
- # and out of a domain. The simplest application is when two users belong to the same
75
- # domain - the only thing they actually share is the remote back-end store and their
76
- # public keys. The lounge tree contains
77
- #
78
- # - key envelopes for ownership transfer
79
- # - key envelopes for sharing
80
- # - key envelopes for telling (sender never actual owns the sealed envelope)
81
- #
82
- #
83
- # == Observable Value
84
- #
85
- # The observable value from the <b>init use case</b> init boils down to
86
- #
87
- # - the public key and <b>8192 bit encrypted private key</b> in the safe
88
- # - the <b>encrypted workstation key</b> in the user's configuration file
89
- # - the <b>encrypted public key signature</b> in the user's configuration file
90
- # - a robust password (for unlocking secrets) +stashed in a human brain+
91
- # - successful test of the open, put, list, lock, read and tell use cases
92
- #
93
- # No cloud or other external access occurs as per the opensecret policy.
94
- #
95
- # == Thwart Public Key Switch Attacks
96
- #
97
- # A <b><em>public key switch attack</em></b> tries to access <b>future secrets</b>
98
- # (not the ones already encrypted) via unwitting encryption using a public key
99
- # the attacker controls.
100
- #
101
- # <b>opensecret</b> thwarts this by continual verification against an
102
- # encrypted <em>public key signature</em> aboard the workstation.
103
- class Init < Command
104
-
105
- attr_writer :master_p4ss, :domain_name, :base_path
106
-
107
-
108
- # The init use case prepares <b>opensecret</b> so that you can <b>open</b> a packet,
109
- # <b>put</b> secrets into it and then <b>lock</b> it, effectively writing the crypt
110
- # material into the backend store.
111
- #
112
- # <b>Main Flow of Events</b>
113
- #
114
- # So to prepare for the <b><em>modus operandi</em></b> that encrypts, decrypts and if
115
- # required transports secrets, we
116
- #
117
- # - if the base path exists, look for base.opensecret.io below, in and above the path
118
- # - if found we configure the config path as appropriate
119
- #
120
- #
121
- #
122
- # - collect the human password (twice) and verify its robustness
123
- # - manufacture workstation key that will be encrypted b4 it rests on machine
124
- # - create amalgamated human/workstation password for locking the private key
125
- # - create a long cryptographically strong symmetric encryption key
126
- # - encrypt workstation key and put crypt into the opensecret configuration file
127
- # - create a super sized 8192 bit private key (and its asymmetric public key)
128
- # - write the AES 256bit encrypted private key into safe-store's master keys
129
- # - create a text bundle for signing composed of the keys, email and date/time
130
- # - sign the bundle and save the signature in the master keys store
131
- # - put the public key in the configuration file (off the homedirectory)
132
- # - test the core open, put, list, lock, read and tell use case commands
133
- #
134
- # <b>Observable (Configuration) Value</b>
135
- #
136
- # The <tt>init use case</tt> observable value post-conditions are
137
- #
138
- # - the domain_name (group) and domain_path (key) exist in configuration file
139
- # - a directory called <tt>ops.<domain_name></tt> exists at/below or above domain_path
140
- #
141
- #
142
- # - the <b>8192 bit encrypted private key</b> in the master keys safe
143
- # - the <b>public key</b>, time stamp and encrypted workstation key in config
144
- # - the <b>encrypted workstation key</b> in the user's configuration file
145
- # - the <b>asymmetric keys, time stamp and email</b> signature in master keys safe
146
- # - a robust password (for unlocking secrets) +stashed in a human brain+
147
- #
148
- # <b>Alternate Flows</b>
149
- #
150
- # - if the base path exists, look for base.opensecret.io below, in and above the path
151
- # - two or more different domains under the same base is fine however there is a catch
152
- # - domain names cannot be duplicated (even if a different base path is given)
153
- # - domain duplication is disallowed as domains are group keys in the config file
154
- #
155
- # <b>Error Flows</b>
156
- #
157
- # An error will be thrown
158
- #
159
- # - if ops can't create or extend the base directory
160
- # - if the domain is already in the configuration file
161
- # - if domain has non alphanums, excl hyphens, underscores, @ symbols, periods
162
- # - if domain does not begin or end with alphanums.
163
- # - if non alpha-nums (excl at signs) appear consecutively
164
- # - if no alpha-nums appear in the string
165
- # - if the domain string's length is less than 5
166
- # - if "base.opensecret.io" appears twice (or more) in a directory tree
167
- #
168
- def execute
169
-
170
- return unless ops_key_exists?
171
-
172
- Mapper::Settings.stash @c[:global][:domain_now_id], @domain_name
173
- Mapper::Settings.write @domain_name, @c[:global][:front_path_id], @base_path
174
-
175
- instantiate_collateral
176
- unless @master_p4ss
177
- @master_p4ss = ToolBelt::Collect.secret_text(
178
- @c[:global][:min_passwd_len],
179
- true,
180
- @c[:global][:prompt_1],
181
- @c[:global][:prompt_2]
182
- )
183
- end
184
-
185
- locking_key = create_crypt_store_locking_key
186
-
187
- asymmetric_keys = OpenSSL::PKey::RSA.new @c[:global][:bit_key_size]
188
- secured_keytext = asymmetric_keys.export @c[:global][:key_cipher], locking_key
189
- @collateral.write_public_key asymmetric_keys.public_key.to_pem
190
- @collateral.write_private_key secured_keytext
191
-
192
- print_success_initializing
193
-
194
- end
195
-
196
-
197
- def pre_validation
198
-
199
- end
200
-
201
-
202
- end
203
-
204
-
205
- end
@@ -1,119 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- module OpenSecret
4
-
5
- # The <tt>key use case</tt> prints out an encrypted session key tied
6
- # to the workstation and shell environment. It should be called like this
7
- # and <tt>printenv</tt> can be used to verify that a shell-scoped
8
- # environment variable tying OPS_KEY to an (approximately) 48 character
9
- # session password, has been created.
10
- #
11
- # export OPS_KEY=`ops key`
12
- # printenv
13
- #
14
- # Note the <b>back-ticks</b> surrounding the <tt>ops key</tt> call.
15
- #
16
- # == Algorithm or Creating the Key
17
- #
18
- # An (approximately) 48 character key is acquired and then the four
19
- # data points below are used to symmetrically encrypt it.
20
- #
21
- # - <b>the parent shell's ID</b>
22
- # - <em>the first MAC address</em>
23
- # - <b>the machine's hostname</b>
24
- # - <em>the current timestamp</em>
25
- #
26
- # The result is Base64 encoded in url safe mode and printed to standard
27
- # out <b>without a trailing newline</b>.
28
- #
29
- # == Removing Equals from Key
30
- #
31
- # An environment variable holds the key's value and the <b>equals sign</b>
32
- # is not allowed within environment variables (in some operating systems)
33
- # mainly due to the fact that it is used as the key/value separator.
34
- #
35
- # The url safe base64 coding may produce one, two or three equal signs in
36
- # a bid to pad the string into a multiple of 4 length.
37
- #
38
- # Thus, we replace the equals signs with the @ symbol when encoding and
39
- # vice versa when decoding.
40
- #
41
- # For added security the key should auto time (or be zeroed) out.
42
- class Key < Command
43
-
44
-
45
- # The <tt>key use case</tt> prints out an encrypted session key tied
46
- # to the workstation and shell environment. It should be called like this
47
- # and <tt>printenv</tt> can be used to verify that a shell-scoped
48
- # environment variable tying OPS_KEY to an (approximately) 48 character
49
- # session password, has been created.
50
- #
51
- # export OPS_KEY=`ops key`
52
- # printenv
53
- #
54
- # Note the <b>back-ticks</b> surrounding the <tt>ops key</tt> call.
55
- #
56
- # <b>The 3 Session Keys</b>
57
- #
58
- # Three keys are involved here.
59
- #
60
- # - the 48 character random session key
61
- # - the encryption key which is an amalgam
62
- # - the base64 encoded key cipher text
63
- #
64
- #
65
- # == Removing Equals from Key
66
- #
67
- # An environment variable holds the key's value and the <b>equals sign</b>
68
- # is not allowed within environment variables (in some operating systems)
69
- # mainly due to the fact that it is used as the key/value separator.
70
- #
71
- # The url safe base64 coding may produce one, two or three equal signs in
72
- # a bid to pad the string into a multiple of 4 length.
73
- #
74
- # Thus, we replace the equals signs with the @ symbol when encoding and
75
- # vice versa when decoding.
76
- #
77
- # @example
78
- #
79
- # Session Key => QE6tlTt1fgwvKCYj9aG1K3cwks0EBMy9RgPT1KLqbnDUVRCdlq1EMxirW3ixyaSA
80
- # Encrypt Key => 20cf3067dec35817data-crunch18083.0321.02.878296898
81
- # An Open Key => FvxETEpmoVUetyJ0jJk19aus1pQkzLZ8OVJccatYnC9GxDE4Iy3AyWNZ...
82
- #
83
- # $ printenv
84
- # $ export OPS_KEY=`ops key`
85
- # $ printenv
86
- #
87
- # The 2nd printenv should reveal a shell specific environment variable.
88
- #
89
- # OPS_KEY=FvxETEpmoVUetyJ0jJk19aus1pQkzLZ8OVJccatYnC9GxDE4Iy3AyWNZ...
90
- #
91
- def execute
92
-
93
- session_key = ToolBelt::Engineer.strong_key( 48 )
94
- openkey_key = Base64.urlsafe_encode64(
95
- ToolBelt::Blowfish.encryptor( session_key, session_key_password )
96
- ).gsub("=","@")
97
-
98
- print openkey_key
99
-
100
- end
101
-
102
-
103
- # Perform pre-conditional validations in preparation to executing the main flow
104
- # of events for this use case. This method may throw the below exceptions.
105
- #
106
- # @raise [SafeDirNotConfigured] if the safe's url has not been configured
107
- # @raise [EmailAddrNotConfigured] if the email address has not been configured
108
- # @raise [StoreUrlNotConfigured] if the crypt store url is not configured
109
- def pre_validation
110
-
111
-
112
- end
113
-
114
-
115
- end
116
-
117
-
118
- end
119
-