opensecret 0.0.988 → 0.0.9925

Sign up to get free protection for your applications and to get access to all the features.
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
-