opensecret 0.0.913 → 0.0.941

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +3 -0
  3. data/README.md +129 -19
  4. data/Rakefile +0 -9
  5. data/bin/opensecret +1 -1
  6. data/lib/{opensecret/plugins.io/cipher/crypto.rb → crypto/amalgam.rb} +6 -8
  7. data/lib/crypto/collect.rb +139 -0
  8. data/lib/crypto/engineer.rb +201 -0
  9. data/lib/crypto/verify.rb +33 -0
  10. data/lib/extension/array.rb +133 -0
  11. data/lib/{opensecret/additions → extension}/dir.rb +0 -0
  12. data/lib/extension/file.rb +56 -0
  13. data/lib/extension/hash.rb +33 -0
  14. data/lib/extension/string.rb +349 -0
  15. data/lib/factbase/facts.opensecret.io.ini +28 -0
  16. data/lib/logging/gem.logging.rb +133 -0
  17. data/lib/opensecret.rb +102 -45
  18. data/lib/opensecret/executors/crypt.keys/crypt.keys.ini +0 -53
  19. data/lib/session/{session.rb → attributes.rb} +60 -5
  20. data/lib/session/exceptions.rb +53 -0
  21. data/lib/session/fact.finder.rb +684 -0
  22. data/lib/session/user.home.rb +49 -0
  23. data/lib/usecase/usecase.rb +245 -0
  24. data/lib/usecase/usecases/init.rb +190 -0
  25. data/lib/usecase/usecases/on.rb +33 -0
  26. data/lib/usecase/usecases/safe.rb +95 -0
  27. data/lib/version.rb +1 -1
  28. metadata +22 -17
  29. data/lib/opensecret/additions/array.rb +0 -117
  30. data/lib/opensecret/additions/string.rb +0 -312
  31. data/lib/opensecret/commons/eco.cmdline.rb +0 -446
  32. data/lib/opensecret/eco.do.rb +0 -46
  33. data/lib/opensecret/plugins.io/error/eco.exceptions.rb +0 -24
  34. data/lib/opensecret/plugins.io/facts/fact.chars.rb +0 -66
  35. data/lib/opensecret/plugins.io/facts/fact.factor.rb +0 -156
  36. data/lib/opensecret/plugins.io/facts/fact.locator.rb +0 -105
  37. data/lib/opensecret/plugins.io/facts/fact.reader.rb +0 -137
  38. data/lib/opensecret/plugins.io/facts/fact.tree.rb +0 -661
  39. data/lib/opensecret/plugins.io/logs/log.object.rb +0 -89
  40. data/lib/opensecret/plugins.io/logs/logging.rb +0 -203
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 26149681c5b0cbb089a8c9d82953c4e8981147c1
4
- data.tar.gz: 3a2cac8d536acc786fbd1343a694f14ff2b0d73e
3
+ metadata.gz: 435d9f265cc382a9089c052a748983ee1218c0af
4
+ data.tar.gz: 6f7015d873d0b4856c587b8edfcfe25688522106
5
5
  SHA512:
