opensecret 0.0.951 → 0.0.957

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/extension/array.rb +29 -0
  3. data/lib/extension/string.rb +31 -0
  4. data/lib/factbase/facts.opensecret.io.ini +17 -9
  5. data/lib/notepad/blow.rb +108 -5
  6. data/lib/opensecret.rb +32 -6
  7. data/lib/plugins/cipher.rb +7 -7
  8. data/lib/plugins/ciphers/blowfish.rb +63 -157
  9. data/lib/plugins/usecase.rb +1 -1
  10. data/lib/plugins/usecases/init.rb +57 -116
  11. data/lib/plugins/usecases/lock.rb +178 -0
  12. data/lib/plugins/usecases/open.rb +17 -86
  13. data/lib/plugins/usecases/put.rb +137 -0
  14. data/lib/plugins/usecases/safe.rb +8 -10
  15. data/lib/session/attributes.rb +16 -11
  16. data/lib/session/dictionary.rb +191 -0
  17. data/lib/session/session.rb +80 -0
  18. data/lib/session/time.stamp.rb +89 -106
  19. data/lib/using.txt +100 -0
  20. data/lib/version.rb +1 -1
  21. metadata +6 -15
  22. data/lib/opensecret/commons/eco.faculty.rb +0 -364
  23. data/lib/opensecret/commons/eco.system.rb +0 -437
  24. data/lib/opensecret/commons/eco.systems.rb +0 -98
  25. data/lib/opensecret/factbase/hub-runtime.ini +0 -123
  26. data/lib/opensecret/factbase/known-hosts.ini +0 -75
  27. data/lib/opensecret/factbase/published.facts/blobbolicious-facts.ini +0 -553
  28. data/lib/opensecret/factbase/published.facts/credential-facts.ini +0 -40
  29. data/lib/opensecret/factbase/published.facts/infrastructure-facts.ini +0 -63
  30. data/lib/opensecret/factbase/readme.md +0 -24
  31. data/lib/opensecret/factbase/retired.facts/maven.database.ide.facts.ini +0 -127
  32. data/lib/opensecret/factbase/retired.facts/s3-upload-block-facts.ini +0 -17
  33. data/lib/opensecret/plugins.io/file/file.rb +0 -483
  34. data/lib/plugins/usecases/on.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ca35c2727f92f764b83fae65d656062b95520ad6
4
- data.tar.gz: 260748f11554e881116e6efd8c4d44c0cdb06284
3
+ metadata.gz: 9681f58d24288c4f1b13d0b83187dff72f9909f5
4
+ data.tar.gz: 850a7fc15a960497f1f6b209d7f30a9c1b26b2fd
5
5
  SHA512:
6
- metadata.gz: 10f94cba6fe468750401a38846641c9dddce2258601d981b1fb26e5b2e88c7fea27edb10264ee070d3d4920c6ada9470e0a7b4cb3178a5f5c2a07facb186db1a
7
- data.tar.gz: 35aa0ff66488c53859c245c10ba2d3aae348b56df4df90d94963241b190b8065f39f20bbfb63c119159f25488b8262f69f847fd1a3e715d3fe8df13954cbc921
6
+ metadata.gz: a3e87ecc9eaf58507d26d92ab6665a3cc4f5f0ea86a1b577b685394af57e6c8db0b2271d399eb9100beb3acf301e863ee43c17a3a7f58751626f6a5264ffbb38
7
+ data.tar.gz: 626b3bbdc2becea5b6d1dfa4eefac208a8dca4d33504598e0e7d6bef6a05629188a2cae69edb981a21db8b6fca1bc2e7af9ed1d3a421b26bfe071f061c3c9dbc
@@ -12,6 +12,35 @@
12
12
  class Array
13
13
 
14
14
 
15
+ # The returned string is a result of a union (join) of all the
16
+ # (expected) string array elements followed by the <b>deletion</b>
17
+ # of <b>all <em>non</em> alphanumeric characters</b>.
18
+ #
19
+ # <b>Disambiguating the String for Cross Platform Use</b>
20
+ #
21
+ # This behaviour is typically used for transforming text that is
22
+ # about to be signed or digested (hashed). Removing all the non
23
+ # alpha-numeric characters disambiguates the string.
24
+ #
25
+ # An example is the exclusion of line ending characters which in
26
+ # Windows are different from Linux.
27
+ #
28
+ # This disambiguation means that signing functions will return the
29
+ # same result on widely variant platfoms like Windows vs CoreOS.
30
+ #
31
+ # @return [String]
32
+ # Returns the alphanumeric union of the strings within this array.
33
+ #
34
+ # @raise [ArgumentError]
35
+ # if the array is nil or empty. Also an error will be thrown if
36
+ # the array contains objects that cannot be naturally converted
37
+ # to a string.
38
+ def alphanumeric_union
39
+ raise ArgumentError, "Cannot do alphanumeric union on an empty array." if self.empty?
40
+ return self.join.to_alphanumeric
41
+ end
42
+
43
+
15
44
  # Log the array using our logging mixin by printing every array
