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
@@ -4,31 +4,31 @@ module OpenSecret
4
4
 
5
5
  require 'openssl'
6
6
 
7
- # The <tt>unlock use case</tt> moves doubly encrypted material <b>from the frozen</b>
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>Unlock | Pre-Conditions</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>unlock</b> expects
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>Unlock | Alternate Flows</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>Unlock | Observable Value</b>
29
+ # <b>Export | Observable Value</b>
30
30
  #
31
- # The observable value proffered by unlock is
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 unlock geo/countries --with=asdfasdf
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 unlock my/gadgets --with="hUM4n-0pen$3cr3t"
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 Unlock < SecretsUseCase
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
- main_store = ColdStore.new @c[:global][:store_mainpath]
114
- keys_store = ColdStore.new @c[:global][:store_keyspath]
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 = OpenSession::Attributes.instance.get_value @c[:global][:name], @c[:global][:name], @c[:global][:machine_key_x]
128
- original_timestamp = OpenSession::Attributes.instance.get_value @c[:global][:name], @c[:global][:name], @c[:global][:stamp_key]
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], @email_addr, @c[:global][:separator_a], original_timestamp ]
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.new.decryptor workstation_cipher, workstation_lock_x
134
- private_key_lock_x = Amalgam.passwords @master_p4ss, workstation_string, @c[:global][:ratio]
135
- private_key_cipher = File.read @c[:global][:master_prv_key]
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
- # key4_pem = File.read 'private.secure.pem'
174
- # pass_phrase = 'superduperpasswordistoBeENTEREDRIGHT1234HereandRightNOW'
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
+