6
- metadata.gz: 79409037388746addf1d6574813a84ab3dedb19761009c56f447b24cfc0ad36262859cf7832f3ff3366847abb912fb81e412893466c9f2489f13e837e6058ea9
7
- data.tar.gz: 79eb02b2befae0c6c0432ed1d065be7b7ea960dc43c64767062ab68419ee49036414376acba0e40047b2d1731422bbd9f9179fc7c6a04a4d8ff92177babdbf9c
6
+ metadata.gz: 3218882929dfda77e99a9fcf164141cfaa1f6b114fe810100db352d4b16f5e02dd4c9d3dea9112742094c02cab8bc6aed2e322c931611e7bad2ffc2ca398898a
7
+ data.tar.gz: ce95ccdee60463940cd67a99faa028afc64d4cdddd1c9b9663d4dab01510670330ea3cc222d1501be275c820098f44acf5fee9daccc88a58b940d17dd37d5586
@@ -0,0 +1,3 @@
1
+ --title "opensecret credentials manager"
2
+ lib/**/*.rb -
3
+ lib/**/*.ini
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  opensecret [![Build Status](https://secure.travis-ci.org/TwP/inifile.png)](http://travis-ci.org/TwP/inifile)
2
2
  ==========
3
3
 
4
- Description
4
+ opensecret | Install and Configure
5
5
  -----------
6
6
 
7
7
  opensecret stashes uncrackable secrets into your Git, S3, DropBox, Google Drive and filesystems backends. You interface with its intuitive Linux, Windows, iOS front ends and it offers SDKs and plugins for Ruby, Python, Go, Java, Jenkins, CodeShip, Ansible, Terraform, Puppet and Chef. Soon, support will be added for database and keystore backends such as MySQL, MongoDB, PostgreSQL, Redis, Memcached and etcd.
@@ -13,21 +13,14 @@ opensecret stashes uncrackable secrets into your Git, S3, DropBox, Google Drive
13
13
 
14
14
  $ gem install opensecret
15
15
 
16
-
17
16
  ### opensecret | Configure It
18
17
 
19
- $ opensecret keydir /path/to/usb/key/dir
20
- $ opensecret name joe
21
- $ opensecret email joebloggs@harvard.edu
22
- $ opensecret domain lecturers@harvard
23
- $ opensecret store https://www.eco-platform.co.uk/crypt/lecturers.git
24
-
18
+ $ opensecret safe /path/to/usb/key/safe
19
+ $ opensecret email joebloggs@harvard.edu
20
+ $ opensecret store https://www.eco-platform.co.uk/crypt/lecturers.git
25
21
  $ opensecret init
26
22
 
27
-
28
- ### opensecret | All Done!
29
-
30
- You are done setting up opensecret with just 5 commands. *Simple* means less mistakes, less confusion and therefore more secure. Let's recap on the 5 configurations
23
+ These directives tell opensecret **where**, **who** and **which** - the order doesn't matter.
31
24
 
32
25
  - <tt>**keydir**</tt> &raquo; best practise is a usb key drive with your **actual keys**
33
26
  - <tt>**name**</tt> &raquo; single word lowercase and short - how your peers call you
@@ -35,15 +28,52 @@ You are done setting up opensecret with just 5 commands. *Simple* means less mis
35
28
  - <tt>**domain**</tt> &raquo; **joe@home** if single or a team like it-dept@ibm.com
36
29
  - <tt>**store**</tt> &raquo; a Git project URL to hold your encrypted secret material
37
30
 
38
- The opensecret init command
31
+ ### opensecret | Create Keys
32
+
33
+ Init(ialize) creates an uncrackable **8192 bit private/public key pair**, locked down with an amalgamated (human and machine generated) password.
34
+
35
+ $ opensecret init
36
+
37
+ Or you can enter the password on the command line.
39
38
 
40
- - creates a 8192 bit uncrackable private key
41
- - collects a human password and creates a machine password
42
- - locks the private key with a minimum 64 character amalgamated password
43
- - locks the public key's fingerprint making it tamper proof
44
- - creates a base directory on your backend store
39
+ $ opensecret init --password="seeKr33t-p4ssw0RD@x"
40
+
41
+
42
+ ### opensecret | All Done!
43
+
44
+ **opensecret is configured!** Before locking and unlocking sensitive data let's ask ***"How can Susan <tt>steal</tt> Joe's secrets?*** Well, she would need to
45
+
46
+ - **acquire** his USB drive key
47
+ - *requisition* his laptop, crack the disk encryption and assail the login password
48
+ - convince Joe that **revealing his password is the painless route, then
49
+ - break into the backend store (AWS S3, GitHub, Google Drive, SSH)
50
+
51
+ It's simple for Joe but nigh impossible for Susan. That's why you need a USB key drive, an offsite storage solution and an encrypted drive.
52
+
53
+ Your ability to access your own secrets (even after disaster scenarios) is as important as preventing the secrets being accessed. This is why opensecret piggy backs off your (already configured) redundancy and backup solutions.
54
+
55
+
56
+ opensecret | Lock and Unlock
57
+ -----------
58
+
59
+ Joe wants to lock away his wifi password.
60
+
61
+ $ opensecret init
62
+
63
+
64
+
65
+ opensecret | moving to anoter computer
66
+ -----------
67
+
68
+ On computer where it is all working you do
69
+
70
+ $ opensecret copy config
71
+
72
+ Then you take out the USB key and (many hours or even days later)
73
+ you put it back into another computer you do
74
+
75
+ $ opensecret paste config
45
76
 
46
- Now you are ready to begin locking and unlocking and soon, you'll be able to request a secret (like a WiFi or NetFlix password) from others in your group. You too can either acquiesce (or reject) requests from your colleagues, friends and family.
47
77
 
48
78
 
49
79
  One Lock | Two Keys
@@ -59,6 +89,78 @@ For scripts that cannot stop and wait for user input - keys can optionally be cr
59
89
 
60
90
  $ opensecret init --password="p455w0rd.!0NDUN"
61
91
 
92
+ The Encryption Strategy
93
+ -----------------------
94
+
95
+ opensecret uses a symmetric key to perform the initial encryption of the data, followed by an asymmetric public key that encrypts the result.
96
+
97
+ The encryption key itself is then locked down by the public key which is then thrown away. The file on the backend store is the doubly encrypted secret.
98
+
99
+ A corresponding file appears on the front end (usb drive) store afer encryption by the master public key. This bundle (decryptable by the master private key) is an amalgamation of the
100
+
101
+ - private key (to unlock the first layer of 1 secret and its encryption key)
102
+ - the encrypted encryption key (unlockable by the aforementioned private key)
103
+ - technical specification of the encryption algorithm plus settings
104
+
105
+ The benefits of this strategy can now be assessed. First off, is the 3 isolated stores that are created.
106
+
107
+
108
+ ### The 3 Isolated (Worthless) Stores
109
+
110
+ There is a grand design behind this mesh of keys, cipher text and symmetricity. The theoretical underpinning
111
+ of opensecret is predicated on a tri-store security solution.
112
+
113
+ **What is tri-store?** Use opensecret and you get 3 isolated (and individually worthless) information stores.
114
+
115
+ - a backend store of doubly encrypted secrets
116
+ - a middle store of doubly encrypted keys
117
+ - a front end of encrypted master key (on USB), human password (in brain) and encrypted machine password (in machine)
118
+
119
+ You can think of opensecret as a reference open source implementation of the tri-store concept.
120
+
121
+ #### Sending a Wifi Password
122
+
123
+ With the **one password culture**, just one password gives you access to everything. I can't send a Wifi password (which is gold dust to hackers) securely. I have to login (potentially exposing every secret) - copy and paste the Wifi password and then email it - even if I encrypt it I am still sending the ciphertext and then they key.
124
+
125
+
126
+ #### benefits of a tri-store solution
127
+
128
+ Think of your doubly encrypted ciphertext as the backend, the doubly encrypted keys as the middle and then the logical group of the master key (on USB), human password (in brain) and encrypted machine password (on machine).
129
+
130
+ - you can transport and/or share secrets by sending the keys (not the backend material)
131
+ - you can rotate your master key and passwords (again - no touching or accessing the backend)
132
+ - you can (and should) assign separate (off-machine) stores for the middle and backend
133
+ - you can select different local or cloud based storage locations for middle and backend stores
134
+ - you can safely backup stores - and with Git you get this (and rollbacks) for no extra effort
135
+ - you can invalidate, expire and revoke secrets by interacting with just the middle tier
136
+ - when a secret is read - it is locked up again with new keys giving you a read audit trail
137
+
138
+ #### the no-go no-clouds mantra
139
+
140
+ opensecret is designed to operate in highly secure locked down environments in which external access is not just constrained - it is non-existent.
141
+
142
+ opensecret does not contact nor talk to anything external. It never asks (nor needs to know) the credentials for accessing your stores - this means it compliments your storage security be it S3, Google Drive, databases, VPN, Git and even email/pop3 solutions.
143
+
144
+ #### the encrypted at rest mantra
145
+
146
+ The ability to read data from drives (after the fact and) after deletion means **nothing unencrypted** should be put on any drive (including usb keys).
147
+
148
+
149
+ #### easy adoption of new algorithms
150
+
151
+ You can configure the algorithm (or algorithms) and implementation used and this information is encrypted within the middle tier store.
152
+
153
+ Attacks usually target particular algorithms so putting this information away (or even randomly selecting from a pool of algorithms) - all adds to the worthlessness of the backend cipher text store.
154
+
155
+ Algorithms can also be selected based on encryption targets like
156
+
157
+ - binary files
158
+ - large text files or
159
+ - small 4 digit keys (like pin numbers)
160
+
161
+ Not only do no two pieces of encrypted material share encryption keys, they also need not share encryption algorithms (and remember - they are doubly encrypted).
162
+
163
+
62
164
 
63
165
  opensecret configuration
64
166
  ------------------------
@@ -114,11 +216,19 @@ It is much more secure to beg for a secret than just have someone reveal it. Whe
114
216
  Any hijacker will need access to a great many things and be very precise with their timing in order to serrupticiously subvert the system.
115
217
 
116
218
 
219
+ Git | S3 or ... | Which Backend Storage?
220
+ ----------------------------------------
221
+
222
+ If you have a choice and would like to know the pros and cons of one of the many backend storage options then visit the opensecret.io website.
223
+
224
+
117
225
 
118
226
  ### opensecret | Summary
119
227
 
120
228
  You can use opensecret alone or you can use it to share secrets with colleagues, friends and family, even machines.
121
229
 
230
+ opensecret is simple and holistically secure. *Simple* means less mistakes, less confusion and more peer reviews from internet security experts.
231
+
122
232
  Every domain is tied to backend storage which is accessible by you and others in your domain. You can use Git, S3, a networked filesystem or shared drive, a SSH accessible filesystem and soon, free storage from <tt>opensecret.io</tt>
123
233
 
124
234
 
data/Rakefile CHANGED
@@ -14,12 +14,3 @@ end
14
14
 
15
15
  task :default => :test
16
16
 
17
- # -
18
- # - This configuration allows us to run "rake yard"
19
- # - to build documentation.
20
- # -
21
- # ---> require 'yard'
22
- # ---> YARD::Rake::YardocTask.new do |t|
23
- # ---> t.files = ['lib/**/*.rb']
24
- # ---> t.stats_options = ['--list-undoc']
25
- # ---> end
@@ -3,4 +3,4 @@
3
3
  # --> require 'opensecret/safe'
4
4
  require 'opensecret'
5
5
 
6
- CommandProcessor.start(ARGV)
6
+ CliInterpreter.start(ARGV)
@@ -2,15 +2,13 @@
2
2
 
3
3
  module OpenSecret
4
4
 
5
+ # This class will be refactored into an interface implemented by a set
6
+ # of plugins that will capture sensitive information from users from an
7
+ # Ubuntu, Windows, RHEL, CoreOS, iOS or CentOS command line interface.
5
8
  #
6
- # Create dynamic secrets of various flavours including
7
- #
8
- # - ssh public/private key secrets
9
- # - secret keys for internal database services
10
- # - hashed SHA256 keys for Jenkins user auth
11
- #
12
- class Crypto
13
-
9
+ # An equivalent REST API will also be available for bringing in sensitive
10
+ # information in the most secure (but simple) manner.
11
+ class Collect
14
12
 
15
13
  # Register two fundamental opensecret crypt pointers
16
14
  #
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module OpenSecret
4
+
5
+
6
+ # This class will be refactored into an interface implemented by a set
7
+ # of plugins that will capture sensitive information from users from an
8
+ # Ubuntu, Windows, RHEL, CoreOS, iOS or CentOS command line interface.
9
+ #
10
+ # An equivalent REST API will also be available for bringing in sensitive
11
+ # information in the most secure (but simple) manner.
12
+ class Collect
13
+
14
+
15
+ # <tt>Collect something sensitive from the command line</tt> with a
16
+ # minimum length specified in the first parameter. This method can't
17
+ # know whether the information is a password, a pin number or whatever
18
+ # so it takes the integer minimum size at its word.
19
+ #
20
+ # @param min_size [Integer] the minimum size of the collected secret
21
+ # whereby one (1) is the least we can expect. The maximum bound is
22
+ # not constrained here so will fall under what is allowed by the
23
+ # interface, be it a CLI, Rest API, Web UI or Mobile App.
24
+ #
25
+ # @param prompt_twice [Boolean] indicate whether the user should be
26
+ # prompted twice. If true the prompt_2 text must be provided and
27
+ # converse is also true. A true value asserts that both times the
28
+ # user enters the same (case sensitive) string.
29
+ #
30
+ # @param prompt_1 [String] the text (aide memoire) used to prompt the user
31
+ #
32
+ # @param prompt_2 [String] if the prompt twice boolean is TRUE, this
33
+ # second prompt (aide memoire) must be provided.
34
+ #
35
+ # @return [String] the collected string text ( watch out for non-ascii chars)
36
+ # @raise [ArgumentError] if the minimum size is less than one
37
+ def self.secret_text min_size, prompt_twice, prompt_1, prompt_2=nil
38
+
39
+ # put this into caller class if reading from facts.
40
+ # put this into caller class if reading from facts.
41
+ # put this into caller class if reading from facts.
42
+ # min_msg = "The minimum size #{min_size.to_s} must be an integer."
43
+ # raise ArgumentError, min_msg unless min_size.instance_of? Integer
44
+
45
+ assert_min_size min_size
46
+
47
+ sleep(1)
48
+ puts "\n#{prompt_1} : "
49
+ first_secret = STDIN.noecho(&:gets).chomp
50
+
51
+ assert_input_text_size first_secret.length, min_size
52
+ return first_secret unless prompt_twice
53
+
54
+ sleep(1)
55
+ puts "\n#{prompt_2} : "
56
+ check_secret = STDIN.noecho(&:gets).chomp
57
+
58
+ assert_same_size_text first_secret, check_secret
59
+
60
+ return first_secret
61
+
62
+ end
63
+
64
+
65
+ # --
66
+ # -- Raise an exception if asked to collect text that is less
67
+ # -- than 3 characters in length.
68
+ # --
69
+ def self.assert_min_size min_size
70
+
71
+ min_length_msg = "\n\nCrypts with 2 (or less) characters open up exploitable holes.\n\n"
72
+ raise ArgumentError.new min_length_msg if min_size < 3
73
+
74
+ end
75
+
76
+
77
+ # --
78
+ # -- Output an error message and then exit if the entered input
79
+ # -- text size does not meet the minimum requirements.
80
+ # --
81
+ def self.assert_input_text_size input_size, min_size
82
+
83
+ if( input_size < min_size )
84
+
85
+ puts
86
+ puts "Input is too short. Please enter at least #{min_size} characters."
87
+ puts
88
+
89
+ exit
90
+
91
+ end
92
+
93
+ end
94
+
95
+
96
+ # --
97
+ # -- Assert that the text entered the second time is exactly (case sensitive)
98
+ # -- the same as the text entered the first time.
99
+ # --
100
+ def self.assert_same_size_text first_text, second_text
101
+
102
+ unless( first_text.eql? second_text )
103
+
104
+ puts
105
+ puts "Those two bits of text are not the same (in my book)!"
106
+ puts
107
+
108
+ exit
109
+
110
+ end
111
+
112
+ end
113
+
114
+
115
+ # --
116
+ # -- Print out the machine password that is to be kept as an environment variable
117
+ # -- on any workstation used for material decryption.
118
+ # --
119
+ # -- Remember that neither the human nor machine passwords are required for the
120
+ # -- encryption phase. That is the beauty of assymetric cryptography - you don't
121
+ # -- need a private key to encrypt - just the end user's public key.
122
+ # --
123
+ def self.print_secret_env_var env_var_name, env_var_value
124
+
125
+ machine_to_env_txt = "sudo echo \"#{env_var_name}=#{env_var_value}\" >> /etc/environment"
126
+
127
+ puts
128
+ puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
129
+ puts "@@@ Add as environment variable @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
130
+ puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
131
+ puts machine_to_env_txt
132
+ puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
133
+ puts
134
+
135
+ end
136
+
137
+ end
138
+
139
+ end
@@ -0,0 +1,201 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module OpenSecret
4
+
5
+ # This class will be refactored into an interface implemented by a set
6
+ # of plugins that will capture sensitive information from users from an
7
+ # Ubuntu, Windows, RHEL, CoreOS, iOS or CentOS command line interface.
8
+ #
9
+ # An equivalent REST API will also be available for bringing in sensitive
10
+ # information in the most secure (but simple) manner.
11
+ class Collect
12
+
13
+ # Register two fundamental opensecret crypt pointers
14
+ #
15
+ # - an opensecret domain like &raquo; **lecturers@harvard**
16
+ # - the url to a backend store like Git, S3 or an SSH accessible drive.
17
+ #
18
+ # The domain will be extended to cover verified internet domains.
19
+ # They will also latch onto LDAP domains so when admins add, revoke
20
+ # or remove users, their opensecret access is adjusted accordingly.
21
+ #
22
+ # @param domain [String] the DOMAIN eg lecturers@harvard for your family or work group.
23
+ # @param store_url [String] the STORE_URL for connecting to the backend storage service
24
+ #
25
+ def self.register_domain domain, store_url
26
+
27
+ # -> read config file map
28
+ # -> create new domain in map
29
+ # -> add type and store url to map
30
+ # -> backup configuration
31
+ # -> overwrite the ini config file
32
+ puts "hello i am registering this super domain #{domain} at #{store_url}"
33
+
34
+ end
35
+
36
+
37
+ # --
38
+ # -- Get a viable machine password taking into account the human
39
+ # -- password length and the specified mix_ratio.
40
+ # --
41
+ # -- machine password length = human password length * mix_ratio - 1
42
+ # --
43
+ def self.get_amalgam_password human_password, machine_password, mix_ratio
44
+
45
+ size_error_msg = "Human pass length times mix_ratio must equal machine pass length."
46
+ lengths_are_perfect = human_password.length * mix_ratio == machine_password.length
47
+ raise ArgumentError.new size_error_msg unless lengths_are_perfect
48
+
49
+ machine_passwd_chunk = 0
50
+ amalgam_passwd_index = 0
51
+ amalgamated_password = ""
52
+
53
+ human_password.each_char do |passwd_char|
54
+
55
+ amalgamated_password[amalgam_passwd_index] = passwd_char
56
+ amalgam_passwd_index += 1
57
+
58
+ for i in 0..(mix_ratio-1) do
59
+ machine_pass_index = machine_passwd_chunk * mix_ratio + i
60
+ amalgamated_password[amalgam_passwd_index] = machine_password[machine_pass_index]
61
+ amalgam_passwd_index += 1
62
+ end
63
+
64
+ machine_passwd_chunk += 1
65
+
66
+ end
67
+
68
+ return amalgamated_password
69
+
70
+ end
71
+
72
+
73
+ # --
74
+ # -- Get a viable machine password taking into account the human
75
+ # -- password length and the specified mix_ratio.
76
+ # --
77
+ # -- machine password length = human password length * mix_ratio - 1
78
+ # --
79
+ def self.get_machine_password human_password_length, mix_ratio
80
+
81
+ machine_raw_secret = engineer_password( human_password_length * ( mix_ratio + 1) )
82
+ return machine_raw_secret[ 0..( human_password_length * mix_ratio - 1 ) ]
83
+
84
+ end
85
+
86
+
87
+ # --
88
+ # -- Collect a password from the user with a minimum length
89
+ # -- specified in the parameter.
90
+ # --
91
+ # -- An exception is raised if the minimum length is not at
92
+ # -- least 8 characters.
93
+ # --
94
+ def self.collect_secret minimum_size, prompt_1, prompt_2
95
+
96
+ assert_min_size minimum_size
97
+
98
+ sleep(1)
99
+ puts "\n#{prompt_1} : "
100
+ first_secret = STDIN.noecho(&:gets).chomp
101
+
102
+ assert_input_text_size first_secret.length, minimum_size
103
+
104
+ sleep(1)
105
+ puts "\n#{prompt_2} : "
106
+ check_secret = STDIN.noecho(&:gets).chomp
107
+
108
+ assert_same_size_text first_secret, check_secret
109
+
110
+ return first_secret
111
+
112
+ end
113
+
114
+
115
+ # --
116
+ # -- Engineer a raw password that is similar (approximate) in
117
+ # -- length to the integer parameter.
118
+ # --
119
+ def self.engineer_password approx_length
120
+
121
+ non_alphanum = SecureRandom.urlsafe_base64(approx_length);
122
+ return non_alphanum.delete("-_")
123
+
124
+ end
125
+
126
+
127
+ # --
128
+ # -- Raise an exception if asked to collect text that is less
129
+ # -- than 3 characters in length.
130
+ # --
131
+ def self.assert_min_size minimum_size
132
+
133
+ min_length_msg = "\n\nCrypts with 2 (or less) characters open up exploitable holes.\n\n"
134
+ raise ArgumentError.new min_length_msg if minimum_size < 3
135
+
136
+ end
137
+
138
+
139
+ # --
140
+ # -- Output an error message and then exit if the entered input
141
+ # -- text size does not meet the minimum requirements.
142
+ # --
143
+ def self.assert_input_text_size input_size, minimum_size
144
+
145
+ if( input_size < minimum_size )
146
+
147
+ puts
148
+ puts "Input is too short. Please enter at least #{minimum_size} characters."
149
+ puts
150
+
151
+ exit
152
+
153
+ end
154
+
155
+ end
156
+
157
+
158
+ # --
159
+ # -- Assert that the text entered the second time is exactly (case sensitive)
160
+ # -- the same as the text entered the first time.
161
+ # --
162
+ def self.assert_same_size_text first_text, second_text
163
+
164
+ unless( first_text.eql? second_text )
165
+
166
+ puts
167
+ puts "Those two bits of text are not the same (in my book)!"
168
+ puts
169
+
170
+ exit
171
+
172
+ end
173
+
174
+ end
175
+
176
+
177
+ # --
178
+ # -- Print out the machine password that is to be kept as an environment variable
179
+ # -- on any workstation used for material decryption.
180
+ # --
181
+ # -- Remember that neither the human nor machine passwords are required for the
182
+ # -- encryption phase. That is the beauty of assymetric cryptography - you don't
183
+ # -- need a private key to encrypt - just the end user's public key.
184
+ # --
185
+ def self.print_secret_env_var env_var_name, env_var_value
186
+
187
+ machine_to_env_txt = "sudo echo \"#{env_var_name}=#{env_var_value}\" >> /etc/environment"
188
+
189
+ puts
190
+ puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
191
+ puts "@@@ Add as environment variable @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
192
+ puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
193
+ puts machine_to_env_txt
194
+ puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
195
+ puts
196
+
197
+ end
198
+
199
+ end
200
+
201
+ end