16
45
  # item into its own log line. In most cases we (the array) are
17
46
  # a list of strings, however if not, each item's to_string method
@@ -12,6 +12,37 @@
12
12
  class String
13
13
 
14
14
 
15
+ # Return a new string matching this one with every non alpha-numeric
16
+ # character removed. This string is left unchanged.
17
+ #
18
+ # Spaces, hyphens, underscores, periods are all removed. The only
19
+ # characters left standing belong to a set of 62 and are
20
+ #
21
+ # - a to z
22
+ # - A to Z
23
+ # - 0 to 9
24
+ #
25
+ # @return [String]
26
+ # Remove any character that is not alphanumeric, a to z, A to Z
27
+ # and 0 to 9 and return a new string leaving this one unchanged.
28
+ def to_alphanumeric
29
+ return self.delete("^A-Za-z0-9")
30
+ end
31
+
32
+
33
+ # Find the length of this string and return a string that is the
34
+ # concatenated union of this string and its integer length.
35
+ # If this string is empty a string of length one ie "0" will be
36
+ # returned.
37
+ #
38
+ # @return [String]
39
+ # Return this string with a cheeky integer tagged onto the end
40
+ # that represents the (pre-concat) length of the string.
41
+ def concat_length
42
+ return self + "#{self.length}"
43
+ end
44
+
45
+
15
46
  # Get the text [in between] this and that delimeter [exclusively].
16
47
  # Exclusively means the returned text [does not] include either of
17
48
  # the matched delimeters (although an unmatched instance of [this]
@@ -8,19 +8,27 @@ root.domain = devopswiki.co.uk
8
8
  env.var.name = SECRET_MATERIAL
9
9
  ratio = rb>> 3
10
10
  bit.key.size = rb>> 8192
11
- key.cipher = rb>> OpenSSL::Cipher.new 'AES-256-CBC'
12
- secret.keydir = rb>> OpenSession::Attributes.instance.get_value @s[:name], "safe"
13
- email.address = rb>> OpenSession::Attributes.instance.get_value @s[:name], "email"
11
+ key.cipher = rb>> OpenSSL::Cipher::AES256.new(:CBC)
12
+ secret.keydir = rb>> OpenSession::Attributes.instance.get_value @s[:name], @s[:name], "safe"
13
+ email.address = rb>> OpenSession::Attributes.instance.get_value @s[:name], @s[:name], "email"
14
14
  safe.user = rb>> File.join @s[:secret_keydir], @s[:email_address]
15
15
  master.dirname = master.keys
16
16
  master.dirpath = rb>> File.join @s[:safe_user], @s[:master_dirname]
17
- master.pub.name = master.public.key.x.os.txt
18
- master.prv.name = master.private.key.x.os.txt
19
- master.pub.key = rb>> File.join @s[:master_dirpath], @s[:master_pub_name]
17
+
18
+ master.sig.file = master.signature.os.txt
19
+ ########### -----> master.pub.name = master.public.key.os.txt
20
+ master.prv.name = master.private.key.xx.txt
21
+ master.sig.path = rb>> File.join @s[:master_dirpath], @s[:master_sig_file]
22
+ ########### -----> master.pub.key = rb>> File.join @s[:master_dirpath], @s[:master_pub_name]
20
23
  master.prv.key = rb>> File.join @s[:master_dirpath], @s[:master_prv_name]
21
24
 
22
- machine.key.x = machine.key.x
25
+ stamp.key = stamp
26
+ stamp.14 = rb>> OpenSession::Stamp.yyjjj_hhmm_sst
27
+ stamp.23 = rb>> OpenSession::Stamp.yyjjj_hhmm_ss_nanosec
28
+
29
+ machine.key.x = os.x
23
30
  separator.a = %$os$%
31
+ publickey.id = public.key
24
32
 
