opensecret 0.0.913 → 0.0.941
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +3 -0
- data/README.md +129 -19
- data/Rakefile +0 -9
- data/bin/opensecret +1 -1
- data/lib/{opensecret/plugins.io/cipher/crypto.rb → crypto/amalgam.rb} +6 -8
- data/lib/crypto/collect.rb +139 -0
- data/lib/crypto/engineer.rb +201 -0
- data/lib/crypto/verify.rb +33 -0
- data/lib/extension/array.rb +133 -0
- data/lib/{opensecret/additions → extension}/dir.rb +0 -0
- data/lib/extension/file.rb +56 -0
- data/lib/extension/hash.rb +33 -0
- data/lib/extension/string.rb +349 -0
- data/lib/factbase/facts.opensecret.io.ini +28 -0
- data/lib/logging/gem.logging.rb +133 -0
- data/lib/opensecret.rb +102 -45
- data/lib/opensecret/executors/crypt.keys/crypt.keys.ini +0 -53
- data/lib/session/{session.rb → attributes.rb} +60 -5
- data/lib/session/exceptions.rb +53 -0
- data/lib/session/fact.finder.rb +684 -0
- data/lib/session/user.home.rb +49 -0
- data/lib/usecase/usecase.rb +245 -0
- data/lib/usecase/usecases/init.rb +190 -0
- data/lib/usecase/usecases/on.rb +33 -0
- data/lib/usecase/usecases/safe.rb +95 -0
- data/lib/version.rb +1 -1
- metadata +22 -17
- data/lib/opensecret/additions/array.rb +0 -117
- data/lib/opensecret/additions/string.rb +0 -312
- data/lib/opensecret/commons/eco.cmdline.rb +0 -446
- data/lib/opensecret/eco.do.rb +0 -46
- data/lib/opensecret/plugins.io/error/eco.exceptions.rb +0 -24
- data/lib/opensecret/plugins.io/facts/fact.chars.rb +0 -66
- data/lib/opensecret/plugins.io/facts/fact.factor.rb +0 -156
- data/lib/opensecret/plugins.io/facts/fact.locator.rb +0 -105
- data/lib/opensecret/plugins.io/facts/fact.reader.rb +0 -137
- data/lib/opensecret/plugins.io/facts/fact.tree.rb +0 -661
- data/lib/opensecret/plugins.io/logs/log.object.rb +0 -89
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 435d9f265cc382a9089c052a748983ee1218c0af
|
4
|
+
data.tar.gz: 6f7015d873d0b4856c587b8edfcfe25688522106
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3218882929dfda77e99a9fcf164141cfaa1f6b114fe810100db352d4b16f5e02dd4c9d3dea9112742094c02cab8bc6aed2e322c931611e7bad2ffc2ca398898a
|
7
|
+
data.tar.gz: ce95ccdee60463940cd67a99faa028afc64d4cdddd1c9b9663d4dab01510670330ea3cc222d1501be275c820098f44acf5fee9daccc88a58b940d17dd37d5586
|
data/.yardopts
ADDED
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
|
-
|
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
|
20
|
-
$ opensecret
|
21
|
-
$ opensecret
|
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> » best practise is a usb key drive with your **actual keys**
|
33
26
|
- <tt>**name**</tt> » 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> » **joe@home** if single or a team like it-dept@ibm.com
|
36
29
|
- <tt>**store**</tt> » a Git project URL to hold your encrypted secret material
|
37
30
|
|
38
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
data/bin/opensecret
CHANGED
@@ -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
|
-
#
|
7
|
-
#
|
8
|
-
|
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 » **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
|