opensecret 0.0.962 → 0.0.988

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,140 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- module OpenSecret
4
-
5
- require 'io/console'
6
-
7
- # This class will be refactored into an interface implemented by a set
8
- # of plugins that will capture sensitive information from users from an
9
- # Ubuntu, Windows, RHEL, CoreOS, iOS or CentOS command line interface.
10
- #
11
- # An equivalent REST API will also be available for bringing in sensitive
12
- # information in the most secure (but simple) manner.
13
- class Collect
14
-
15
-
16
- # <tt>Collect something sensitive from the command line</tt> with a
17
- # minimum length specified in the first parameter. This method can't
18
- # know whether the information is a password, a pin number or whatever
19
- # so it takes the integer minimum size at its word.
20
- #
21
- # @param min_size [Integer] the minimum size of the collected secret
22
- # whereby one (1) is the least we can expect. The maximum bound is
23
- # not constrained here so will fall under what is allowed by the
24
- # interface, be it a CLI, Rest API, Web UI or Mobile App.
25
- #
26
- # @param prompt_twice [Boolean] indicate whether the user should be
27
- # prompted twice. If true the prompt_2 text must be provided and
28
- # converse is also true. A true value asserts that both times the
29
- # user enters the same (case sensitive) string.
30
- #
31
- # @param prompt_1 [String] the text (aide memoire) used to prompt the user
32
- #
33
- # @param prompt_2 [String] if the prompt twice boolean is TRUE, this
34
- # second prompt (aide memoire) must be provided.
35
- #
36
- # @return [String] the collected string text ( watch out for non-ascii chars)
37
- # @raise [ArgumentError] if the minimum size is less than one
38
- def self.secret_text min_size, prompt_twice, prompt_1, prompt_2=nil
39
-
40
- # put this into caller class if reading from facts.
41
- # put this into caller class if reading from facts.
42
- # put this into caller class if reading from facts.
43
- # min_msg = "The minimum size #{min_size.to_s} must be an integer."
44
- # raise ArgumentError, min_msg unless min_size.instance_of? Integer
45
-
46
- assert_min_size min_size
47
-
48
- sleep(1)
49
- puts "\n#{prompt_1} : "
50
- first_secret = STDIN.noecho(&:gets).chomp
51
-
52
- assert_input_text_size first_secret.length, min_size
53
- return first_secret unless prompt_twice
54
-
55
- sleep(1)
56
- puts "\n#{prompt_2} : "
57
- check_secret = STDIN.noecho(&:gets).chomp
58
-
59
- assert_same_size_text first_secret, check_secret
60
-
61
- return first_secret
62
-
63
- end
64
-
65
-
66
- # --
67
- # -- Raise an exception if asked to collect text that is less
68
- # -- than 3 characters in length.
69
- # --
70
- def self.assert_min_size min_size
71
-
72
- min_length_msg = "\n\nCrypts with 2 (or less) characters open up exploitable holes.\n\n"
73
- raise ArgumentError.new min_length_msg if min_size < 3
74
-
75
- end
76
-
77
-
78
- # --
79
- # -- Output an error message and then exit if the entered input
80
- # -- text size does not meet the minimum requirements.
81
- # --
82
- def self.assert_input_text_size input_size, min_size
83
-
84
- if( input_size < min_size )
85
-
86
- puts
87
- puts "Input is too short. Please enter at least #{min_size} characters."
88
- puts
89
-
90
- exit
91
-
92
- end
93
-
94
- end
95
-
96
-
97
- # --
98
- # -- Assert that the text entered the second time is exactly (case sensitive)
99
- # -- the same as the text entered the first time.
100
- # --
101
- def self.assert_same_size_text first_text, second_text
102
-
103
- unless( first_text.eql? second_text )
104
-
105
- puts
106
- puts "Those two bits of text are not the same (in my book)!"
107
- puts
108
-
109
- exit
110
-
111
- end
112
-
113
- end
114
-
115
-
116
- # --
117
- # -- Print out the machine password that is to be kept as an environment variable
118
- # -- on any workstation used for material decryption.
119
- # --
120
- # -- Remember that neither the human nor machine passwords are required for the
121
- # -- encryption phase. That is the beauty of assymetric cryptography - you don't
122
- # -- need a private key to encrypt - just the end user's public key.
123
- # --
124
- def self.print_secret_env_var env_var_name, env_var_value
125
-
126
- machine_to_env_txt = "sudo echo \"#{env_var_name}=#{env_var_value}\" >> /etc/environment"
127
-
128
- puts
129
- puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
130
- puts "@@@ Add as environment variable @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
131
- puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
132
- puts machine_to_env_txt
133
- puts "@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
134
- puts
135
-
136
- end
137
-
138
- end
139
-
140
- end
@@ -1,33 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- module OpenSecret
4
-
5
- # This class verifies domain names, email addresses and othe external
6
- # reference data.
7
- class Verify
8
-
9
- # Register two fundamental opensecret crypt pointers
10
- #
11
- # - an opensecret domain like &raquo; **lecturers@harvard**
12
- # - the url to a backend store like Git, S3 or an SSH accessible drive.
13
- #
14
- # The domain will be extended to cover verified internet domains.
15
- # They will also latch onto LDAP domains so when admins add, revoke
16
- # or remove users, their opensecret access is adjusted accordingly.
17
- #
18
- # @param domain [String] the DOMAIN eg lecturers@harvard for your family or work group.
19
- # @param store_url [String] the STORE_URL for connecting to the backend storage service
20
- #
21
- def self.verify_domain domain, store_url
22
-
23
- # -> read config file map
24
- # -> create new domain in map
25
- # -> add type and store url to map
26
- # -> backup configuration
27
- # -> overwrite the ini config file
28
-
29
- end
30
-
31
- end
32
-
33
- end
@@ -1,236 +0,0 @@
1
- require "thor"
2
- require "fileutils"
3
-
4
- require "session/time.stamp"
5
- require "session/attributes"
6
- require "logging/gem.logging"
7
- require "session/require.gem"
8
-
9
- # Include the logger mixins so that every class can enjoy "import free"
10
- # logging through pointers to the (extended) log behaviour.
11
- include OpenLogger
12
-
13
- # This standard out sync command flushes text destined for STDOUT immediately,
14
- # without waiting either for a full cache or script completion.
15
- $stdout.sync = true
16
-
17
- # Recursively require all gems that are either in or under the directory
18
- # that this code is executing from. Only use this tool if your library is
19
- # relatively small but highly interconnected. In these instances it raises
20
- # productivity and reduces harassing "not found" exceptions.
21
- OpenSession::RecursivelyRequire.now( __FILE__ )
22
-
23
-
24
- # This command line processor extends the Thor gem CLI tools in order to
25
- #
26
- # - read the posted commands, options and switches
27
- # - maps the incoming string data to objects
28
- # - assert that the mandatory options exist
29
- # - assert the type of each parameter
30
- # - ensure that the parameter values are in range
31
- # - delegate processing to the registered handlers
32
- #
33
- class CliInterpreter < Thor
34
-
35
- OpenSession::Session.instance.context = "opensecret"
36
- log.info(x) {"opensecret session initiated at [#{OpenSession::Stamp.yyjjj_hhmm_sst}]." }
37
- log.info(x) {"opensecret session context is [#{OpenSession::Session.instance.context}]." }
38
-
39
- #
40
- # This class option allows every CLI call the option to include
41
- # a --debug boolean switch which will up the verbosity of the
42
- # content logged to the file .opensecret/opensecret.log
43
- #
44
- class_option :debug, :type => :boolean
45
-
46
-
47
-
48
- # Description of the init configuration call.
49
- desc "init", "initialize secret keys and check access to the crypt store"
50
-
51
- # Initialize secret keys and check access to the crypt store.
52
- #
53
- # - checks the installed configuration.
54
- def init
55
- OpenSecret::Init.new.flow_of_events
56
- end
57
-
58
-
59
- # Description of the lock use case command line call.
60
- desc "lock", "Lock away the (secret stuffed) envelope into key and crypt stores."
61
-
62
- # Lock away the (secret stuffed) envelope into key and crypt stores.
63
- def lock
64
- OpenSecret::Lock.new.flow_of_events
65
- end
66
-
67
-
68
- # Description of the open use case command.
69
- desc "open OUTER_PATH", "OUTER_PATH to envelope of secrets to stuff and then lock."
70
-
71
- # Open up a conduit from which we can add, subtract, update and list secrets
72
- # before they are committed (and pushed) into permanent locked storage.
73
- #
74
- # @param outer_path [String] the path to USB key for storing encrypted keys
75
- def open outer_path
76
-
77
- open_uc = OpenSecret::Open.new
78
- open_uc.outer_path = outer_path
79
- open_uc.flow_of_events
80
-
81
- end
82
-
83
- # Description of the unlock use case command.
84
- desc "unlock OUTER_PATH", "OUTER_PATH to locked secrets to open for reading or stuffing."
85
-
86
- # If confident that command history cannot be exploited to gain the human password
87
- # or if the agent running opensecret is itself a script, the <tt>with</tt> option can
88
- # be used to convey the password.
89
- option :with
90
-
91
- # Unlock a secrets envelope at the specified outer path so that we can read, put
92
- # and discard secrets.
93
- #
94
- # This use case requires the human (agent) password unless the <tt>--no-human-password</tt>
95
- # flag was posted along with the <tt>init</tt> command.
96
- #
97
- # There are two ways to provide the password (for the <b><em>my/gadgets</em></b> group)
98
- #
99
- # - <tt>opensecret unlock my/gadgets</tt> and respond to the password prompt (or)
100
- # - <tt>opensecret unlock my/gadgets --with="hUM4n-0pen$3cr3t"</tt>
101
- #
102
- # If providing the password on the command line, one must be confident that the shell's
103
- # command history cannot be exploited to capture it.
104
- #
105
- # @param outer_path [String] the path to the (previously) locked secrets in frozen storage.
106
- def unlock outer_path
107
-
108
- unlock_uc = OpenSecret::Unlock.new
109
- unlock_uc.outer_path = outer_path
110
- unlock_uc.master_p4ss = options[:with] if options[:with]
111
- unlock_uc.flow_of_events
112
-
113
- end
114
-
115
- # Description of the put secret command.
116
- desc "put <secret_id> <secret_value>", "put secret like login/username into opened context."
117
-
118
- # Put a secret with an id like login/username and a value like joebloggs into the
119
- # context (eg work/laptop) that was opened with the open command.
120
- #
121
- # @param secret_id [String] the id of the secret to put into the opened context
122
- # @param secret_value [String] the value of the secret to put into the opened context
123
- def put secret_id, secret_value
124
-
125
- put_uc = OpenSecret::Put.new
126
- put_uc.secret_id = secret_id
127
- put_uc.secret_value = secret_value
128
- put_uc.flow_of_events
129
-
130
- end
131
-
132
-
133
- # Description of the mandatory safe and (safe directory) configuration.
134
- desc "safe SAFE_DIR", "SAFE_DIR full path to the (ideally USB key) storage location"
135
-
136
- #
137
- # A USB key drive is the ideal store for the encrypted private
138
- # key and the tamper proof configuration file. This method collects
139
- # the usb drive path and then
140
- #
141
- # - checks the path exists
142
- # - if not, it attempts to create the path
143
- # - if successful it's written into HOME/.opensecret/opensecret.keydir.txt
144
- #
145
- # @param safe_dir [String] the path to USB key for storing encrypted keys
146
- #
147
- def safe safe_dir
148
-
149
- configure_safe_uc = OpenSecret::Safe.new
150
- configure_safe_uc.safe_path = safe_dir
151
- configure_safe_uc.flow_of_events
152
-
153
- end
154
-
155
-
156
- #
157
- # Description of the email-address that is unique
158
- # for the domain in question.
159
- #
160
- desc "email EMAIL_ADDRESS", "EMAIL_ADDRESS Your email address unique for the domain."
161
-
162
- #
163
- # This method collects the email address that is unique for the domain in
164
- # question. For the email address to be valid it must consist of only alphanumerics,
165
- # underscores, periods, hyphens and (at most) one @ symbol.
166
- #
167
- # Note that underscores, periods, hyphens and @ symbol are permissable if not
168
- # at the start or end of the email address nor can they appear consecutively.
169
- #
170
- # <tt>a@b.cd</tt> is the minimum size of an externally addressable email
171
- # address so 6 or more characters is enforced by this configuation method.
172
- #
173
- # email validation will be added to opensecret including
174
- # - validation of the email address character array
175
- # - proof of control and ownership of the email address
176
- #
177
- # If an email address already exists within the domain section of the
178
- # configuration file, it is overwritten. If there is no configuration
179
- # file yet, one is created within the auspices of the home directory.
180
- #
181
- # @param email_address [String] email address of the user (eg a@b.cd)
182
- #
183
- def email email_address
184
-
185
- if email_address.length < 6
186
- abort "The tiniest (externally accessible) email address [a@b.cd] has 6 characters."
187
- end
188
-
189
- OpenSession::Attributes.stash "opensecret", "opensecret", "email", email_address
190
-
191
- end
192
-
193
-
194
- desc "store STORE_URL", "STORE_URL denotes the location of the backend crypt store"
195
-
196
- #
197
- # Here we define the location (the URL) of the crypt store. The crypt store will hold
198
- # the cipher text and is known as <tt>backend storage</tt>.
199
- #
200
- # The planned list of backend storage systems (each onlined with a plugin), is
201
- #
202
- # - Git (including GitHub, GitLab, BitBucket, OpenGit and private repositories.
203
- # - S3 Buckets from the Amazon Web Services (AWS) cloud.
204
- # - SSH, SCP, SFTP connected file-systems
205
- # - network storage including Samba, NFS, VMWare vSAN and
206
- # - GoogleDrive (only Windows has suitable synchronized support).
207
- #
208
- # @param store_url [String] the STORE_URL identifying a filesystem or Git or S3 storage location
209
- def store store_url
210
-
211
-
212
- if store_url.strip.length < 3
213
- abort "4 characters is the minimum domain name length."
214
- end
215
-
216
- OpenSession::Attributes.stash "opensecret", "opensecret", "store", store_url.strip
217
-
218
- ### if( File.exists?( store_url ) && !(File.directory? store_url) )
219
- ### abort "The store url path cannot be a file => #{store_url}"
220
- ### end
221
-
222
- end
223
-
224
-
225
- desc "on", "Open a session to encrypt (lock) one or more secrets"
226
-
227
- # The [on] message tells opensecret to prepare to lock one or more secrets.
228
- def on
229
-
230
- #### FileUtils.mkdir_p store_url unless File.exists? store_url
231
- #### OpenSession::Attributes.stash "opensecret", "store.id.#{store_id}", store_url
232
-
233
- end
234
-
235
-
236
- end
@@ -1,203 +0,0 @@
1
- #!/usr/bin/ruby
2
- # coding: utf-8
3
-
4
- module OpenSecret
5
-
6
- require "base64"
7
-
8
-
9
- # {OpenSecret::Cipher} is a base class that enables cipher varieties
10
- # to be plugged and played with minimal effort. This Cipher implements much
11
- # of the use case functionality - all extension classes need to do, is
12
- # to subclass and implement only the core behaviour that define its identity.
13
- #
14
- # == Double Encryption | Cipher Parent vs Cipher Child
15
- #
16
- # Double encryption first with a symmetric and then an asymmetric one fulfills
17
- # the +opensecret+ promise of making the stored ciphertext utterly worthless.
18
- #
19
- # The child ciphers implement the inner symmetric encyption whilst the parent
20
- # implements the outer asymmetric encryption algorithm.
21
- #
22
- # The process is done twice resulting in two stores that are mirrored in structure.
23
- # The front end store holds doubly encrypted keys whist the backend store holds
24
- # the doubly encrypted secrets.
25
- #
26
- # Attackers wouldn't be able to distinguish one from the other. Even if they
27
- # theoretically cracked the asymmetric encryption - they would then be faced
28
- # with a powerful symmetric encryption algorithm which could be any one of the
29
- # leading ciphers such as TwoFish or the Advanced Encryption Standard (AES).
30
- #
31
- # == Ciphers at 3 Levels
32
- #
33
- # Ciphers are implemented at three distinct levels.
34
- #
35
- # <b>Low Level Ciphers</b>
36
- #
37
- # Low level ciphers are given text to encrypt and an instantiated dictionary
38
- # in which to place the encryption parameters such as keys and initialization
39
- # vectors (iv)s.
40
- #
41
- # Some more specific ciphers can handle authorization data for example the
42
- # Galois Counter Mode (GCM) cipher.
43
- #
44
- # Low level ciphers know nothing about text IO nor reading and writing to
45
- # persistence structures like files, queues and databases.
46
- #
47
- # <b>Mid Level Ciphers</b>
48
- #
49
- # Mid level ciphers talk to the low level ciphers and bring in input and output
50
- # textual formats like OpenSecret's two-part block structures.
51
- #
52
- # Mid level ciphers still know nothing of persistence structures like files,
53
- # queues and databases.
54
- #
55
- # <b>Use Case Level Ciphers</b>
56
- #
57
- # The ciphers operating at the use case level talk to mid level ciphers. They
58
- # interact with the <b>opensecret store API</b> which brings persistence
59
- # functions such as <b>read/write</b> as well as remoting functions such as
60
- # <b>push/pull</b>.
61
- #
62
- # Use Case level ciphers interact with the latest crypt technologies due to
63
- # interface separation. Also they talk classes implementing persistence stores
64
- # allowing assets liek Git, S3, DropBox, simple files, SSH filesystems, Samba
65
- # to hold locked key and material crypts.
66
- #
67
- # Databases stores will be introduced soon allowing opensecret to plug in and
68
- # exploit database managers like Mongo, Hadoop, MySQL, Maria, and PostgreSQL.
69
- #
70
- # Plugging into DevOps orchestration platforms like Terraform, Ansible, Chef
71
- # and Puppet will soon be available. Add this with integrations to other credential
72
- # managers like HashiCorp's Vault, Credstash, Amazon KMS, Git Secrets, PGP,
73
- # LastPass, KeePass and KeePassX.
74
- #
75
- # == How to Implement a Cipher
76
- #
77
- # Extend this base class to inherit lots of +unexciting+ functionality
78
- # that essentially
79
- #
80
- # - manages the main encryption and decryption use case flow
81
- # - +concatenates+ the symmetric encryption meta data with ciphertext +after encryption+
82
- # - _splits_ and objectifies the key/value metadata plus ciphertext +before decryption+
83
- # - +handles file read/writes+ in conjunction with the store plugins
84
- # - handles +exceptions+ and +malicious input detection+ and incubation
85
- # - +_performs the asymmetric encryption_+ of the cipher's symmetrically encrypted output
86
- #
87
- # == What Behaviour Must Ciphers Implement
88
- #
89
- # Ciphers bring the cryptographic mathematics and implementation algorithms
90
- # to the table. So when at home they must implement
91
- #
92
- # - <tt>do_symmetric_encryption(plain_text)</tt> - resulting in ciphertext
93
- # - <tt>do_symmetric_decryption(ciphertext, encryption_dictionary)</tt> &raquo; plaintext
94
- #
95
- # and also set the <tt>@dictionary</tt> hash (map) of pertinent
96
- # key/value pairs including the encryption algorithm, the encryption key and
97
- # the ciphertext signature to thwart any at-rest tampering.
98
- #
99
- # That's It. Cipher children can rely on the {OpenSecret::Cipher} parent to
100
- # do the nitty gritty of file-handling plus managing stores and paths.
101
- class Cipher
102
-
103
- # Ciphers use <b>symmetric algorithms</b> to encrypt the given text, which
104
- # is then wrapped up along with the encryption key and other <b>metadata</b>
105
- # pertinent to the algorithm, they then encrypt this bundle with the
106
- # <b>public key</b> provided and return the text that can safely be stored in
107
- # a text file.
108
- #
109
- # Ciphers should never interact with the filesystem which makes them
110
- # reusable in API and remote store scenarios.
111
- #
112
- # Binary files should be converted into the base64 format before being
113
- # presented to ciphers.
114
- #
115
- # Every component in the pipeline bears the responsibility for nullifying
116
- # and rejecting malicious content.
117
- #
118
- # @param public_key [OpenSSL::PKey::RSA]
119
- # an {OpenSSL::PKey::RSA} public key. The unique selling point of
120
- # asymmetric encryption is it can be done without recourse to the heavily
121
- # protected private key. Thus the encryption process can continue with
122
- # just a public key as long as its authenticity is assured.
123
- #
124
- # @param payload_text [String]
125
- # plaintext (or base64 encoded) text to encrypt
126
- #
127
- # @return [String] doubly (symmetric and asymmetric) encrypted cipher text
128
- def self.encrypt_it public_key, payload_text
129
-
130
- crypt_data = {}
131
- crypted_payload = Base64.encode64( Aes256.do_encrypt( crypt_data, payload_text ) )
132
- unified_material = CryptIO.inner_crypt_serialize crypt_data, crypted_payload
133
-
134
- outer_crypt_key = OpenSecret::Engineer.strong_key( 128 )
135
- crypted_cryptkey = Base64.encode64( public_key.public_encrypt( outer_crypt_key ) )
136
-
137
- crypted_material = Base64.encode64(Blowfish.new.encryptor unified_material, outer_crypt_key)
138
-
139
- return CryptIO.outer_crypt_serialize( crypted_cryptkey, crypted_material )
140
-
141
- end
142
-
143
-
144
- # This method takes and <b><em>opensecret formatted</em></b> cipher-text block
145
- # generated by {self.encrypt_it} and returns the original message that has effectively
146
- # been doubly encrypted using a symmetric and asymmetric cipher. This type of
147
- # encryption is standard best practice when serializing secrets.
148
- #
149
- # opensecret cipher-text blocks <b><em>look like a two(2) part bundle</em></b>
150
- # but they are <b><em>actually a three(3) part bundle</em></b> because the second
151
- # part is in itself an amalgam of two distinct objects, serialized as text blocks.
152
- #
153
- # <b>The 3 OpenSecret Blocks</b>
154
- #
155
- # Even though the incoming text <b><em>appears to contain two (2) blocks</em></b>,
156
- # it <b><em>actually contains three (3)</em></b>.
157
- #
158
- # - a massive symmetric encryption key (locked by an asymmetric keypair)
159
- # - a dictionary denoting the algorithm and parameters used to encrypt the 3rd block
160
- # - the true message whose encryption is parametized by the dictionary (in 2nd block)
161
- #
162
- # The second and third block are only revealed by asymmetrically decrypting
163
- # the key in the first block and using it to symmetrically decrypt what appears
164
- # to be a unified second block.
165
- #
166
- # @param private_key [OpenSSL::PKey::RSA]
167
- # the <b>asymmetric private key</b> whose corresponding public key was
168
- # employed during the encryption of a super-strong 128 character symmetric
169
- # key embalmed by the first ciphertext block.
170
- #
171
- # @param os_block_text [String]
172
- # the locked cipher text is the opensecret formatted block which comes
173
- # in two main chunks. First is the <b>long strong</b> symmetric encryption
174
- # key crypted with the public key portion of the private key in the first
175
- # parameter.
176
- #
177
- # The second chunk is the symmetrically crypted text that was locked with
178
- # the encryption key revealed in the first chunk.
179
- #
180
- # @return [String]
181
- # the doubly encrypted plain text that is locked by a symmetric key and
182
- # that symmetric key itself locked using the public key portion of the
183
- # private key whose crypted form is presented in the first parameter.
184
- def self.decrypt_it private_key, os_block_text
185
-
186
- first_block = Base64.decode64( CryptIO.outer_crypt_deserialize os_block_text, true )
187
- trail_block = Base64.decode64( CryptIO.outer_crypt_deserialize os_block_text, false )
188
-
189
- decrypt_key = private_key.private_decrypt first_block
190
- inner_block = Blowfish.new.decryptor( trail_block, decrypt_key )
191
-
192
- crypt_props = Hash.new
193
- cipher_text = CryptIO.inner_crypt_deserialize( crypt_props, inner_block )
194
-
195
- return Aes256.do_decrypt( crypt_props, cipher_text )
196
-
197
- end
198
-
199
-
200
- end
201
-
202
-
203
- end