25
33
  repo.name = material_data
26
34
 
@@ -32,8 +40,8 @@ prompt.2 = Re-enter that Password
32
40
  open.name = session
33
41
  open.dirname = session.material
34
42
  open.dirpath = rb>> File.join @f[:global][:safe_user], @s[:open_dirname]
35
- open.idlen = 9
36
- open.keylen = 96
43
+ open.idlen = rb>> 10
44
+ open.keylen = rb>> 56
37
45
  open.idname = session.id
38
46
  open.keyname = session.key
39
47
  open.pathname = session.path
data/lib/notepad/blow.rb CHANGED
@@ -10,19 +10,75 @@
10
10
  class Trial
11
11
 
12
12
 
13
+ def self.certify
14
+
15
+ require 'openssl'
16
+ require "base64"
17
+
18
+ key = OpenSSL::PKey::RSA.new(1024)
19
+ public_key = key.public_key
20
+
21
+ subject = "/C=BE/O=Test/OU=Test/CN=Test"
22
+
23
+ cert = OpenSSL::X509::Certificate.new
24
+ cert.subject = cert.issuer = OpenSSL::X509::Name.parse(subject)
25
+ cert.not_before = Time.now
26
+ cert.not_after = Time.now + 365 * 24 * 60 * 60
27
+ cert.public_key = public_key
28
+ cert.serial = 0x0
29
+ cert.version = 2
30
+
31
+ ef = OpenSSL::X509::ExtensionFactory.new
32
+ ef.subject_certificate = cert
33
+ ef.issuer_certificate = cert
34
+ cert.extensions = [
35
+ ef.create_extension("basicConstraints","CA:TRUE", true),
36
+ ef.create_extension("subjectKeyIdentifier", "hash"),
37
+ # ef.create_extension("keyUsage", "cRLSign,keyCertSign", true),
38
+ ]
39
+ cert.add_extension ef.create_extension("authorityKeyIdentifier",
40
+ "keyid:always,issuer:always")
41
+
42
+ cert.sign key, OpenSSL::Digest::SHA1.new
43
+
44
+ puts cert.to_pem
45
+
46
+ end
47
+
48
+
49
+ ##### -----> Trial.certify
50
+
51
+
13
52
  def self.crypt
14
53
 
15
54
  require 'openssl'
16
55
  require "base64"
17
56
 
18
- key = OpenSSL::PKey::RSA.new(8192)
57
+ =begin
58
+ puts ""
59
+ puts Time.now.strftime "%9N"
60
+ puts Time.now.strftime "%12N"
61
+ puts Time.now.strftime "%15N"
62
+ puts Time.now.strftime "%18N"
63
+ puts ""
64
+ exit
65
+ =end
66
+
67
+ ## --------------------------------------------------------------------------------------------
68
+ ## --------------------------------------------------------------------------------------------
69
+
70
+ key = OpenSSL::PKey::RSA.new(2048)
19
71
 
20
72
 
21
73
  payload = "55fff4c5895bb247676c6edd2307f17c665305457b3bcfcd985c398246b8780f54e337252c5407afd4895a5e3a2415fce5b703a483da3edc88739cb7787262a19d69fb9416f900fed797c046aaec83b8e15b14edb032ed76535def8ada77108936e5442a839d4078048ca01449a6acd7315c9b7a7b8802dba0c83eb4c13e21b1051efa77a420a3ffd3cbf1fa13182933a0503f23cce95b68787081f3af33c69049657bdbf1fd30d79f108d604faad1fbee198a3e2c1b28cdddf7ebb84b6b0c1d3e9b47665bd96d7df8407e11d00e4d9275e805c7b9e61b6739802d6d87ac8283ef92a593ed53db2096cd1dc9496307f40942cc3d54a7c864ede71e0b192ce152"
22
74
 
75
+ puts ""
76
+ puts ""
77
+ puts public_key_text = key.public_key.to_pem
23
78
  puts ""
24
79
  puts "Payload size is #{payload.length}"
25
80
  puts ""
81
+ =begin
26
82
  puts ""
