opensecret 0.0.951 → 0.0.957
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/extension/array.rb +29 -0
- data/lib/extension/string.rb +31 -0
- data/lib/factbase/facts.opensecret.io.ini +17 -9
- data/lib/notepad/blow.rb +108 -5
- data/lib/opensecret.rb +32 -6
- data/lib/plugins/cipher.rb +7 -7
- data/lib/plugins/ciphers/blowfish.rb +63 -157
- data/lib/plugins/usecase.rb +1 -1
- data/lib/plugins/usecases/init.rb +57 -116
- data/lib/plugins/usecases/lock.rb +178 -0
- data/lib/plugins/usecases/open.rb +17 -86
- data/lib/plugins/usecases/put.rb +137 -0
- data/lib/plugins/usecases/safe.rb +8 -10
- data/lib/session/attributes.rb +16 -11
- data/lib/session/dictionary.rb +191 -0
- data/lib/session/session.rb +80 -0
- data/lib/session/time.stamp.rb +89 -106
- data/lib/using.txt +100 -0
- data/lib/version.rb +1 -1
- metadata +6 -15
- data/lib/opensecret/commons/eco.faculty.rb +0 -364
- data/lib/opensecret/commons/eco.system.rb +0 -437
- data/lib/opensecret/commons/eco.systems.rb +0 -98
- data/lib/opensecret/factbase/hub-runtime.ini +0 -123
- data/lib/opensecret/factbase/known-hosts.ini +0 -75
- data/lib/opensecret/factbase/published.facts/blobbolicious-facts.ini +0 -553
- data/lib/opensecret/factbase/published.facts/credential-facts.ini +0 -40
- data/lib/opensecret/factbase/published.facts/infrastructure-facts.ini +0 -63
- data/lib/opensecret/factbase/readme.md +0 -24
- data/lib/opensecret/factbase/retired.facts/maven.database.ide.facts.ini +0 -127
- data/lib/opensecret/factbase/retired.facts/s3-upload-block-facts.ini +0 -17
- data/lib/opensecret/plugins.io/file/file.rb +0 -483
- data/lib/plugins/usecases/on.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9681f58d24288c4f1b13d0b83187dff72f9909f5
|
4
|
+
data.tar.gz: 850a7fc15a960497f1f6b209d7f30a9c1b26b2fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3e87ecc9eaf58507d26d92ab6665a3cc4f5f0ea86a1b577b685394af57e6c8db0b2271d399eb9100beb3acf301e863ee43c17a3a7f58751626f6a5264ffbb38
|
7
|
+
data.tar.gz: 626b3bbdc2becea5b6d1dfa4eefac208a8dca4d33504598e0e7d6bef6a05629188a2cae69edb981a21db8b6fca1bc2e7af9ed1d3a421b26bfe071f061c3c9dbc
|
data/lib/extension/array.rb
CHANGED
@@ -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
|
data/lib/extension/string.rb
CHANGED
@@ -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
|
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
|
-
|
18
|
-
master.
|
19
|
-
master.pub.
|
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
|
-
|
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 =
|
36
|
-
open.keylen =
|
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
|
-
|
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
|
-
|
59
|
-
|
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
|
-
|
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", "
|
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
|
-
|
63
|
-
|
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}"
|
data/lib/plugins/cipher.rb
CHANGED
@@ -6,7 +6,7 @@ module OpenSecret
|
|
6
6
|
require "base64"
|
7
7
|
|
8
8
|
|
9
|
-
#
|
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
|
-
# ==
|
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
|
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.
|
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
|
-
#
|
27
|
-
#
|
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
|
-
#
|
30
|
-
# to
|
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
|
-
#
|
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
|
-
#
|
35
|
-
#
|
37
|
+
# {Base64.encode64} facilitates the ciphertext encoding returning text that
|
38
|
+
# is safe to write to a file.
|
36
39
|
#
|
37
|
-
#
|
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
|
-
#
|
40
|
-
#
|
41
|
-
#
|
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
|
-
#
|
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
|
-
|
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(
|
71
|
+
return Base64.encode64( encrypted_lines ).chomp
|
78
72
|
|
79
73
|
end
|
80
74
|
|
81
75
|
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
#
|
80
|
+
# Its okay to use a bespoke encryptor - just ensure you encode the result
|
81
|
+
# and override the padding constant.
|
106
82
|
#
|
107
|
-
#
|
108
|
-
#
|
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
|
-
#
|
112
|
-
#
|
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
|
-
#
|
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
|
-
#
|
138
|
-
#
|
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
|
-
#
|
141
|
-
#
|
99
|
+
# The digest processing guarantees a symmetric key whose length conforms to
|
100
|
+
# the multiple of eight block length requirement.
|
142
101
|
#
|
143
|
-
# @
|
144
|
-
#
|
145
|
-
|
146
|
-
|
147
|
-
|
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
|
-
|
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
|
-
|
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
|