opensecret 0.0.962 → 0.0.988
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +16 -10
- data/bin/opensecret +3 -4
- data/bin/ops +5 -0
- data/lib/extension/string.rb +114 -0
- data/lib/factbase/facts.opensecret.io.ini +9 -21
- data/lib/interprete/begin.rb +232 -0
- data/lib/interprete/cmd.rb +621 -0
- data/lib/{plugins/usecases/unlock.rb → interprete/export.rb} +25 -70
- data/lib/interprete/init.rb +205 -0
- data/lib/interprete/key.rb +119 -0
- data/lib/interprete/open.rb +148 -0
- data/lib/{plugins/usecases → interprete}/put.rb +19 -6
- data/lib/{plugins/usecases → interprete}/safe.rb +2 -1
- data/lib/{plugins/usecases/lock.rb → interprete/seal.rb} +24 -34
- data/lib/interprete/set.rb +46 -0
- data/lib/interprete/use.rb +43 -0
- data/lib/interpreter.rb +165 -0
- data/lib/keytools/binary.map.rb +245 -0
- data/lib/keytools/digester.rb +245 -0
- data/lib/keytools/doc.conversion.to.ones.and.zeroes.ruby +179 -0
- data/lib/keytools/doc.rsa.radix.binary-mapping.ruby +190 -0
- data/lib/keytools/doc.star.schema.strategy.txt +77 -0
- data/lib/keytools/doc.using.pbkdf2.kdf.ruby +95 -0
- data/lib/keytools/doc.using.pbkdf2.pkcs.ruby +266 -0
- data/lib/keytools/kdf.bcrypt.rb +180 -0
- data/lib/keytools/kdf.pbkdf2.rb +164 -0
- data/lib/keytools/key.data.rb +227 -0
- data/lib/keytools/key.derivation.rb +341 -0
- data/lib/keytools/key.module.rb +140 -0
- data/lib/keytools/key.rb +481 -0
- data/lib/logging/gem.logging.rb +1 -2
- data/lib/modules/cryptology.md +43 -0
- data/lib/{plugins/ciphers → modules/cryptology}/aes-256.rb +6 -0
- data/lib/{crypto → modules/cryptology}/amalgam.rb +6 -0
- data/lib/modules/cryptology/blowfish.rb +130 -0
- data/lib/modules/cryptology/cipher.rb +207 -0
- data/lib/modules/cryptology/collect.rb +118 -0
- data/lib/{plugins → modules/cryptology}/crypt.io.rb +5 -0
- data/lib/{crypto → modules/cryptology}/engineer.rb +7 -1
- data/lib/{crypto → modules/cryptology}/open.bcrypt.rb +0 -0
- data/lib/modules/mappers/collateral.rb +282 -0
- data/lib/modules/mappers/dictionary.rb +288 -0
- data/lib/modules/mappers/envelope.rb +127 -0
- data/lib/modules/mappers/settings.rb +170 -0
- data/lib/modules/storage/coldstore.rb +186 -0
- data/lib/{opensecret/plugins.io/git/git.flow.rb → modules/storage/git.store.rb} +11 -0
- data/lib/notepad/scratch.pad.rb +17 -0
- data/lib/session/fact.finder.rb +13 -0
- data/lib/session/require.gem.rb +5 -0
- data/lib/store-commands.txt +180 -0
- data/lib/version.rb +1 -1
- data/opensecret.gemspec +5 -6
- metadata +74 -29
- data/lib/crypto/blowfish.rb +0 -85
- data/lib/crypto/collect.rb +0 -140
- data/lib/crypto/verify.rb +0 -33
- data/lib/opensecret.rb +0 -236
- data/lib/plugins/cipher.rb +0 -203
- data/lib/plugins/ciphers/blowfish.rb +0 -126
- data/lib/plugins/coldstore.rb +0 -181
- data/lib/plugins/envelope.rb +0 -116
- data/lib/plugins/secrets.uc.rb +0 -94
- data/lib/plugins/usecase.rb +0 -239
- data/lib/plugins/usecases/init.rb +0 -145
- data/lib/plugins/usecases/open.rb +0 -108
- data/lib/session/attributes.rb +0 -279
- data/lib/session/dictionary.rb +0 -191
- data/lib/session/file.path.rb +0 -53
- data/lib/session/session.rb +0 -80
@@ -4,31 +4,31 @@ module OpenSecret
|
|
4
4
|
|
5
5
|
require 'openssl'
|
6
6
|
|
7
|
-
# The <tt>
|
7
|
+
# The <tt>export use case</tt> moves doubly encrypted material <b>from the frozen</b>
|
8
8
|
# (key and crypt) stores, <b>into an (encrypted) session envelope</b>.
|
9
9
|
#
|
10
10
|
# Material within the auspices of the session envelope can be manipulated by commands
|
11
11
|
# like {OpenSecret::Put} and remove and also read by commands like peep, look and update.
|
12
12
|
#
|
13
|
-
# <b>
|
13
|
+
# <b>Export | Pre-Conditions</b>
|
14
14
|
#
|
15
15
|
# To deliver on its core promise of moving the encrypted (key and crypt) stores
|
16
|
-
# to an encrypted session envelope, <b>
|
16
|
+
# to an encrypted session envelope, <b>export</b> expects
|
17
17
|
#
|
18
18
|
# - the local key and crypt stores to be pulled (refreshed) from remote
|
19
19
|
# - the destination session path to either be empty (or)
|
20
20
|
# - a populated session path containing equivalent data (ie cannot be overwritten)
|
21
21
|
# - both the human (agent) password and workstation key to be correct
|
22
22
|
#
|
23
|
-
# <b>
|
23
|
+
# <b>Export | Alternate Flows</b>
|
24
24
|
#
|
25
25
|
# This use case requires the human (agent) password unless the <tt>--no-human-password</tt>
|
26
26
|
# flag was posted along with the <tt>init</tt> command. In this instance an agent password
|
27
27
|
# will have been generated and encrypted with the user's home tree.
|
28
28
|
#
|
29
|
-
# <b>
|
29
|
+
# <b>Export | Observable Value</b>
|
30
30
|
#
|
31
|
-
# The observable value proffered by
|
31
|
+
# The observable value proffered by export is
|
32
32
|
#
|
33
33
|
# - validating the existence of the requested secret path
|
34
34
|
# - validation of the human password and workstation key
|
@@ -46,7 +46,7 @@ module OpenSecret
|
|
46
46
|
# $ opensecret put france/capital paris
|
47
47
|
# $ opensecret put france/population 23000000
|
48
48
|
# $ opensecret lock
|
49
|
-
# $ opensecret
|
49
|
+
# $ opensecret export geo/countries --with=asdfasdf
|
50
50
|
#
|
51
51
|
# Below are future examples with use cases like list and print
|
52
52
|
# which curently have not been implemented.
|
@@ -62,7 +62,7 @@ module OpenSecret
|
|
62
62
|
# $ opensecret lock
|
63
63
|
# $ opensecret list
|
64
64
|
#
|
65
|
-
# $ opensecret
|
65
|
+
# $ opensecret export my/gadgets --with="hUM4n-0pen$3cr3t"
|
66
66
|
# $ opensecret print
|
67
67
|
#
|
68
68
|
# $ opensecret put wifi/ssid Virgin-HGPAS
|
@@ -71,10 +71,9 @@ module OpenSecret
|
|
71
71
|
# $ opensecret print
|
72
72
|
# $ opensecret lock
|
73
73
|
#
|
74
|
-
class
|
74
|
+
class Export < Command
|
75
75
|
|
76
76
|
attr_writer :outer_path, :master_p4ss
|
77
|
-
@@context_name = "opensecret"
|
78
77
|
|
79
78
|
|
80
79
|
# The <tt>lock use case</tt> is called after {OpenSecret::Open} and {OpenSecret::Put}
|
@@ -110,76 +109,39 @@ module OpenSecret
|
|
110
109
|
# - deletion of {Open}ed session data to locate and decrypt envelope
|
111
110
|
def execute
|
112
111
|
|
113
|
-
|
114
|
-
|
112
|
+
instantiate_collateral
|
113
|
+
|
114
|
+
keys_store = Store::ColdStore.new( @collateral.frontend_keystore_path )
|
115
|
+
main_store = Store::ColdStore.new( @collateral.backend_cryptstore_path )
|
115
116
|
|
116
117
|
keys_crypt = keys_store.read @outer_path
|
117
118
|
main_crypt = main_store.read @outer_path
|
118
119
|
|
119
120
|
unless @master_p4ss
|
120
|
-
@master_p4ss = Collect.secret_text(
|
121
|
+
@master_p4ss = ToolBelt::Collect.secret_text(
|
121
122
|
@c[:global][:min_passwd_len],
|
122
123
|
false,
|
123
124
|
"Enter Master Password "
|
124
125
|
)
|
125
126
|
end
|
126
127
|
|
127
|
-
workstation_rawkey =
|
128
|
-
original_timestamp =
|
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]
|
129
130
|
workstation_cipher = Base64.urlsafe_decode64( workstation_rawkey )
|
130
|
-
crypt_key_segments = [ @master_p4ss, @c[:global][:separator_a],
|
131
|
+
crypt_key_segments = [ @master_p4ss, @c[:global][:separator_a], original_timestamp ]
|
131
132
|
workstation_lock_x = crypt_key_segments.alphanumeric_union.concat_length
|
132
133
|
|
133
|
-
workstation_string = Blowfish.
|
134
|
-
private_key_lock_x = Amalgam.passwords @master_p4ss, workstation_string, @c[:global][:ratio]
|
135
|
-
private_key_cipher =
|
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
|
136
137
|
private_key_object = unlock_private_key( private_key_cipher, private_key_lock_x )
|
137
138
|
|
138
|
-
string_private_key = Cipher.decrypt_it( private_key_object, keys_crypt )
|
139
|
-
plain_message_text = Cipher.decrypt_it( to_private_key(string_private_key), main_crypt )
|
140
|
-
|
141
|
-
puts ""
|
142
|
-
puts "==== ======================================= ===="
|
143
|
-
puts "==== The Exported Plain Text Structured Data ===="
|
144
|
-
puts "==== ======================================= ===="
|
145
|
-
puts ""
|
146
|
-
puts plain_message_text
|
147
|
-
puts ""
|
148
|
-
puts ""
|
149
|
-
puts JSON.pretty_generate( JSON.parse( plain_message_text ) )
|
150
|
-
puts ""
|
151
|
-
|
152
|
-
exit
|
153
|
-
|
154
|
-
#############################################################################################
|
155
|
-
#############################################################################################
|
156
|
-
|
157
|
-
rel_filepath = OpenSession::Attributes.instance.get_value @@context_name, @c[:open][:open_name], @c[:open][:open_pathname]
|
158
|
-
master_public_key = Base64.urlsafe_decode64( OpenSession::Attributes.instance.get_value @c[:global][:name], @c[:global][:name], "public.key" )
|
159
|
-
|
160
|
-
|
161
|
-
#############################################################################################
|
162
|
-
#############################################################################################
|
163
|
-
|
164
|
-
=begin
|
165
|
-
Crypto.print_secret_env_var @p[:env_var_name], machine_key
|
166
|
-
GitFlow.do_clone_repo @p[:public_gitrepo], @p[:local_gitrepo]
|
167
|
-
FileUtils.mkdir_p @p[:public_keydir]
|
168
|
-
File.write @p[:public_keypath], public_key_text
|
169
|
-
GitFlow.push @p[:local_gitrepo], @p[:public_keyname], @c[:time][:stamp]
|
170
|
-
=end
|
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 )
|
171
141
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
# key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase
|
176
|
-
# decrypted_text = key4.private_decrypt(Base64.urlsafe_decode64(encrypted_string))
|
177
|
-
|
178
|
-
# print "\nHey we have done the decryption.\n", "\n"
|
179
|
-
# print decrypted_text, "\n"
|
180
|
-
|
181
|
-
#############################################################################################
|
182
|
-
#############################################################################################
|
142
|
+
puts
|
143
|
+
puts JSON.pretty_generate( JSON.parse( plain_message_text ) )
|
144
|
+
puts
|
183
145
|
|
184
146
|
end
|
185
147
|
|
@@ -192,11 +154,6 @@ module OpenSecret
|
|
192
154
|
# @raise [StoreUrlNotConfigured] if the crypt store url is not configured
|
193
155
|
def pre_validation
|
194
156
|
|
195
|
-
@email_addr = OpenSession::Attributes.instance.get_value @@context_name, @@context_name, "email"
|
196
|
-
email_configured = !@email_addr.nil? && !@email_addr.empty? && @email_addr.length > 4
|
197
|
-
@err_msg = "viable [email address] not configured. Try =>] opensecret email joe@example.com"
|
198
|
-
raise EmailAddrNotConfigured.new @err_msg, @email_addr unless email_configured
|
199
|
-
|
200
157
|
end
|
201
158
|
|
202
159
|
|
@@ -204,5 +161,3 @@ module OpenSecret
|
|
204
161
|
|
205
162
|
|
206
163
|
end
|
207
|
-
|
208
|
-
|
@@ -0,0 +1,205 @@
|
|
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
|
@@ -0,0 +1,119 @@
|
|
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
|
+
|