27
83
  puts encrypted_string = key.public_encrypt( payload, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
28
84
  puts ""
@@ -38,9 +94,55 @@ payload = "55fff4c5895bb247676c6edd2307f17c665305457b3bcfcd985c398246b8780f54e33
38
94
  puts ""
39
95
  puts encrypted_string.unpack("H*").first
40
96
  puts ""
41
- puts key.private_decrypt(encrypted_string, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
42
97
  puts ""
43
-
98
+ puts "Padding => #{OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING}"
99
+ puts ""
100
+ puts key.private_decrypt( encrypted_string, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING )
101
+ puts ""
102
+ =end
103
+ email_address = "bob@hotmail.com"
104
+ time_stamp = "5th.April.2020.20:21pm"
105
+
106
+ secured_privatekey = key.export( OpenSSL::Cipher::AES256.new(:CBC), "secret12345abcde" )
107
+
108
+
109
+ second_key = OpenSSL::PKey::RSA.new(2048)
110
+ second_public_key_text = second_key.public_key.to_pem
111
+
112
+ context_string_dirty = secured_privatekey + public_key_text + email_address + time_stamp
113
+ context_string_clean = context_string_dirty.delete("^A-Za-z0-9")
114
+ context_string_clean += context_string_clean.length.to_s
115
+ #### context_signature_str = Base64.encode64(second_key.sign OpenSSL::Digest::SHA256.new, context_string_clean)
116
+ context_signature_str = Base64.encode64(key.sign OpenSSL::Digest::SHA256.new, context_string_clean)
117
+
118
+
119
+ ## --------------------------------------------------------------------------------------------
120
+ ## --------------------------------------------------------------------------------------------
121
+
122
+ reinstated_key = OpenSSL::PKey::RSA.new "#{public_key_text}"
123
+ ### reinstated_key = OpenSSL::PKey::RSA.new "#{second_public_key_text}"
124
+ raw_signature_text = Base64.decode64(context_signature_str)
125
+ is_valid = reinstated_key.public_key.verify OpenSSL::Digest::SHA256.new, raw_signature_text, (context_string_clean)
126
+ raise ArgumentError, "Keys not validated" unless is_valid
127
+
128
+ ## --------------------------------------------------------------------------------------------
129
+ ## --------------------------------------------------------------------------------------------
130
+
131
+ puts "======================================================================================"
132
+ puts "======================================================================================"
133
+ puts context_string_dirty
134
+ puts "======================================================================================"
135
+ puts "======================================================================================"
136
+ puts context_string_clean
137
+ puts "======================================================================================"
138
+ puts "======================================================================================"
139
+ puts context_signature_str
140
+ puts "======================================================================================"
141
+ puts "======================================================================================"
142
+ puts "Keys Are Valid => #{is_valid}"
143
+ puts "======================================================================================"
144
+ puts "======================================================================================"
145
+ puts ""
44
146
 
45
147
  end
46
148
 
@@ -55,8 +157,9 @@ HNkUjWaFoI5dPTRUUymyf7uKMaXFhiIZaOq+ZYj4TWPN92qv6ANTd3pRvVa3
55
157
  S+aQSOX7q3FkKIOc5yfWLushGAMSwidgH1kzLvocCf+SSWH5BY3zTb7NAGjW
56
158
  =end
57
159
 
58
- ### Trial.crypt
59
- ### exit
160
+ # -------->
161
+ # --------> Trial.crypt
162
+ # -------->
60
163
 
61
164
  def try
62
165
 
data/lib/opensecret.rb CHANGED
@@ -32,7 +32,9 @@ OpenSession::RecursivelyRequire.now( __FILE__ )
32
32
  #
33
33
  class CliInterpreter < Thor
34
34
 
35
- log.info(x) {"Wake up loggers."}
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}]." }
36
38
 
37
39
  #
38
40
  # This class option allows every CLI call the option to include
@@ -55,12 +57,36 @@ class CliInterpreter < Thor
55
57
 
56
58
 
57
59
  # Description of the open "wake-up" call.
58
- desc "open", "open up a conduit for adding, subtracting and swapping secrets for a future commit."
60
+ desc "open CONTEXT_PATH", "CONTEXT_PATH context path to the family of secrets to be created."
59
61
 
60
62
  # Open up a conduit from which we can add, subtract, update and list secrets
61
63
  # before they are committed (and pushed) into permanent locked storage.
