opensecret 0.0.951 → 0.0.957
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|