encrypted_strings 0.1.1 → 0.2.0
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.
- data/CHANGELOG.rdoc +8 -0
- data/README.rdoc +23 -23
- data/Rakefile +1 -1
- data/lib/encrypted_strings/{asymmetric_encryptor.rb → asymmetric_cipher.rb} +30 -37
- data/lib/encrypted_strings/{encryptor.rb → cipher.rb} +3 -3
- data/lib/encrypted_strings/extensions/string.rb +49 -40
- data/lib/encrypted_strings/{sha_encryptor.rb → sha_cipher.rb} +13 -11
- data/lib/encrypted_strings/symmetric_cipher.rb +102 -0
- data/lib/encrypted_strings.rb +4 -4
- data/test/asymmetric_cipher_test.rb +183 -0
- data/test/cipher_test.rb +15 -0
- data/test/keys/encrypted_private +12 -12
- data/test/sha_cipher_test.rb +81 -0
- data/test/string_test.rb +22 -22
- data/test/symmetric_cipher_test.rb +99 -0
- metadata +13 -23
- data/lib/encrypted_strings/no_key_error.rb +0 -7
- data/lib/encrypted_strings/no_private_key_error.rb +0 -7
- data/lib/encrypted_strings/no_public_key_error.rb +0 -7
- data/lib/encrypted_strings/symmetric_encryptor.rb +0 -134
- data/test/asymmetric_encryptor_test.rb +0 -194
- data/test/encryptor_test.rb +0 -15
- data/test/keys/pkcs5_encrypted_private +0 -12
- data/test/no_key_error_test.rb +0 -7
- data/test/no_private_key_error_test.rb +0 -7
- data/test/no_public_key_error_test.rb +0 -7
- data/test/sha_encryptor_test.rb +0 -81
- data/test/symmetric_encryptor_test.rb +0 -137
data/test/string_test.rb
CHANGED
@@ -6,7 +6,7 @@ class StringByDefaultTest < Test::Unit::TestCase
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def test_should_use_sha
|
9
|
-
assert_instance_of PluginAWeek::EncryptedStrings::
|
9
|
+
assert_instance_of PluginAWeek::EncryptedStrings::ShaCipher, @encrypted_string.cipher
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -16,21 +16,21 @@ class StringWithCustomOptionsTest < Test::Unit::TestCase
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def test_should_use_sha
|
19
|
-
assert_instance_of PluginAWeek::EncryptedStrings::
|
19
|
+
assert_instance_of PluginAWeek::EncryptedStrings::ShaCipher, @encrypted_string.cipher
|
20
20
|
end
|
21
21
|
|
22
22
|
def test_should_use_custom_options
|
23
|
-
assert_equal 'different_salt', @encrypted_string.
|
23
|
+
assert_equal 'different_salt', @encrypted_string.cipher.salt
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
class
|
27
|
+
class StringWithCustomCipher
|
28
28
|
def setup
|
29
29
|
@encrypted_string = 'test'.encrypt(:symmetric, :password => 'key')
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
assert_instance_of PluginAWeek::EncryptedStrings::
|
32
|
+
def test_should_use_custom_cipher
|
33
|
+
assert_instance_of PluginAWeek::EncryptedStrings::SymmetricCipher, @encrypted_string.cipher
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -43,8 +43,8 @@ class StringTest < Test::Unit::TestCase
|
|
43
43
|
assert !@string.encrypted?
|
44
44
|
end
|
45
45
|
|
46
|
-
def
|
47
|
-
assert_nil @string.
|
46
|
+
def test_should_not_have_a_cipher
|
47
|
+
assert_nil @string.cipher
|
48
48
|
end
|
49
49
|
|
50
50
|
def test_should_not_be_able_to_decrypt
|
@@ -72,8 +72,8 @@ class StringAfterBeingEncryptedAndReplacedTest < Test::Unit::TestCase
|
|
72
72
|
assert !'test'.equals_without_encryption(@encrypted_string)
|
73
73
|
end
|
74
74
|
|
75
|
-
def
|
76
|
-
assert_instance_of PluginAWeek::EncryptedStrings::
|
75
|
+
def test_should_have_a_cipher
|
76
|
+
assert_instance_of PluginAWeek::EncryptedStrings::ShaCipher, @encrypted_string.cipher
|
77
77
|
end
|
78
78
|
|
79
79
|
def test_should_be_encrypted
|
@@ -91,8 +91,8 @@ class StringAfterBeingDecryptedTest < Test::Unit::TestCase
|
|
91
91
|
assert !@decrypted_string.encrypted?
|
92
92
|
end
|
93
93
|
|
94
|
-
def
|
95
|
-
assert_nil @decrypted_string.
|
94
|
+
def test_should_not_have_a_cipher
|
95
|
+
assert_nil @decrypted_string.cipher
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
@@ -103,15 +103,15 @@ class StringAfterBeingDecryptedAndReplacedTest < Test::Unit::TestCase
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def test_should_not_be_the_original_value
|
106
|
-
assert !"
|
106
|
+
assert !"oTxJd67ElLY=\n".equals_without_encryption(@encrypted_string)
|
107
107
|
end
|
108
108
|
|
109
109
|
def test_should_be_the_decrypted_value
|
110
110
|
assert 'test'.equals_without_encryption(@encrypted_string)
|
111
111
|
end
|
112
112
|
|
113
|
-
def
|
114
|
-
assert_nil @encrypted_string.
|
113
|
+
def test_should_not_have_a_cipher
|
114
|
+
assert_nil @encrypted_string.cipher
|
115
115
|
end
|
116
116
|
|
117
117
|
def test_should_not_be_encrypted
|
@@ -119,7 +119,7 @@ class StringAfterBeingDecryptedAndReplacedTest < Test::Unit::TestCase
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
-
class
|
122
|
+
class StringWithUndecryptableCipherTest < Test::Unit::TestCase
|
123
123
|
def setup
|
124
124
|
@encrypted_string = 'test'.encrypt(:sha)
|
125
125
|
end
|
@@ -148,7 +148,7 @@ class StringWithUndecryptableEncryptorTest < Test::Unit::TestCase
|
|
148
148
|
assert_equal encrypted_encrypted_string, @encrypted_string
|
149
149
|
end
|
150
150
|
|
151
|
-
def
|
151
|
+
def test_should_be_able_to_check_equality_with_same_string_without_cipher
|
152
152
|
assert_equal @encrypted_string.to_s, @encrypted_string
|
153
153
|
assert_equal @encrypted_string, @encrypted_string.to_s
|
154
154
|
end
|
@@ -161,7 +161,7 @@ class StringWithUndecryptableEncryptorTest < Test::Unit::TestCase
|
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
164
|
-
class
|
164
|
+
class StringWithDecryptableCipherTest < Test::Unit::TestCase
|
165
165
|
def setup
|
166
166
|
@encrypted_string = 'test'.encrypt(:symmetric, :password => 'secret')
|
167
167
|
end
|
@@ -186,7 +186,7 @@ class StringWithDecryptableEncryptorTest < Test::Unit::TestCase
|
|
186
186
|
assert_equal encrypted_encrypted_string, @encrypted_string
|
187
187
|
end
|
188
188
|
|
189
|
-
def
|
189
|
+
def test_should_be_able_to_check_equality_with_same_string_without_cipher
|
190
190
|
assert_equal @encrypted_string.to_s, @encrypted_string
|
191
191
|
assert_equal @encrypted_string, @encrypted_string.to_s
|
192
192
|
end
|
@@ -201,15 +201,15 @@ end
|
|
201
201
|
|
202
202
|
class StringPreviouslyEncryptedTest < Test::Unit::TestCase
|
203
203
|
def setup
|
204
|
-
@encrypted_string = "
|
204
|
+
@encrypted_string = "oTxJd67ElLY=\n"
|
205
205
|
end
|
206
206
|
|
207
207
|
def test_should_not_be_encrypted
|
208
208
|
assert !@encrypted_string.encrypted?
|
209
209
|
end
|
210
210
|
|
211
|
-
def
|
212
|
-
assert_nil @encrypted_string.
|
211
|
+
def test_should_not_have_a_cipher
|
212
|
+
assert_nil @encrypted_string.cipher
|
213
213
|
end
|
214
214
|
|
215
215
|
def test_should_not_be_able_to_decrypt
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class NoPasswordErrorTest < Test::Unit::TestCase
|
4
|
+
def test_should_exist
|
5
|
+
assert_not_nil PluginAWeek::EncryptedStrings::NoPasswordError
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class SymmetricCipherByDefaultTest < Test::Unit::TestCase
|
10
|
+
def setup
|
11
|
+
@symmetric_cipher = PluginAWeek::EncryptedStrings::SymmetricCipher.new(:password => 'secret')
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_use_default_algorithm
|
15
|
+
assert_equal 'DES-EDE3-CBC', @symmetric_cipher.algorithm
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_should_raise_exception
|
19
|
+
assert_raise(PluginAWeek::EncryptedStrings::NoPasswordError) {PluginAWeek::EncryptedStrings::SymmetricCipher.new}
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_should_encrypt_using_default_configuration
|
23
|
+
assert_equal "oTxJd67ElLY=\n", @symmetric_cipher.encrypt('test')
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_should_decrypt_encrypted_string_using_default_configuration
|
27
|
+
assert_equal 'test', @symmetric_cipher.decrypt("oTxJd67ElLY=\n")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class SymmetricCipherWithCustomDefaultsTest < Test::Unit::TestCase
|
32
|
+
def setup
|
33
|
+
@original_default_algorithm = PluginAWeek::EncryptedStrings::SymmetricCipher.default_algorithm
|
34
|
+
@original_default_password = PluginAWeek::EncryptedStrings::SymmetricCipher.default_password
|
35
|
+
|
36
|
+
PluginAWeek::EncryptedStrings::SymmetricCipher.default_algorithm = 'DES-EDE3-CFB'
|
37
|
+
PluginAWeek::EncryptedStrings::SymmetricCipher.default_password = 'secret'
|
38
|
+
@symmetric_cipher = PluginAWeek::EncryptedStrings::SymmetricCipher.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_should_use_custom_default_algorithm
|
42
|
+
assert_equal 'DES-EDE3-CFB', @symmetric_cipher.algorithm
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_should_use_custom_default_password
|
46
|
+
assert_equal 'secret', @symmetric_cipher.password
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_should_encrypt_using_custom_default_configuration
|
50
|
+
assert_equal "QWz/eQ==\n", @symmetric_cipher.encrypt('test')
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_should_decrypt_encrypted_string_using_custom_default_configuration
|
54
|
+
assert_equal 'test', @symmetric_cipher.decrypt("QWz/eQ==\n")
|
55
|
+
end
|
56
|
+
|
57
|
+
def teardown
|
58
|
+
PluginAWeek::EncryptedStrings::SymmetricCipher.default_algorithm = @original_default_algorithm
|
59
|
+
PluginAWeek::EncryptedStrings::SymmetricCipher.default_password = @original_default_password
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class SymmetricCipherWithInvalidOptionsTest < Test::Unit::TestCase
|
64
|
+
def test_should_throw_an_exception
|
65
|
+
assert_raise(ArgumentError) {PluginAWeek::EncryptedStrings::SymmetricCipher.new(:invalid => true)}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class SymmetricCipherTest < Test::Unit::TestCase
|
70
|
+
def setup
|
71
|
+
@symmetric_cipher = PluginAWeek::EncryptedStrings::SymmetricCipher.new(:password => 'secret')
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_should_be_able_to_decrypt
|
75
|
+
assert @symmetric_cipher.can_decrypt?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class SymmetricCipherWithCustomOptionsTest < Test::Unit::TestCase
|
80
|
+
def setup
|
81
|
+
@symmetric_cipher = PluginAWeek::EncryptedStrings::SymmetricCipher.new(:algorithm => 'DES-EDE3-CFB', :password => 'secret')
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_should_use_custom_algorithm
|
85
|
+
assert_equal 'DES-EDE3-CFB', @symmetric_cipher.algorithm
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_should_use_custom_password
|
89
|
+
assert_equal 'secret', @symmetric_cipher.password
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_should_encrypt_using_custom_options
|
93
|
+
assert_equal "QWz/eQ==\n", @symmetric_cipher.encrypt('test')
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_should_decrypt_using_custom_options
|
97
|
+
assert_equal 'test', @symmetric_cipher.decrypt("QWz/eQ==\n")
|
98
|
+
end
|
99
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: encrypted_strings
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Pfeifer
|
@@ -23,30 +23,23 @@ extra_rdoc_files: []
|
|
23
23
|
|
24
24
|
files:
|
25
25
|
- lib/encrypted_strings
|
26
|
-
- lib/encrypted_strings/
|
27
|
-
- lib/encrypted_strings/
|
28
|
-
- lib/encrypted_strings/sha_encryptor.rb
|
26
|
+
- lib/encrypted_strings/cipher.rb
|
27
|
+
- lib/encrypted_strings/sha_cipher.rb
|
29
28
|
- lib/encrypted_strings/extensions
|
30
29
|
- lib/encrypted_strings/extensions/string.rb
|
31
|
-
- lib/encrypted_strings/
|
32
|
-
- lib/encrypted_strings/
|
33
|
-
- lib/encrypted_strings/no_public_key_error.rb
|
34
|
-
- lib/encrypted_strings/symmetric_encryptor.rb
|
30
|
+
- lib/encrypted_strings/symmetric_cipher.rb
|
31
|
+
- lib/encrypted_strings/asymmetric_cipher.rb
|
35
32
|
- lib/encrypted_strings.rb
|
36
|
-
- test/asymmetric_encryptor_test.rb
|
37
|
-
- test/symmetric_encryptor_test.rb
|
38
33
|
- test/test_helper.rb
|
39
|
-
- test/
|
40
|
-
- test/
|
41
|
-
- test/
|
34
|
+
- test/symmetric_cipher_test.rb
|
35
|
+
- test/asymmetric_cipher_test.rb
|
36
|
+
- test/sha_cipher_test.rb
|
42
37
|
- test/keys
|
43
38
|
- test/keys/encrypted_private
|
44
39
|
- test/keys/private
|
45
40
|
- test/keys/public
|
46
|
-
- test/keys/pkcs5_encrypted_private
|
47
41
|
- test/string_test.rb
|
48
|
-
- test/
|
49
|
-
- test/encryptor_test.rb
|
42
|
+
- test/cipher_test.rb
|
50
43
|
- CHANGELOG.rdoc
|
51
44
|
- init.rb
|
52
45
|
- LICENSE
|
@@ -79,11 +72,8 @@ signing_key:
|
|
79
72
|
specification_version: 2
|
80
73
|
summary: Dead-simple string encryption/decryption syntax.
|
81
74
|
test_files:
|
82
|
-
- test/
|
83
|
-
- test/
|
84
|
-
- test/
|
85
|
-
- test/sha_encryptor_test.rb
|
86
|
-
- test/no_private_key_error_test.rb
|
75
|
+
- test/symmetric_cipher_test.rb
|
76
|
+
- test/asymmetric_cipher_test.rb
|
77
|
+
- test/sha_cipher_test.rb
|
87
78
|
- test/string_test.rb
|
88
|
-
- test/
|
89
|
-
- test/encryptor_test.rb
|
79
|
+
- test/cipher_test.rb
|
@@ -1,134 +0,0 @@
|
|
1
|
-
require 'encrypted_strings/no_key_error'
|
2
|
-
|
3
|
-
module PluginAWeek #:nodoc:
|
4
|
-
module EncryptedStrings
|
5
|
-
# Symmetric encryption uses a password and a specific algorithm to encrypt
|
6
|
-
# the string. As long as the password and algorithm are known, the string
|
7
|
-
# can be decrypted.
|
8
|
-
#
|
9
|
-
# Source: http://support.microsoft.com/kb/246071
|
10
|
-
#
|
11
|
-
# == Encrypting
|
12
|
-
#
|
13
|
-
# To encrypt a string using a symmetric algorithm, the type of algorithm and
|
14
|
-
# password *must* be specified. You can define the defaults for these
|
15
|
-
# values like so:
|
16
|
-
#
|
17
|
-
# PluginAWeek::EncryptedStrings::SymmetricEncryptor.default_algorithm = 'des-ecb'
|
18
|
-
# PluginAWeek::EncryptedStrings::SymmetricEncryptor.default_password = 'secret'
|
19
|
-
#
|
20
|
-
# If these configuration options are not passed in to #encrypt, then the
|
21
|
-
# default values will be used. You can override the default values like so:
|
22
|
-
#
|
23
|
-
# password = 'shhhh'
|
24
|
-
# password.encrypt(:symmetric, :algorithm => 'des-ecb', :password => 'secret') # => "sUG6tYSn0mI=\n"
|
25
|
-
#
|
26
|
-
# An exception will be raised if no password is specified.
|
27
|
-
#
|
28
|
-
# == Decrypting
|
29
|
-
#
|
30
|
-
# To decrypt a string using an symmetric algorithm, the type of algorithm
|
31
|
-
# and password must also be specified. Defaults for these values can be
|
32
|
-
# defined as show above.
|
33
|
-
#
|
34
|
-
# If these configuration options are not passed in to #decrypt, then the
|
35
|
-
# default values will be used. You can override the default values like so:
|
36
|
-
#
|
37
|
-
# password = "sUG6tYSn0mI=\n"
|
38
|
-
# password.decrypt(:symmetric, :algorithm => 'des-ecb', :password => 'secret') # => "shhhh"
|
39
|
-
#
|
40
|
-
# An exception will be raised if no password is specified.
|
41
|
-
class SymmetricEncryptor < Encryptor
|
42
|
-
class << self
|
43
|
-
# The default algorithm to use for encryption. Default is DES-EDE3-CBC.
|
44
|
-
attr_accessor :default_algorithm
|
45
|
-
|
46
|
-
# The default password to use for generating the key and initialization
|
47
|
-
# vector. Default is nil.
|
48
|
-
attr_accessor :default_password
|
49
|
-
|
50
|
-
# DEPRECATED
|
51
|
-
def default_key #:nodoc:
|
52
|
-
warn("#{self}.default_key is deprecated and will be removed from encrypted_attributes 0.2.0 (use default_password)")
|
53
|
-
@default_password
|
54
|
-
end
|
55
|
-
|
56
|
-
# DEPRECATED
|
57
|
-
def default_key=(value) #:nodoc:
|
58
|
-
warn("#{self}.default_key= is deprecated and will be removed from encrypted_attributes 0.2.0 (use default_password=)")
|
59
|
-
@default_password = value
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# Set default values
|
64
|
-
@default_algorithm = 'DES-EDE3-CBC'
|
65
|
-
@default_password = nil
|
66
|
-
|
67
|
-
# The algorithm to use for encryption/decryption
|
68
|
-
attr_accessor :algorithm
|
69
|
-
|
70
|
-
# The password that generates the key/initialization vector for the
|
71
|
-
# algorithm
|
72
|
-
attr_accessor :password
|
73
|
-
|
74
|
-
# Configuration options:
|
75
|
-
# * +algorithm+ - The algorithm to use
|
76
|
-
# * +password+ - The secret key to use for generating the key/initialization vector for the algorithm
|
77
|
-
# * +key+ - DEPRECATED. The secret key to use for generating the key/initialization vector for the algorithm
|
78
|
-
# * +pkcs5_compliant+ - Whether the generated key/iv should comply to the PKCS #5 standard. Default is false.
|
79
|
-
def initialize(options = {})
|
80
|
-
invalid_options = options.keys - [:algorithm, :password, :key, :pkcs5_compliant]
|
81
|
-
raise ArgumentError, "Unknown key(s): #{invalid_options.join(", ")}" unless invalid_options.empty?
|
82
|
-
|
83
|
-
options = {
|
84
|
-
:algorithm => self.class.default_algorithm,
|
85
|
-
:password => self.class.default_password,
|
86
|
-
:pkcs5_compliant => false
|
87
|
-
}.merge(options)
|
88
|
-
|
89
|
-
@pkcs5_compliant = options[:pkcs5_compliant]
|
90
|
-
warn('PKCS #5 non-compliancy is deprecated and will be removed from encrypted_attributes 0.2.0') if @pkcs5_compliant == false
|
91
|
-
|
92
|
-
self.algorithm = options[:algorithm]
|
93
|
-
|
94
|
-
self.password = options[:password] || options[:key]
|
95
|
-
warn(':key option is deprecated and will be removed from encrypted_attributes 0.2.0 (use :password)') if options[:key]
|
96
|
-
raise NoKeyError if password.nil?
|
97
|
-
|
98
|
-
super()
|
99
|
-
end
|
100
|
-
|
101
|
-
# Decrypts the current string using the current key and algorithm specified
|
102
|
-
def decrypt(data)
|
103
|
-
cipher = build_cipher(:decrypt)
|
104
|
-
cipher.update(Base64.decode64(data)) + cipher.final
|
105
|
-
end
|
106
|
-
|
107
|
-
# Encrypts the current string using the current key and algorithm specified
|
108
|
-
def encrypt(data)
|
109
|
-
cipher = build_cipher(:encrypt)
|
110
|
-
Base64.encode64(cipher.update(data) + cipher.final)
|
111
|
-
end
|
112
|
-
|
113
|
-
private
|
114
|
-
def build_cipher(type) #:nodoc:
|
115
|
-
cipher = OpenSSL::Cipher.new(algorithm)
|
116
|
-
cipher.send(type)
|
117
|
-
|
118
|
-
if @pkcs5_compliant
|
119
|
-
# Use the default PKCS5 key/iv generator algorithm
|
120
|
-
cipher.pkcs5_keyivgen(password)
|
121
|
-
else
|
122
|
-
# To remain backwards-compatible, the deprecated #encrypt/#decrypt
|
123
|
-
# calls (which take a single argument, being the password) is replaced
|
124
|
-
# with pkcs5_keyivgen. Internally, this uses "OpenSSL for Ruby rulez!"
|
125
|
-
# as the IV/salt. This is also the case for the number of iterations.
|
126
|
-
cipher.pkcs5_keyivgen(password, 'OpenSSL ', 1)
|
127
|
-
cipher.iv = 'OpenSSL for Ruby rulez!'
|
128
|
-
end
|
129
|
-
|
130
|
-
cipher
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|