62
- def open
63
- OpenSecret::Open.new.flow_of_events
64
+ #
65
+ # @param context_path [String] the path to USB key for storing encrypted keys
66
+ def open context_path
67
+
68
+ open_uc = OpenSecret::Open.new
69
+ open_uc.context_path = context_path
70
+ open_uc.flow_of_events
71
+
72
+ end
73
+
74
+
75
+ # Description of the put secret command.
76
+ desc "put <secret_id> <secret_value>", "put secret like login/username into opened context."
77
+
78
+ # Put a secret with an id like login/username and a value like joebloggs into the
79
+ # context (eg work/laptop) that was opened with the open command.
80
+ #
81
+ # @param secret_id [String] the id of the secret to put into the opened context
82
+ # @param secret_value [String] the value of the secret to put into the opened context
83
+ def put secret_id, secret_value
84
+
85
+ put_uc = OpenSecret::Put.new
86
+ put_uc.secret_id = secret_id
87
+ put_uc.secret_value = secret_value
88
+ put_uc.flow_of_events
89
+
64
90
  end
65
91
 
66
92
 
@@ -120,7 +146,7 @@ class CliInterpreter < Thor
120
146
  abort "The tiniest (externally accessible) email address [a@b.cd] has 6 characters."
121
147
  end
122
148
 
123
- OpenSession::Attributes.stash "opensecret", "email", email_address
149
+ OpenSession::Attributes.stash "opensecret", "opensecret", "email", email_address
124
150
 
125
151
  end
126
152
 
@@ -147,7 +173,7 @@ class CliInterpreter < Thor
147
173
  abort "4 characters is the minimum domain name length."
148
174
  end
149
175
 
150
- OpenSession::Attributes.stash "opensecret", "store", store_url.strip
176
+ OpenSession::Attributes.stash "opensecret", "opensecret", "store", store_url.strip
151
177
 
152
178
  ### if( File.exists?( store_url ) && !(File.directory? store_url) )
153
179
  ### abort "The store url path cannot be a file => #{store_url}"
@@ -6,7 +6,7 @@ module OpenSecret
6
6
  require "base64"
7
7
 
8
8
 
9
- # An {OpenSecret::Cipher} is a base class that enables cipher varieties
9
+ # {OpenSecret::Cipher} is a base class that enables cipher varieties
10
10
  # to be plugged and played with minimal effort. This Cipher implements much
11
11
  # of the use case functionality - all extension classes need to do, is
12
12
  # to subclass and implement only the core behaviour that define its identity.
@@ -28,6 +28,7 @@ module OpenSecret
28
28
  # with a powerful symmetric encryption algorithm which could be any one of the
29
29
  # leading ciphers such as TwoFish or the Advanced Encryption Standard (AES).
30
30
  #
31
+ #
31
32
  # == How to Implement a Cipher
32
33
  #
33
34
  # Extend this base class to inherit lots of +unexciting+ functionality
@@ -40,9 +41,8 @@ module OpenSecret
40
41
  # - handles +exceptions+ and +malicious input detection+ and incubation
41
42
  # - +_performs the asymmetric encryption_+ of the cipher's symmetrically encrypted output
42
43
  #
43
- # -------------------------------------
44
- # What Behaviour Must Ciphers Implement
45
- # -------------------------------------
44
+ #
45
+ # == What Behaviour Must Ciphers Implement
46
46
  #
47
47
  # Ciphers bring the cryptographic mathematics and implementation algorithms
48
48
  # to the table. So when at home they must implement
@@ -62,7 +62,7 @@ module OpenSecret
62
62
  # of 8 (or 16) and a common +right pad with spaces+ strategy is employed
63
63
  # as a workaround. opensecret does it diferently.
64
64
  #
65
- # == No Space Padding? | Why Not?
65
+ # == Why isn't Space Padding Used?
66
66
  #
67
67
  # If opensecret padded plaintext (ending in one or more spaces) with
68
68
  # spaces, the decrypt phase (after right stripping spaces) would return
@@ -87,7 +87,7 @@ module OpenSecret
87
87
 
88
88
  # An unusual string that glues together an encryption dictionary and
89
89
  # a chunk of base64 encoded and encrypted ciphertext.
90
- # The string must be unusual enough to ensure it dos not occur within
90
+ # The string must be unusual enough to ensure it does not occur within
91
91
  # the dictionary metadata keys or values.
92
92
  INNER_GLUE_STRING = "\n<-|@| < || opensecret inner crypt material axis || > |@|->\n\n"
93
93
 
@@ -155,7 +155,7 @@ module OpenSecret
155
155
  unified_material = unify_hash_and_text crypted_payload
156
156
  blowfish_cryptor = Blowfish.new
157
157
  outer_crypt_key = OpenSecret::Engineer.strong_key( 128 )
