opensecret 0.0.957 → 0.0.959
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/factbase/facts.opensecret.io.ini +0 -2
- data/lib/notepad/blow.rb +16 -4
- data/lib/opensecret.rb +9 -0
- data/lib/plugins/cipher.rb +25 -23
- data/lib/plugins/ciphers/aes-256.rb +16 -12
- data/lib/plugins/ciphers/blowfish.rb +7 -10
- data/lib/plugins/envelope.rb +116 -0
- data/lib/plugins/secrets.uc.rb +50 -0
- data/lib/plugins/usecases/init.rb +9 -7
- data/lib/plugins/usecases/lock.rb +77 -93
- data/lib/plugins/usecases/open.rb +1 -1
- data/lib/plugins/usecases/put.rb +18 -18
- data/lib/plugins/usecases/safe.rb +1 -1
- data/lib/session/dictionary.rb +5 -5
- data/lib/using.txt +2 -0
- data/lib/version.rb +1 -1
- data/opensecret.gemspec +2 -2
- metadata +4 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ced0dc3656c2318960d7c747cd24e8eacb189224
|
4
|
+
data.tar.gz: dcca8f54f93da21ef00d6fbbdba0e8975ac7ddca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 219cd0fe00537778fb1364d6a214856bea94be3196e399177bbcbd912ffab087dda9bb01fb906ad1fd7f078f15f27b9d1c24d82894fb1790f592e838487aa10e
|
7
|
+
data.tar.gz: 2ba3881642795bf29de00431cbd7926b664b3d0a0031f18eb17b2dc5d79d282f8df7ccb32559720e614be52229e2ec8eb59b924282b88596960ab10fa52bc8cf
|
@@ -16,10 +16,8 @@ master.dirname = master.keys
|
|
16
16
|
master.dirpath = rb>> File.join @s[:safe_user], @s[:master_dirname]
|
17
17
|
|
18
18
|
master.sig.file = master.signature.os.txt
|
19
|
-
########### -----> master.pub.name = master.public.key.os.txt
|
20
19
|
master.prv.name = master.private.key.xx.txt
|
21
20
|
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]
|
23
21
|
master.prv.key = rb>> File.join @s[:master_dirpath], @s[:master_prv_name]
|
24
22
|
|
25
23
|
stamp.key = stamp
|
data/lib/notepad/blow.rb
CHANGED
@@ -9,6 +9,18 @@
|
|
9
9
|
|
10
10
|
class Trial
|
11
11
|
|
12
|
+
def self.ciphername
|
13
|
+
|
14
|
+
require 'openssl'
|
15
|
+
require "base64"
|
16
|
+
|
17
|
+
crypt_cipher = OpenSSL::Cipher::AES256.new(:CBC)
|
18
|
+
puts "Cipher Name => #{crypt_cipher.class.name}"
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
Trial.ciphername
|
23
|
+
|
12
24
|
|
13
25
|
def self.certify
|
14
26
|
|
@@ -82,7 +94,7 @@ payload = "55fff4c5895bb247676c6edd2307f17c665305457b3bcfcd985c398246b8780f54e33
|
|
82
94
|
puts ""
|
83
95
|
puts encrypted_string = key.public_encrypt( payload, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
|
84
96
|
puts ""
|
85
|
-
puts base64text = Base64.
|
97
|
+
puts base64text = Base64.urlsafe_encode64(encrypted_string)
|
86
98
|
puts ""
|
87
99
|
puts signature = key.sign(OpenSSL::Digest::SHA256.new, payload )
|
88
100
|
puts ""
|
@@ -112,8 +124,8 @@ payload = "55fff4c5895bb247676c6edd2307f17c665305457b3bcfcd985c398246b8780f54e33
|
|
112
124
|
context_string_dirty = secured_privatekey + public_key_text + email_address + time_stamp
|
113
125
|
context_string_clean = context_string_dirty.delete("^A-Za-z0-9")
|
114
126
|
context_string_clean += context_string_clean.length.to_s
|
115
|
-
#### context_signature_str = Base64.
|
116
|
-
context_signature_str = Base64.
|
127
|
+
#### context_signature_str = Base64.urlsafe_encode64(second_key.sign OpenSSL::Digest::SHA256.new, context_string_clean)
|
128
|
+
context_signature_str = Base64.urlsafe_encode64(key.sign OpenSSL::Digest::SHA256.new, context_string_clean)
|
117
129
|
|
118
130
|
|
119
131
|
## --------------------------------------------------------------------------------------------
|
@@ -121,7 +133,7 @@ payload = "55fff4c5895bb247676c6edd2307f17c665305457b3bcfcd985c398246b8780f54e33
|
|
121
133
|
|
122
134
|
reinstated_key = OpenSSL::PKey::RSA.new "#{public_key_text}"
|
123
135
|
### reinstated_key = OpenSSL::PKey::RSA.new "#{second_public_key_text}"
|
124
|
-
raw_signature_text = Base64.
|
136
|
+
raw_signature_text = Base64.urlsafe_decode64(context_signature_str)
|
125
137
|
is_valid = reinstated_key.public_key.verify OpenSSL::Digest::SHA256.new, raw_signature_text, (context_string_clean)
|
126
138
|
raise ArgumentError, "Keys not validated" unless is_valid
|
127
139
|
|
data/lib/opensecret.rb
CHANGED
@@ -56,6 +56,15 @@ class CliInterpreter < Thor
|
|
56
56
|
end
|
57
57
|
|
58
58
|
|
59
|
+
# Description of the lock use case command line call.
|
60
|
+
desc "lock", "Lock away the (secret stuffed) envelope into key and crypt stores."
|
61
|
+
|
62
|
+
# Lock away the (secret stuffed) envelope into key and crypt stores.
|
63
|
+
def lock
|
64
|
+
OpenSecret::Lock.new.flow_of_events
|
65
|
+
end
|
66
|
+
|
67
|
+
|
59
68
|
# Description of the open "wake-up" call.
|
60
69
|
desc "open CONTEXT_PATH", "CONTEXT_PATH context path to the family of secrets to be created."
|
61
70
|
|
data/lib/plugins/cipher.rb
CHANGED
@@ -28,7 +28,6 @@ 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
|
-
#
|
32
31
|
# == How to Implement a Cipher
|
33
32
|
#
|
34
33
|
# Extend this base class to inherit lots of +unexciting+ functionality
|
@@ -100,10 +99,23 @@ module OpenSecret
|
|
100
99
|
# Text header for key-value pairs hash map that will be serialized.
|
101
100
|
DICTIONARY = "dictionary"
|
102
101
|
|
102
|
+
# Name for the class of cipher employed.
|
103
|
+
DICT_CIPHER_NAME = "cipher.class"
|
104
|
+
|
105
|
+
# Name for the {Base64} encoded symmetric (lock/unlock) crypt key.
|
106
|
+
DICT_CRYPT_KEY = "encryption.key"
|
107
|
+
|
108
|
+
# Name for the {Base64} encoded plain text digest.
|
109
|
+
DICT_PLAINTEXT_DIGEST = "plaintext.digest"
|
110
|
+
|
111
|
+
# Name for the {Base64} encoded crypt material digest.
|
112
|
+
DICT_MATERIAL_DIGEST = "cipher.digest"
|
103
113
|
|
104
|
-
|
105
|
-
|
106
|
-
|
114
|
+
# Name for the plain text initialization vector (iv).
|
115
|
+
DICT_INIT_VECTOR = "crypt.init.vector"
|
116
|
+
|
117
|
+
# Name for the {Base64} encoded crypted cipher text.
|
118
|
+
DICT_CIPHER_TEXT = "cipher.text"
|
107
119
|
|
108
120
|
|
109
121
|
# The cipher constructor instantiates the encryption dictionary which
|
@@ -131,40 +143,30 @@ module OpenSecret
|
|
131
143
|
# and rejecting malicious content.
|
132
144
|
#
|
133
145
|
# @param public_key_text [String] textual portion of an {OpenSSL::PKey::RSA}
|
134
|
-
# public key
|
135
|
-
#
|
146
|
+
# public key. There is no need for an asymmetric encryption agent to know
|
147
|
+
# the asymmetic private key.
|
136
148
|
#
|
137
149
|
# @param payload_text [String] plaintext (or base64 encoded) text to encrypt
|
138
|
-
# @param payload_signature [String] signature of payload verifiable with public key
|
139
150
|
#
|
140
151
|
# @return [String] doubly (symmetric and asymmetric) encrypted cipher text
|
141
|
-
def encrypt_it public_key_text, payload_text
|
142
|
-
|
143
|
-
asymmetric_key = OpenSSL::PKey::RSA.new public_key_text
|
152
|
+
def encrypt_it public_key_text, payload_text
|
144
153
|
|
145
|
-
signature_valid = asymmetric_key.verify(
|
146
|
-
OpenSSL::Digest::SHA256.new,
|
147
|
-
payload_signature,
|
148
|
-
payload_text
|
149
|
-
)
|
150
|
-
|
151
|
-
raise ArgumentError, "Payload not verified by the signature." unless signature_valid
|
152
|
-
@dictionary[@@payload_signature_keyname] = payload_signature.to_hex
|
153
154
|
crypted_payload = do_symmetric_encryption payload_text
|
154
155
|
|
156
|
+
######### puts JSON.pretty_generate(@dictionary)
|
157
|
+
|
155
158
|
unified_material = unify_hash_and_text crypted_payload
|
156
|
-
blowfish_cryptor = Blowfish.new
|
157
159
|
outer_crypt_key = OpenSecret::Engineer.strong_key( 128 )
|
158
|
-
crypted_material = blowfish_cryptor.encryptor unified_material, outer_crypt_key
|
159
160
|
crypted_cryptkey = do_asymmetric_encryption public_key_text, outer_crypt_key
|
160
|
-
|
161
|
+
crypted_material = Base64.encode64(Blowfish.new.encryptor unified_material, outer_crypt_key)
|
162
|
+
locked_ciphertxt = unify_text_and_text crypted_cryptkey, crypted_material
|
161
163
|
|
162
|
-
return
|
164
|
+
return locked_ciphertxt
|
163
165
|
|
164
166
|
end
|
165
167
|
|
166
168
|
|
167
|
-
#
|
169
|
+
# This method takes the textual public key lacking the private key portion
|
168
170
|
# as it is not needed, and encrypts the secret text with it.
|
169
171
|
# It returns a Base64 encoded version of they encrypted text.
|
170
172
|
#
|
@@ -7,7 +7,7 @@ module OpenSecret
|
|
7
7
|
# {OpenSecret::Cipher} base class in order to implement plug and play
|
8
8
|
# symmetric encryption.
|
9
9
|
#
|
10
|
-
# == Aes256 Symmetric Encrypt/Decrypt
|
10
|
+
# == Aes256 Symmetric Encrypt/Decrypt
|
11
11
|
#
|
12
12
|
# To facilitate decryption - this cipher produces a key/value pair
|
13
13
|
# dictionary which will be stored along with the ciphertext itself.
|
@@ -51,16 +51,20 @@ module OpenSecret
|
|
51
51
|
# @return [String] the symmetrically encrypted cipher text
|
52
52
|
def do_symmetric_encryption plain_text
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
crypt_cipher = OpenSSL::Cipher.new @cipher_name
|
54
|
+
crypt_cipher = OpenSSL::Cipher::AES256.new(:CBC)
|
57
55
|
crypt_cipher.encrypt
|
58
56
|
|
59
|
-
@dictionary[
|
60
|
-
@dictionary[
|
61
|
-
@dictionary[
|
57
|
+
@dictionary[DICT_CIPHER_NAME] = crypt_cipher.class.name
|
58
|
+
@dictionary[DICT_CRYPT_KEY] = Base64.urlsafe_encode64 crypt_cipher.random_key
|
59
|
+
@dictionary[DICT_INIT_VECTOR] = Base64.urlsafe_encode64 crypt_cipher.random_iv
|
60
|
+
@dictionary[DICT_PLAINTEXT_DIGEST] = Base64.urlsafe_encode64(Digest::SHA256.digest(plain_text))
|
61
|
+
|
62
|
+
cipher_text = crypt_cipher.update( plain_text ) + crypt_cipher.final
|
63
|
+
|
64
|
+
@dictionary[DICT_CIPHER_TEXT] = Base64.urlsafe_encode64( cipher_text )
|
65
|
+
@dictionary[DICT_MATERIAL_DIGEST] = Base64.urlsafe_encode64(Digest::SHA256.digest(cipher_text))
|
62
66
|
|
63
|
-
return
|
67
|
+
return cipher_text
|
64
68
|
|
65
69
|
end
|
66
70
|
|
@@ -69,7 +73,7 @@ module OpenSecret
|
|
69
73
|
# and initialization vector (iv) sitting in the encryption_dictionary,
|
70
74
|
# to symmetrically decrypt the parameter cipher text.
|
71
75
|
#
|
72
|
-
# == Pre-Condition | Encryption
|
76
|
+
# == Pre-Condition | Encryption ...
|
73
77
|
#
|
74
78
|
# This method requires the <tt>@dictionary</tt> instance
|
75
79
|
# variable to have been set and to contain (amongst others)
|
@@ -112,7 +116,7 @@ crypt_text += encode_cipher.update line5
|
|
112
116
|
crypt_text += encode_cipher.update line6
|
113
117
|
crypt_text += encode_cipher.update line7
|
114
118
|
crypt_text += encode_cipher.final
|
115
|
-
coded_crypt_text = Base64.
|
119
|
+
coded_crypt_text = Base64.urlsafe_encode64(crypt_text)
|
116
120
|
|
117
121
|
puts ""
|
118
122
|
puts "The key is #{hex_key}"
|
@@ -133,13 +137,13 @@ puts "========================"
|
|
133
137
|
puts ""
|
134
138
|
puts ""
|
135
139
|
|
136
|
-
unencoded_crypt_text = Base64.
|
140
|
+
unencoded_crypt_text = Base64.urlsafe_decode64(coded_crypt_text)
|
137
141
|
decode_cipher = OpenSSL::Cipher.new('aes-256-cbc')
|
138
142
|
|
139
143
|
decode_cipher.decrypt
|
140
144
|
decode_cipher.key = [hex_key].pack("H*")
|
141
145
|
decode_cipher.iv = [hex_iv].pack("H*")
|
142
|
-
first_part = decode_cipher.update( Base64.
|
146
|
+
first_part = decode_cipher.update( Base64.urlsafe_decode64(coded_crypt_text) )
|
143
147
|
second_part = ""
|
144
148
|
second_part << decode_cipher.final
|
145
149
|
|
@@ -34,7 +34,7 @@ module OpenSecret
|
|
34
34
|
# takes care of it and its sister method {self.decryptor} will also perform
|
35
35
|
# the correct reversal activities to give you back the original plain text.
|
36
36
|
#
|
37
|
-
# {Base64.
|
37
|
+
# {Base64.urlsafe_encode64} facilitates the ciphertext encoding returning text that
|
38
38
|
# is safe to write to a file.
|
39
39
|
#
|
40
40
|
# @param plain_text [String]
|
@@ -66,16 +66,14 @@ module OpenSecret
|
|
66
66
|
|
67
67
|
blowfish_encryptor = OpenSSL::Cipher.new(OpenSecret::Blowfish::BLOWFISH_CIPHER_ID).encrypt
|
68
68
|
blowfish_encryptor.key = raw_stretched_key
|
69
|
-
|
70
|
-
|
71
|
-
return Base64.encode64( encrypted_lines ).chomp
|
69
|
+
return blowfish_encryptor.update(block_txt) << blowfish_encryptor.final
|
72
70
|
|
73
71
|
end
|
74
72
|
|
75
73
|
|
76
74
|
# Decrypt the cipher text parameter using the symmetric decryption key
|
77
|
-
# specified in the second parameter. The cipher text is expected to
|
78
|
-
#
|
75
|
+
# specified in the second parameter. The cipher text is expected to have
|
76
|
+
# already been decoded if necessary.
|
79
77
|
#
|
80
78
|
# Its okay to use a bespoke encryptor - just ensure you encode the result
|
81
79
|
# and override the padding constant.
|
@@ -87,8 +85,8 @@ module OpenSecret
|
|
87
85
|
# takes care of the reversing the activities carried out by {self.encryptor}.
|
88
86
|
#
|
89
87
|
# @param cipher_text [String]
|
90
|
-
# This incoming cipher text should be encoded
|
91
|
-
#
|
88
|
+
# This incoming cipher text should already be encoded but it
|
89
|
+
# will <b>chomped and stripped upon receipt</b> followed by
|
92
90
|
# decryption using the Blowfish algorithm.
|
93
91
|
#
|
94
92
|
# @param decryption_key [String]
|
@@ -109,13 +107,12 @@ module OpenSecret
|
|
109
107
|
#
|
110
108
|
def decryptor cipher_text, decryption_key
|
111
109
|
|
112
|
-
decoded_text = Base64.decode64(cipher_text.chomp.strip)
|
113
110
|
digested_key = Digest::SHA256.digest decryption_key
|
114
111
|
|
115
112
|
decrypt_tool = OpenSSL::Cipher.new(OpenSecret::Blowfish::BLOWFISH_CIPHER_ID).decrypt
|
116
113
|
decrypt_tool.key = digested_key
|
117
114
|
|
118
|
-
padded_plaintxt = decrypt_tool.update(
|
115
|
+
padded_plaintxt = decrypt_tool.update(cipher_text) << decrypt_tool.final
|
119
116
|
pad_begin_index = padded_plaintxt.index OpenSecret::Cipher::TEXT_PADDER
|
120
117
|
return padded_plaintxt if pad_begin_index.nil?
|
121
118
|
return padded_plaintxt[ 0 .. (pad_begin_index-1) ]
|
@@ -0,0 +1,116 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
module OpenSecret
|
5
|
+
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
# An envelope knows how to manipulate a JSON backed data structure
|
9
|
+
# (put, add etc) <b>after reading and then decrypting it</b> from a
|
10
|
+
# file and <b>before encrypting and then writing it</b> to a file.
|
11
|
+
#
|
12
|
+
# It provides behaviour to which we can create, append (add), update
|
13
|
+
# (change), read parts and delete essentially two structures
|
14
|
+
#
|
15
|
+
# - a collection of name/value pairs
|
16
|
+
# - an ordered list of values
|
17
|
+
#
|
18
|
+
# == JSON is Not Exposed in the Interface
|
19
|
+
#
|
20
|
+
# An envelope doesn't expose the data format used in the implementation
|
21
|
+
# allowing this to be changed seamlessly to YAMl or other formats.
|
22
|
+
#
|
23
|
+
# == Symmetric Encryption and Decryption
|
24
|
+
#
|
25
|
+
# An envelope supports operations to <b>read from</b> and <b>write to</b>
|
26
|
+
# a known filepath and with a symmetric key it can
|
27
|
+
#
|
28
|
+
# - decrypt <b>after reading from</b> a file and
|
29
|
+
# - encrypt <b>before writing to</b> a (the same) file
|
30
|
+
#
|
31
|
+
# == Hashes as the Primary Data Structure
|
32
|
+
#
|
33
|
+
# Envelope extends {Hash} as the core data structure for holding
|
34
|
+
#
|
35
|
+
# - strings
|
36
|
+
# - arrays
|
37
|
+
# - other hashes
|
38
|
+
# - booleans
|
39
|
+
# - integers and floats
|
40
|
+
class Envelope < Hash
|
41
|
+
|
42
|
+
|
43
|
+
# Write the data in this envelope hash map into a file-system
|
44
|
+
# backed mirror whose path was specified in the {self.read} method.
|
45
|
+
#
|
46
|
+
# Technology for encryption at rest is supported by this dictionary
|
47
|
+
# and to this aim, please endeavour to post a robust symmetric
|
48
|
+
# encryption key.
|
49
|
+
#
|
50
|
+
# Calling this {self.write} method when the file at the prescribed path
|
51
|
+
# does not exist results in the directory structure being created
|
52
|
+
# (if necessary) and then the encrypted file being written.
|
53
|
+
#
|
54
|
+
# @param encryption_key [String]
|
55
|
+
# encryption at rest is a given so this mandatory parameter must
|
56
|
+
# contain a robust symmetric encryption key. The symmetric key will
|
57
|
+
# be used for the decryption after the read. Note that the decryption
|
58
|
+
# key does not linger meaning it isn't cached in an instance variable.
|
59
|
+
def write encryption_key
|
60
|
+
|
61
|
+
FileUtils.mkdir_p(File.dirname(@filepath))
|
62
|
+
cipher_text = Base64.encode64 Blowfish.new.encryptor( self.to_json, encryption_key )
|
63
|
+
File.write @filepath, cipher_text
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
# Read and inject into this envelope, the data structure found in a
|
69
|
+
# file at the path specified in the first parameter.
|
70
|
+
#
|
71
|
+
# Symmetric cryptography is mandatory for the envelope so we must
|
72
|
+
# <b>encrypt before writing</b> and <b>decrypt after reading</b>.
|
73
|
+
#
|
74
|
+
# An argument error will result if a suitable key is not provided.
|
75
|
+
#
|
76
|
+
# If the file does not exist (denoting the first read) all this method
|
77
|
+
# does is to stash the filepath as an instance variable and igore the
|
78
|
+
# decryption key which can be nil (or ommitted).
|
79
|
+
#
|
80
|
+
# @param the_filepath [String]
|
81
|
+
# absolute path to the file which acts as the persistent mirror to
|
82
|
+
# this data structure envelope.
|
83
|
+
#
|
84
|
+
# @param decryption_key [String]
|
85
|
+
# encryption at rest is a given so this mandatory parameter must
|
86
|
+
# contain a robust symmetric decryption key. The key will be used
|
87
|
+
# for decryption after the read and it will not linger (ie not cached
|
88
|
+
# as an instance variable).
|
89
|
+
#
|
90
|
+
# @raise [ArgumentError] if the decryption key is not robust enough.
|
91
|
+
def read the_filepath, decryption_key = nil
|
92
|
+
|
93
|
+
@filepath = the_filepath
|
94
|
+
return unless File.exists? @filepath
|
95
|
+
|
96
|
+
cipher_text = Base64.decode64( File.read( @filepath ).strip )
|
97
|
+
plain_text = OpenSecret::Blowfish.new.decryptor( cipher_text, decryption_key )
|
98
|
+
|
99
|
+
puts ""
|
100
|
+
puts "=== ============================"
|
101
|
+
puts "=== Envelope After Decryption"
|
102
|
+
puts "=== ============================"
|
103
|
+
puts plain_text
|
104
|
+
puts "=== ============================"
|
105
|
+
puts ""
|
106
|
+
|
107
|
+
data_structure = JSON.parse plain_text
|
108
|
+
self.merge! data_structure
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
module OpenSecret
|
5
|
+
|
6
|
+
# The parent OpenSecret use case is designed to be extended by the cli
|
7
|
+
# (command line) use cases like {OpenSecret::Open}, {OpenSecret::Put} and
|
8
|
+
# {OpenSecret::Lock} because it describes behaviour common to at least two
|
9
|
+
# (but usually more) of the use cases.
|
10
|
+
#
|
11
|
+
# == Behaviour Reuse
|
12
|
+
#
|
13
|
+
# Behaviour that is reusable by any use case fits within {OpenSession::UseCase}
|
14
|
+
# whilst behaviour common to two or more {OpenSecret} use cases belongs here.
|
15
|
+
# Therefore the only behaviour in the named use case is detailed and must belong
|
16
|
+
# solely to it.
|
17
|
+
#
|
18
|
+
# == Fact Reuse
|
19
|
+
#
|
20
|
+
# Fact evaluation rules are born with reuse in mind. <b>Use case facts</b>
|
21
|
+
# are evaluated when they belong to either the class or its parent or any
|
22
|
+
# ancestors.
|
23
|
+
class SecretsUseCase < OpenSession::UseCase
|
24
|
+
|
25
|
+
@@context_name = "opensecret"
|
26
|
+
|
27
|
+
# Get the envelope that <b>was opened</b> by the open command but
|
28
|
+
# <b>not locked</b> with the lock command.
|
29
|
+
#
|
30
|
+
# @return [Envelope]
|
31
|
+
# return the Envelope that has been opened. The state carried alongside an
|
32
|
+
# open envelope is an id, an encryption key and a filepath all inside the
|
33
|
+
# userhome configuration file.
|
34
|
+
def get_envelope
|
35
|
+
|
36
|
+
encrypt_key = OpenSession::Attributes.instance.get_value @@context_name, @c[:open][:open_name], @c[:open][:open_keyname]
|
37
|
+
rel_filepath = OpenSession::Attributes.instance.get_value @@context_name, @c[:open][:open_name], @c[:open][:open_pathname]
|
38
|
+
|
39
|
+
put_filepath = File.join @c[:open][:open_dirpath], rel_filepath
|
40
|
+
the_envelope = Envelope.new
|
41
|
+
the_envelope.read put_filepath, encrypt_key
|
42
|
+
return the_envelope
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
end
|
@@ -32,7 +32,7 @@ module OpenSecret
|
|
32
32
|
#
|
33
33
|
# <b>opensecret</b> thwarts this by continual verification against an
|
34
34
|
# encrypted <em>public key signature</em> aboard the workstation.
|
35
|
-
class Init <
|
35
|
+
class Init < SecretsUseCase
|
36
36
|
|
37
37
|
attr_writer :safe_path, :email_addr, :store_url
|
38
38
|
@@context_name = "opensecret"
|
@@ -83,18 +83,20 @@ module OpenSecret
|
|
83
83
|
secured_keytext = asymmetric_keys.export @c[:global][:key_cipher], amalgam_key
|
84
84
|
|
85
85
|
crypt_key_segments = [ human_password, @c[:global][:separator_a], @email_addr, @c[:global][:separator_a], @c[:global][:stamp_23] ]
|
86
|
+
|
86
87
|
machine_key_crypt_key = crypt_key_segments.alphanumeric_union.concat_length
|
87
|
-
|
88
|
-
|
89
|
-
|
88
|
+
machine_key_x = Base64.urlsafe_encode64(
|
89
|
+
Blowfish.new.encryptor(machine_key, machine_key_crypt_key)
|
90
|
+
)
|
91
|
+
public_key_64 = Base64.urlsafe_encode64 asymmetric_keys.public_key.to_pem
|
90
92
|
|
91
93
|
OpenSession::Attributes.stash @c[:global][:name], @c[:global][:name], @c[:global][:machine_key_x], machine_key_x
|
92
94
|
OpenSession::Attributes.stash @c[:global][:name], @c[:global][:name], @c[:global][:stamp_key], @c[:global][:stamp_23]
|
93
|
-
OpenSession::Attributes.stash @c[:global][:name], @c[:global][:name], @c[:global][:publickey_id],
|
95
|
+
OpenSession::Attributes.stash @c[:global][:name], @c[:global][:name], @c[:global][:publickey_id], public_key_64
|
94
96
|
|
95
|
-
to_sign_segments = [ secured_keytext,
|
97
|
+
to_sign_segments = [ secured_keytext, public_key_64, @email_addr, @c[:global][:stamp_23] ]
|
96
98
|
to_sign_packet = to_sign_segments.alphanumeric_union.concat_length
|
97
|
-
signature_string = Base64.
|
99
|
+
signature_string = Base64.urlsafe_encode64( asymmetric_keys.sign( OpenSSL::Digest::SHA256.new, to_sign_packet ) )
|
98
100
|
|
99
101
|
FileUtils.mkdir_p @c[:global][:master_dirpath]
|
100
102
|
File.write @c[:global][:master_prv_key], secured_keytext
|
@@ -10,97 +10,110 @@ module OpenSecret
|
|
10
10
|
#
|
11
11
|
# The 3 core scenarios that this lock use case is equiped to handle are
|
12
12
|
#
|
13
|
-
# - a new source
|
14
|
-
# - an
|
15
|
-
# -
|
13
|
+
# - a new source that is as yet uncommitted
|
14
|
+
# - updating (overwriting) an existing source
|
15
|
+
# - requiring the destination to be deleted
|
16
16
|
#
|
17
|
-
#
|
17
|
+
# <b>Lock | Observable Value</b>
|
18
18
|
#
|
19
|
-
#
|
19
|
+
# The observable value after the lock use case has completed entails
|
20
|
+
#
|
21
|
+
# - a doubly encrypted data envelope placed in the backend store
|
22
|
+
# - a doubly encrypted private key placed in the frontend store
|
23
|
+
# - both stores sync'd with off-machine Git (S3, ...) mirrors
|
24
|
+
# - deletion of the (encrypted) envelope {Open}ed and stuffed with {Put}
|
25
|
+
# - deletion of {Open}ed session data to locate and decrypt envelope
|
20
26
|
#
|
21
|
-
#
|
27
|
+
# @example
|
22
28
|
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
|
26
|
-
# - a public key that is verifid against its encrypted signature
|
27
|
-
# - deleted session material created (and encrypted) by the put use case
|
28
|
-
class Lock < OpenSession::UseCase
|
29
|
+
# $ opensecret lock
|
30
|
+
#
|
31
|
+
class Lock < SecretsUseCase
|
29
32
|
|
30
33
|
attr_writer :secret_id, :secret_value
|
31
34
|
@@context_name = "opensecret"
|
32
35
|
|
33
36
|
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
+
# The <tt>lock use case</tt> is called after {OpenSecret::Open} and {OpenSecret::Put}
|
38
|
+
# and its effect is to dispatch the doubly encrypted materrial to the configured storage
|
39
|
+
# platform, be it Git, S3, SSH or just an accessible file-system.
|
40
|
+
#
|
41
|
+
# <b>Main Flow of Events</b>
|
37
42
|
#
|
38
|
-
#
|
39
|
-
#
|
43
|
+
# To seal the envelope built up by put, file and add amongst others requires
|
44
|
+
# that we
|
40
45
|
#
|
41
|
-
#
|
46
|
+
# - get the encrypted envelope
|
47
|
+
# - create a strong asymmetric key
|
48
|
+
# - lock the envelope using opensecret's double encrypt modus operandi
|
49
|
+
# - place the doubly encrypted result into the crypt store
|
50
|
+
# - lock the asymmetric key again with opensecret's double encrypt modus operandi
|
51
|
+
# - place the doubly encrypted result into the key store
|
42
52
|
#
|
43
|
-
# The
|
53
|
+
# The second double lock of the crypted envelope is done with the public key
|
54
|
+
# aspect of an asymmetric key created here.
|
44
55
|
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
56
|
+
# The second double lock of the crypted private key (created here) is done with
|
57
|
+
# the master public key created in the {Init.execute} use case main flow.
|
58
|
+
#
|
59
|
+
# <b>Lock | Observable Value</b>
|
60
|
+
#
|
61
|
+
# The observable value after the lock use case has completed entails
|
62
|
+
#
|
63
|
+
# - a doubly encrypted data envelope placed in the backend store
|
64
|
+
# - a doubly encrypted private key placed in the frontend store
|
65
|
+
# - both stores sync'd with off-machine Git (S3, ...) mirrors
|
66
|
+
# - deletion of the (encrypted) envelope {Open}ed and stuffed with {Put}
|
67
|
+
# - deletion of {Open}ed session data to locate and decrypt envelope
|
50
68
|
def execute
|
51
69
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
put_filepath = File.join @c[:open][:open_dirpath], rel_filepath
|
57
|
-
|
58
|
-
x_dictionary = OpenSession::Dictionary.new
|
59
|
-
x_dictionary.read put_filepath, true, encrypt_key
|
70
|
+
envelope = get_envelope
|
71
|
+
asym_key = OpenSSL::PKey::RSA.new @c[:global][:bit_key_size]
|
72
|
+
lockdown = Aes256.new.encrypt_it( asym_key.public_key.to_pem, envelope.to_json )
|
60
73
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
74
|
+
#### ###########################################
|
75
|
+
#### ###########################################
|
76
|
+
#### Now Give lockdown to the Backend Store
|
77
|
+
#### ###########################################
|
78
|
+
#### ###########################################
|
67
79
|
|
68
|
-
|
69
|
-
OpenSession::Attributes.stash @@context_name, @c[:open][:open_name], @c[:open][:open_keyname], new_encryption_key
|
70
|
-
x_dictionary.write new_encryption_key
|
80
|
+
master_public_key = Base64.urlsafe_decode64( OpenSession::Attributes.instance.get_value @c[:global][:name], @c[:global][:name], "public.key" )
|
71
81
|
|
82
|
+
lockedup = Aes256.new.encrypt_it( master_public_key, asym_key.export )
|
72
83
|
|
73
|
-
|
74
|
-
|
84
|
+
puts "#### #############################"
|
85
|
+
puts "#### The Crypt Store Suitcase"
|
86
|
+
puts "#### #############################"
|
87
|
+
puts ""
|
88
|
+
puts lockdown
|
89
|
+
puts ""
|
90
|
+
puts "#### #############################"
|
91
|
+
puts "#### The Key Store Suitcase"
|
92
|
+
puts "#### #############################"
|
93
|
+
puts ""
|
94
|
+
puts lockedup
|
95
|
+
puts ""
|
96
|
+
puts "================================================================================================="
|
97
|
+
puts "Now Continue with Unencoding the public key and then locking down the above asym_key.export"
|
98
|
+
puts "================================================================================================="
|
99
|
+
puts ""
|
75
100
|
|
101
|
+
exit
|
76
102
|
|
77
103
|
|
104
|
+
locked_block = Aes256.new.encrypt_it( asym_key.public_key.to_pem, asym_key.export )
|
78
105
|
|
79
|
-
|
80
|
-
|
106
|
+
secured_keytext = asym_key.export
|
107
|
+
## public_key_text = asymmetric_keys.public_key.to_pem
|
81
108
|
|
82
109
|
|
83
|
-
|
84
|
-
File.write @c[:global][:master_pub_key], public_key_crypt
|
110
|
+
Aes256.new.encrypt_it( "rubbish", secrets_dictionary.to_s )
|
85
111
|
|
86
|
-
|
112
|
+
the_encrypted_stuff = Aes256.new.encrypt_it( "rubbish", )
|
87
113
|
|
88
|
-
big_crypted_block = Aes256.new.encrypt_it(
|
89
|
-
public_key_text,
|
90
|
-
public_key_text,
|
91
|
-
payload_signature
|
92
|
-
)
|
93
114
|
|
94
|
-
|
95
|
-
|
96
|
-
puts "Crypted Block"
|
97
|
-
puts "=============="
|
98
|
-
puts ""
|
99
|
-
puts "#{big_crypted_block}"
|
100
|
-
puts ""
|
101
|
-
puts ""
|
102
|
-
puts "Carry on development in init.rb"
|
103
|
-
puts ""
|
115
|
+
#############################################################################################
|
116
|
+
#############################################################################################
|
104
117
|
|
105
118
|
|
106
119
|
=begin
|
@@ -116,7 +129,7 @@ module OpenSecret
|
|
116
129
|
# key4_pem = File.read 'private.secure.pem'
|
117
130
|
# pass_phrase = 'superduperpasswordistoBeENTEREDRIGHT1234HereandRightNOW'
|
118
131
|
# key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase
|
119
|
-
# decrypted_text = key4.private_decrypt(Base64.
|
132
|
+
# decrypted_text = key4.private_decrypt(Base64.urlsafe_decode64(encrypted_string))
|
120
133
|
|
121
134
|
# print "\nHey we have done the decryption.\n", "\n"
|
122
135
|
# print decrypted_text, "\n"
|
@@ -126,35 +139,6 @@ module OpenSecret
|
|
126
139
|
#############################################################################################
|
127
140
|
#############################################################################################
|
128
141
|
|
129
|
-
|
130
|
-
machine_key = Engineer.machine_key human_password.length, @c[:global][:ratio]
|
131
|
-
amalgam_key = Amalgam.passwords human_password, machine_key, @c[:global][:ratio]
|
132
|
-
asymmetric_keys = OpenSSL::PKey::RSA.new @c[:global][:bit_key_size]
|
133
|
-
secured_keytext = asymmetric_keys.export @c[:global][:key_cipher], amalgam_key
|
134
|
-
|
135
|
-
crypt_key_segments = [ human_password, @c[:global][:separator_a], @email_addr, @c[:global][:separator_a], @c[:global][:stamp_23] ]
|
136
|
-
machine_key_crypt_key = crypt_key_segments.alphanumeric_union.concat_length
|
137
|
-
blowfish_cipher = OpenSecret::Blowfish.new()
|
138
|
-
machine_key_x = blowfish_cipher.encryptor machine_key, machine_key_crypt_key
|
139
|
-
public_key_text = asymmetric_keys.public_key.to_pem
|
140
|
-
|
141
|
-
OpenSession::Attributes.stash @c[:global][:name], @c[:global][:name], @c[:global][:machine_key_x], machine_key_x
|
142
|
-
OpenSession::Attributes.stash @c[:global][:name], @c[:global][:name], @c[:global][:stamp_key], @c[:global][:stamp_23]
|
143
|
-
OpenSession::Attributes.stash @c[:global][:name], @c[:global][:name], @c[:global][:publickey_id], public_key_text.to_hex
|
144
|
-
|
145
|
-
to_sign_segments = [ secured_keytext, public_key_text, @email_addr, @c[:global][:stamp_23] ]
|
146
|
-
to_sign_packet = to_sign_segments.alphanumeric_union.concat_length
|
147
|
-
signature_string = Base64.encode64( asymmetric_keys.sign( OpenSSL::Digest::SHA256.new, to_sign_packet ) )
|
148
|
-
|
149
|
-
FileUtils.mkdir_p @c[:global][:master_dirpath]
|
150
|
-
File.write @c[:global][:master_prv_key], secured_keytext
|
151
|
-
File.write @c[:global][:master_sig_path], signature_string
|
152
|
-
|
153
|
-
|
154
|
-
#############################################################################################
|
155
|
-
#############################################################################################
|
156
|
-
|
157
|
-
|
158
142
|
end
|
159
143
|
|
160
144
|
|
data/lib/plugins/usecases/put.rb
CHANGED
@@ -5,9 +5,9 @@ module OpenSecret
|
|
5
5
|
require 'openssl'
|
6
6
|
|
7
7
|
# The <b>put use case</b> follows <b>open</b> and it adds secrets into an
|
8
|
-
# <em>(encrypted at rest)</em>
|
9
|
-
#
|
10
|
-
# into the configured storage engines.
|
8
|
+
# <em>(encrypted at rest)</em> <b>envelope</b>. Put can be called many times
|
9
|
+
# and when done, the <b>lock use case</b> can be called to commit all opened
|
10
|
+
# secrets into the configured storage engines.
|
11
11
|
#
|
12
12
|
# Calling <em>put</em> <b>before</b> calling open or <b>after</b> calling lock
|
13
13
|
# is not allowed and will result in an error.
|
@@ -50,8 +50,7 @@ module OpenSecret
|
|
50
50
|
#
|
51
51
|
# @example
|
52
52
|
#
|
53
|
-
# $ opensecret
|
54
|
-
# $ opensecret init
|
53
|
+
# $ opensecret init bill.clinton@example.com
|
55
54
|
# $ opensecret open my/friends
|
56
55
|
#
|
57
56
|
# $ opensecret put monica/surname lewinsky
|
@@ -64,7 +63,15 @@ module OpenSecret
|
|
64
63
|
#
|
65
64
|
# $ opensecret lock
|
66
65
|
#
|
67
|
-
|
66
|
+
# Soon follow up use cases will be unveiled, enabling us to
|
67
|
+
#
|
68
|
+
# - <b>get</b>
|
69
|
+
# - <b>read</b>
|
70
|
+
# - <b>list</b>
|
71
|
+
# - <b>look</b>
|
72
|
+
# - <b>peep</b> and
|
73
|
+
# - <b>peek</b>
|
74
|
+
class Put < SecretsUseCase
|
68
75
|
|
69
76
|
attr_writer :secret_id, :secret_value
|
70
77
|
@@context_name = "opensecret"
|
@@ -94,25 +101,18 @@ module OpenSecret
|
|
94
101
|
# - a new session id and encryption key is generated and used to re-encrypt
|
95
102
|
def execute
|
96
103
|
|
97
|
-
|
98
|
-
encrypt_key = OpenSession::Attributes.instance.get_value @@context_name, @c[:open][:open_name], @c[:open][:open_keyname]
|
99
|
-
rel_filepath = OpenSession::Attributes.instance.get_value @@context_name, @c[:open][:open_name], @c[:open][:open_pathname]
|
100
|
-
|
101
|
-
put_filepath = File.join @c[:open][:open_dirpath], rel_filepath
|
102
|
-
|
103
|
-
x_dictionary = OpenSession::Dictionary.new
|
104
|
-
x_dictionary.read put_filepath, true, encrypt_key
|
104
|
+
envelope = get_envelope
|
105
105
|
|
106
106
|
secret_ids = @secret_id.split("/")
|
107
|
-
if (
|
108
|
-
|
107
|
+
if ( envelope.has_key? secret_ids.first )
|
108
|
+
envelope[secret_ids.first][secret_ids.last] = @secret_value
|
109
109
|
else
|
110
|
-
|
110
|
+
envelope[secret_ids.first] = { secret_ids.last => @secret_value }
|
111
111
|
end
|
112
112
|
|
113
113
|
new_encryption_key = Engineer.strong_key @c[:open][:open_keylen]
|
114
114
|
OpenSession::Attributes.stash @@context_name, @c[:open][:open_name], @c[:open][:open_keyname], new_encryption_key
|
115
|
-
|
115
|
+
envelope.write new_encryption_key
|
116
116
|
|
117
117
|
end
|
118
118
|
|
@@ -14,7 +14,7 @@ module OpenSecret
|
|
14
14
|
# Stash the path into the host machine's configuration file and proceed
|
15
15
|
# to create the path directory chain if it does not already exist.
|
16
16
|
#
|
17
|
-
class Safe <
|
17
|
+
class Safe < SecretsUseCase
|
18
18
|
|
19
19
|
attr_writer :safe_path
|
20
20
|
@@context_name = "opensecret"
|
data/lib/session/dictionary.rb
CHANGED
@@ -15,7 +15,7 @@ module OpenSession
|
|
15
15
|
# - decrypt +after reading from+ a file
|
16
16
|
# - encrypt +before writing to+ a file
|
17
17
|
#
|
18
|
-
#
|
18
|
+
# This dictionary extends {Hash} in order to deliver on its core key value
|
19
19
|
# store, report and retrieve use cases.
|
20
20
|
#
|
21
21
|
# @example
|
@@ -80,13 +80,13 @@ module OpenSession
|
|
80
80
|
|
81
81
|
puts ""
|
82
82
|
puts "============================"
|
83
|
-
puts "Before Encryption
|
83
|
+
puts "Before Encryption"
|
84
84
|
puts "============================"
|
85
85
|
puts ini_string
|
86
86
|
puts "============================"
|
87
87
|
puts ""
|
88
88
|
|
89
|
-
ini_string = OpenSecret::Blowfish.new.encryptor(ini_string,encrypt_key) if @encrypt_at_rest
|
89
|
+
ini_string = Base64.encode64( OpenSecret::Blowfish.new.encryptor(ini_string,encrypt_key) ) if @encrypt_at_rest
|
90
90
|
|
91
91
|
File.write @filepath, ini_string
|
92
92
|
|
@@ -127,12 +127,12 @@ module OpenSession
|
|
127
127
|
|
128
128
|
file_contents = File.read( @filepath ).strip
|
129
129
|
if @encrypt_at_rest then
|
130
|
-
file_contents = OpenSecret::Blowfish.new.decryptor( file_contents, decrypt_key )
|
130
|
+
file_contents = OpenSecret::Blowfish.new.decryptor( Base64.decode64(file_contents), decrypt_key )
|
131
131
|
end
|
132
132
|
|
133
133
|
puts ""
|
134
134
|
puts "==========================="
|
135
|
-
puts "After Decryption
|
135
|
+
puts "After Decryption"
|
136
136
|
puts "==========================="
|
137
137
|
puts file_contents
|
138
138
|
puts "==========================="
|
data/lib/using.txt
CHANGED
data/lib/version.rb
CHANGED
data/opensecret.gemspec
CHANGED
@@ -28,8 +28,8 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.add_dependency 'thor'
|
29
29
|
|
30
30
|
spec.add_development_dependency "bundler", "~> 1.16"
|
31
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
32
|
-
spec.add_development_dependency "minitest", "~> 5.0"
|
31
|
+
#### in standard library ==> spec.add_development_dependency "rake", "~> 10.0"
|
32
|
+
#### in standard library ==> spec.add_development_dependency "minitest", "~> 5.0"
|
33
33
|
|
34
34
|
|
35
35
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opensecret
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.959
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Apollo Akora
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-03-
|
11
|
+
date: 2018-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: inifile
|
@@ -52,34 +52,6 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.16'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: rake
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '10.0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '10.0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: minitest
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '5.0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '5.0'
|
83
55
|
description: opensecret stashes uncrackable secrets into your Git, S3, DropBox, Google
|
84
56
|
Drive and filesystems backends. You interface with its intuitive Linux, Windows,
|
85
57
|
iOS front ends and it offers SDKs and plugins for Ruby, Python, Java, Jenkins, CodeShip,
|
@@ -127,6 +99,8 @@ files:
|
|
127
99
|
- lib/plugins/cipher.rb
|
128
100
|
- lib/plugins/ciphers/aes-256.rb
|
129
101
|
- lib/plugins/ciphers/blowfish.rb
|
102
|
+
- lib/plugins/envelope.rb
|
103
|
+
- lib/plugins/secrets.uc.rb
|
130
104
|
- lib/plugins/stores/store.rb
|
131
105
|
- lib/plugins/usecase.rb
|
132
106
|
- lib/plugins/usecases/init.rb
|