158
- crypted_material = blowfish_cryptor.do_encrypt_with_key unified_material, outer_crypt_key
158
+ crypted_material = blowfish_cryptor.encryptor unified_material, outer_crypt_key
159
159
  crypted_cryptkey = do_asymmetric_encryption public_key_text, outer_crypt_key
160
160
  locked_up_string = unify_text_and_text crypted_cryptkey, crypted_material
161
161
 
@@ -23,45 +23,38 @@ module OpenSecret
23
23
  BLOWFISH_BLOCK_LEN = 8
24
24
 
25
25
 
26
- # This method provides the Blowfish algorithm but we reserve the
27
- # right to enforce upon it an encryption key of our choosing.
26
+ # Encrypt the (plain) text parameter using the symmetric encryption key
27
+ # specified in the second parameter and return the base64 encoded
28
+ # representation of the cipher text.
28
29
  #
29
- # The key length need not be a multiple of 8 - however it is advisable
30
- # to use {Digest::SHA256.digest} to produce a strong 32 character key.
30
+ # Blowfish is a block cipher meaning it needs both the key and the plain
31
+ # text inputted to conform to a divisible block length.
31
32
  #
32
- # == Multiples of 8 | Plain Text Length
33
+ # Don't worry about this block length requirement as this encrption method
34
+ # takes care of it and its sister method {self.decryptor} will also perform
35
+ # the correct reversal activities to give you back the original plain text.
33
36
  #
34
- # Blowfish constrains plain text lengths to multiples of 8 but we
35
- # do NOT walk the common +space padding+ road.
37
+ # {Base64.encode64} facilitates the ciphertext encoding returning text that
38
+ # is safe to write to a file.
36
39
  #
37
- # == No Space Padding? | Why Not?
40
+ # @param plain_text [String]
41
+ # This parameter should be the non-nil text to encrypt using Blowfish.
42
+ # Before encryption the text will be padded using a text string from
43
+ # the {OpenSecret::Cipher::TEXT_PADDER} constant until it results in
44
+ # a string with the required block length.
38
45
  #
39
- # Many ciphers (like Blowfish) constrains plain text lengths to multiples
40
- # of 8 (or 16) and a common +right pad with spaces+ strategy is employed
41
- # as a workaround.
46
+ # @param encryption_key [String]
47
+ # send a long strong unencoded key which does not have to be a multiple of
48
+ # eight even though the algorithm demands it. Before the encryption this key
49
+ # will be passed through a digest using behaviour from {Digest::SHA256.digest}
42
50
  #
43
- # If opensecret padded plaintext (ending in one or more spaces) with
44
- # spaces, the decrypt phase (after right stripping spaces) would return
45
- # plain text string +shorter than the original+.
46
- #
47
- # == So How is Padding Done?
48
- #
49
- # Instead of single space padding - opensecret uses an unlikely 7 character
50
- # delimiter which is repeated until the multiple is reached.
51
- #
52
- # Please see {OpenSecret::Cipher::PLAIN_TEXT_DELIMITER} for the definition
53
- # of the constant delimiter.
54
- #
55
- # == Key Length Error
56
- #
57
- # Short keys receive a <tt>key length too short</tt> error from the
58
- # {OpenSSL::Cipher} class namely {OpenSSL::Cipher::CipherError}.
59
- #
60
- # @param plain_text [String] the text to encrypt using Blowfish
61
- # @param encryption_key [String] strong unencoded (32 character key)
51
+ # This behaviour returns a key whose length is a multiple of eight.
62
52
  #
63
53
  # @return [String] base64 representation of blowfish crypted ciphertext
64
- def do_encrypt_with_key plain_text, encryption_key
54
+ #
55
+ # @raise [OpenSSL::Cipher::CipherError]
56
+ # An (encryption) <tt>key length too short</tt> error is raised for short keys.
57
+ def encryptor plain_text, encryption_key
65
58
 
66
59
  shortkey_msg = "The #{encryption_key.length} character encryption key is too short."
67
60
  raise ArgumentError, shortkey_msg unless encryption_key.length > 8
@@ -73,148 +66,61 @@ module OpenSecret
73
66
 
74
67
  blowfish_encryptor = OpenSSL::Cipher.new(OpenSecret::Blowfish::BLOWFISH_CIPHER_ID).encrypt
75
68
  blowfish_encryptor.key = raw_stretched_key
69
+ encrypted_lines = blowfish_encryptor.update(block_txt) << blowfish_encryptor.final
76
70
 
77
- return Base64.encode64( blowfish_encryptor.update(block_txt) << blowfish_encryptor.final )
71
+ return Base64.encode64( encrypted_lines ).chomp
78
72
 
79
73
  end
80
74
 
81
75
 
82
- =begin
83
- puts "Plain Text => #{sentence}"
84
- puts "Plain Text Length => #{sentence.length}"
85
- puts "Multiple 8 Text => [#{multiple8}]"
86
- puts "Multiple 8 Length => [#{multiple8.length}]"
87
- puts "Encrypted Text Length => #{encrypted_text.length}"
88
- ######### puts "Encrypted Text => #{encrypted_text}"
89
- puts "Base64 Encrypted Text => #{base64_encrypted_text}"
90
-
91
- dbf = OpenSSL::Cipher.new("BF-ECB").decrypt
92
- dbf.key = the_key
93
- debase64_text = Base64.decode64( base64_encrypted_text )
94
- decrypted_text = dbf.update(debase64_text) << dbf.final
95
-
96
- puts "Decrypted Text => #{decrypted_text}"
97
- =end
98
-
99
-
100
-
101
-
102
- # Use the AES 256 bit block cipher and a robust strong random key plus
103
- # initialization vector (IV) to symmetrically encrypt the plain text.
76
+ # Decrypt the cipher text parameter using the symmetric decryption key
77
+ # specified in the second parameter. The cipher text is expected to be
78
+ # base64 encoded as per our sister method {self.encryptor}.
104
79
  #
105
- # Add these key/value pairs to @encryption_dictionary instance map.
80
+ # Its okay to use a bespoke encryptor - just ensure you encode the result
81
+ # and override the padding constant.
106
82
  #
107
- # - <tt>symmetric.cipher</tt> - the algorithm used to encrypt and decrypt
108
- # - <tt>encryption.key</tt> - hex encoded key for encrypting and decrypting
109
- # - <tt>initialize.vector</tt> - the initialization vector known as a IV (four)
83
+ # Blowfish is a block cipher meaning it needs both the key and the plain
84
+ # text inputted to conform to a divisible block length.
110
85
  #
111
- # @param plain_text [String] the plain (or base64 encoded) text to encrypt
112
- # @return [String] the symmetrically encrypted cipher text
113
- def do_symmetric_encryption plain_text
114
-
115
- @cipher_name = "aes-256-cbc"
116
-
117
- crypt_cipher = OpenSSL::Cipher.new @cipher_name
118
- crypt_cipher.encrypt( plain_text )
119
-
120
- @encryption_dictionary = {
121
- @@symmetric_cipher_keyname => @cipher_name,
122
- @@encryption_key_keyname => crypt_cipher.random_key.unpack("H*").first,
123
- @@initialize_vector_keyname => crypt_cipher.random_iv.unpack("H*").first
124
- }
125
-
126
- Base64.encode64( crypt_cipher.update + crypt_cipher.final )
127
-
128
- end
129
-
130
-
131
- # Use the AES 256 bit block cipher together with the encryption key
132
- # and initialization vector (iv) sitting in the encryption_dictionary,
133
- # to symmetrically decrypt the parameter cipher text.
86
+ # Don't worry about this block length requirement as this decrption method
87
+ # takes care of the reversing the activities carried out by {self.encryptor}.
134
88
  #
135
- # == Pre-Condition | Encryption Dictionary
89
+ # @param cipher_text [String]
90
+ # This incoming cipher text should be encoded using {Base64.encode64}
91
+ # and it will be +chomped and stripped upon receipt+ followed by
92
+ # decryption using the Blowfish algorithm.
136
93
  #
137
- # This method requires the <tt>@encryption_dictionary</tt> instance
138
- # variable to have been set and to contain (amongst others)
94
+ # @param decryption_key [String]
95
+ # Send the same key that was used during the encryption phase. The encryption
96
+ # phase passed the key through the {Digest::SHA256.digest} digest so here
97
+ # the decryption does the exact same thing.
139
98
  #
140
- # - the <tt>encryption.key</tt> - hex encoded key for encrypting and decrypting
141
- # - and <tt>initialize.vector</tt> - the initialization vector known as a IV (four)
99
+ # The digest processing guarantees a symmetric key whose length conforms to
100
+ # the multiple of eight block length requirement.
142
101
  #
143
- # @param cipher_text [String] the base64 encoded cipher text to decrypt
144
- # @return [String] decrypted plain text from symmetric key and cipher text
145
- def do_symmetric_decryption cipher_text
146
-
147
- abort "Implement AES 256 decryption in aes-256"
102
+ # @return [String]
103
+ # After decoding and decryption the plain text string will still be padded,
104
+ # +but not with spaces+. The unlikely to occur padding string constant used
105
+ # is the {OpenSecret::Cipher::TEXT_PADDER}.
106
+ #
107
+ # If the plaintext ended with spaces these would be preserved. After padder
108
+ # removal any trailing spaces will be preserved in the returned plain text.
109
+ #
110
+ def decryptor cipher_text, decryption_key
148
111
 
149
- end
112
+ decoded_text = Base64.decode64(cipher_text.chomp.strip)
113
+ digested_key = Digest::SHA256.digest decryption_key
150
114
 
115
+ decrypt_tool = OpenSSL::Cipher.new(OpenSecret::Blowfish::BLOWFISH_CIPHER_ID).decrypt
116
+ decrypt_tool.key = digested_key
151
117
 
118
+ padded_plaintxt = decrypt_tool.update(decoded_text) << decrypt_tool.final
119
+ pad_begin_index = padded_plaintxt.index OpenSecret::Cipher::TEXT_PADDER
120
+ return padded_plaintxt if pad_begin_index.nil?
121
+ return padded_plaintxt[ 0 .. (pad_begin_index-1) ]
152
122
 
153
- =begin
154
- encode_cipher = OpenSSL::Cipher.new('aes-256-cbc')
155
- encode_cipher.encrypt # We are encrypting
156
- key = encode_cipher.random_key
157
- iv = encode_cipher.random_iv
158
- hex_key = key.unpack("H*").first
159
- hex_iv = iv.unpack("H*").first
160
-
161
- line1 = "1>> This is secret number one over here with at @ and squiggle~ and round brakets().\n"
162
- line2 = "2>> secret number two with colon and semi :; angular <> qmarks ??.\n"
163
- line3 = "3>> secret number 3 fwd slash / and backslash twice \\ and pipe || and excla !!\n"
164
- line4 = "4>> secret 4 with pound ££ dollar $$ percent %% hat ^^ ampr && stars **\n"
165
- line5 = "5>> secret 5 with hyphens - and underscore __ and plus ++ and equal == and sqBs [[]].\n"
166
- line6 = "6>> secret 6 with double quote \"from here to here\" and \' single quotes\'.\n"
167
- line7 = "7>> secret 7 with periods .... and hashes #####\n"
168
-
169
- crypt_text = ""
170
- crypt_text += encode_cipher.update line1
171
- crypt_text += encode_cipher.update line2
172
- crypt_text += encode_cipher.update line3
173
- crypt_text += encode_cipher.update line4
174
- crypt_text += encode_cipher.update line5
175
- crypt_text += encode_cipher.update line6
176
- crypt_text += encode_cipher.update line7
177
- crypt_text += encode_cipher.final
178
- coded_crypt_text = Base64.encode64(crypt_text)
179
-
180
- puts ""
181
- puts "The key is #{hex_key}"
182
- puts "The IV is #{hex_iv}"
183
- puts "========================"
184
- puts "The Cipher Text is Below"
185
- puts "========================"
186
- puts coded_crypt_text
187
- puts "========================"
188
- puts crypt_text
189
- puts "========================"
190
- puts "========================"
191
- puts "========================"
192
- puts line1 + line2 + line3 + line4 + line5 + line6 + line7
193
- puts "========================"
194
- puts "========================"
195
- puts "========================"
196
- puts ""
197
- puts ""
198
-
199
- unencoded_crypt_text = Base64.decode64(coded_crypt_text)
200
- decode_cipher = OpenSSL::Cipher.new('aes-256-cbc')
201
-
202
- decode_cipher.decrypt
203
- decode_cipher.key = [hex_key].pack("H*")
204
- decode_cipher.iv = [hex_iv].pack("H*")
205
- first_part = decode_cipher.update( Base64.decode64(coded_crypt_text) )
206
- second_part = ""
207
- second_part << decode_cipher.final
208
-
209
- puts "========================"
210
- puts "Decrypted Text is Below"
211
- puts "========================"
212
- puts first_part
213
- puts "========================"
214
- puts second_part
215
- puts "========================"
216
- puts ""
217
- =end
123
+ end
218
124
 
219
125
 
220
126
  end