pluginaweek-encrypted_strings 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +59 -0
- data/LICENSE +20 -0
- data/README.rdoc +88 -0
- data/Rakefile +96 -0
- data/init.rb +1 -0
- data/lib/encrypted_strings.rb +7 -0
- data/lib/encrypted_strings/asymmetric_cipher.rb +185 -0
- data/lib/encrypted_strings/cipher.rb +17 -0
- data/lib/encrypted_strings/extensions/string.rb +205 -0
- data/lib/encrypted_strings/sha_cipher.rb +67 -0
- data/lib/encrypted_strings/symmetric_cipher.rb +101 -0
- data/test/asymmetric_cipher_test.rb +183 -0
- data/test/cipher_test.rb +15 -0
- data/test/keys/encrypted_private +12 -0
- data/test/keys/private +9 -0
- data/test/keys/public +4 -0
- data/test/sha_cipher_test.rb +82 -0
- data/test/string_test.rb +222 -0
- data/test/symmetric_cipher_test.rb +99 -0
- data/test/test_helper.rb +4 -0
- metadata +79 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
module EncryptedStrings
|
2
|
+
# Represents the base class for all ciphers. By default, all ciphers are
|
3
|
+
# assumed to be able to decrypt strings. Note, however, that certain
|
4
|
+
# encryption algorithms do not allow decryption.
|
5
|
+
class Cipher
|
6
|
+
# Can this string be decrypted? Default is true.
|
7
|
+
def can_decrypt?
|
8
|
+
true
|
9
|
+
end
|
10
|
+
|
11
|
+
# Attempts to decrypt the given data using the current configuration. By
|
12
|
+
# default, decryption is not implemented.
|
13
|
+
def decrypt(data)
|
14
|
+
raise NotImplementedError, "Decryption is not supported using a(n) #{self.class.name}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
module EncryptedStrings
|
2
|
+
module Extensions #:nodoc:
|
3
|
+
# Adds support for in-place encryption/decryption of strings
|
4
|
+
module String
|
5
|
+
def self.included(base) #:nodoc:
|
6
|
+
base.class_eval do
|
7
|
+
attr_accessor :cipher
|
8
|
+
|
9
|
+
alias_method :equals_without_encryption, :==
|
10
|
+
alias_method :==, :equals_with_encryption
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Encrypts the current string using the specified cipher. The default
|
15
|
+
# cipher is sha.
|
16
|
+
#
|
17
|
+
# Configuration options are cipher-specific. See each individual cipher
|
18
|
+
# class to find out the options available.
|
19
|
+
#
|
20
|
+
# == Example
|
21
|
+
#
|
22
|
+
# The following uses an SHA cipher to encrypt the string:
|
23
|
+
#
|
24
|
+
# password = 'shhhh'
|
25
|
+
# password.encrypt # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
26
|
+
#
|
27
|
+
# == Custom encryption mode
|
28
|
+
#
|
29
|
+
# The following uses Symmetric cipher (with a default password) to
|
30
|
+
# encrypt the string:
|
31
|
+
#
|
32
|
+
# EncryptedStrings::SymmetricCipher.default_password = 'secret'
|
33
|
+
# password = 'shhhh'
|
34
|
+
# password.encrypt(:symmetric) # => "jDACXI5hMPI=\n"
|
35
|
+
#
|
36
|
+
# == Custom encryption options
|
37
|
+
#
|
38
|
+
# Some encryption modes also support additional configuration options
|
39
|
+
# that determine how to encrypt the string. For example, SHA supports
|
40
|
+
# a salt which seeds the algorithm:
|
41
|
+
#
|
42
|
+
# password = 'shhhh'
|
43
|
+
# password.encrypt(:sha, :salt => 'secret') # => "3b22cbe4acde873c3efc82681096f3ae69aff828"
|
44
|
+
def encrypt(*args)
|
45
|
+
cipher = cipher_from_args(*args)
|
46
|
+
encrypted_string = cipher.encrypt(self)
|
47
|
+
encrypted_string.cipher = cipher
|
48
|
+
|
49
|
+
encrypted_string
|
50
|
+
end
|
51
|
+
|
52
|
+
# Encrypts this string and replaces it with the encrypted value. This
|
53
|
+
# takes the same parameters as #encrypt, but returns the same string
|
54
|
+
# instead of a different one.
|
55
|
+
#
|
56
|
+
# == Example
|
57
|
+
#
|
58
|
+
# password = 'shhhh'
|
59
|
+
# password.encrypt!(:symmetric, :password => 'secret') # => "qSg8vOo6QfU=\n"
|
60
|
+
# password # => "qSg8vOo6QfU=\n"
|
61
|
+
def encrypt!(*args)
|
62
|
+
encrypted_string = encrypt(*args)
|
63
|
+
self.cipher = encrypted_string.cipher
|
64
|
+
|
65
|
+
replace(encrypted_string)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Is this string encrypted? This will return true if the string is the
|
69
|
+
# result of a call to #encrypt or #encrypt!.
|
70
|
+
#
|
71
|
+
# == Example
|
72
|
+
#
|
73
|
+
# password = 'shhhh'
|
74
|
+
# password.encrypted? # => false
|
75
|
+
# password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
76
|
+
# password.encrypted? # => true
|
77
|
+
def encrypted?
|
78
|
+
!cipher.nil?
|
79
|
+
end
|
80
|
+
|
81
|
+
# Decrypts this string. If this is not a string that was previously
|
82
|
+
# encrypted, the cipher must be specified in the same way that it is
|
83
|
+
# when encrypting a string.
|
84
|
+
#
|
85
|
+
# == Example
|
86
|
+
#
|
87
|
+
# Without being previously encrypted:
|
88
|
+
#
|
89
|
+
# password = "qSg8vOo6QfU=\n"
|
90
|
+
# password.decrypt(:symmetric, :password => 'secret') # => "shhhh"
|
91
|
+
#
|
92
|
+
# After being previously encrypted:
|
93
|
+
#
|
94
|
+
# password = 'shhhh'
|
95
|
+
# password.encrypt!(:symmetric, :password => 'secret') # => "qSg8vOo6QfU=\n"
|
96
|
+
# password.decrypt # => "shhhh"
|
97
|
+
def decrypt(*args)
|
98
|
+
raise ArgumentError, 'Cipher cannot be inferred: must specify it as an argument' if args.empty? && !encrypted?
|
99
|
+
|
100
|
+
cipher = args.empty? && self.cipher || cipher_from_args(*args)
|
101
|
+
encrypted_string = cipher.decrypt(self)
|
102
|
+
encrypted_string.cipher = nil
|
103
|
+
|
104
|
+
encrypted_string
|
105
|
+
end
|
106
|
+
|
107
|
+
# Decrypts this string and replaces it with the decrypted value This
|
108
|
+
# takes the same parameters as #decrypt, but returns the same string
|
109
|
+
# instead of a different one.
|
110
|
+
#
|
111
|
+
# For example,
|
112
|
+
#
|
113
|
+
# password = "qSg8vOo6QfU=\n"
|
114
|
+
# password.decrypt!(:symmetric, :password => 'secret') # => "shhhh"
|
115
|
+
# password # => "shhhh"
|
116
|
+
def decrypt!(*args)
|
117
|
+
value = replace(decrypt(*args))
|
118
|
+
self.cipher = nil
|
119
|
+
value
|
120
|
+
end
|
121
|
+
|
122
|
+
# Can this string be decrypted? Strings can only be decrypted if they
|
123
|
+
# have previously been decrypted *and* the cipher supports decryption.
|
124
|
+
# To determine whether or not the cipher supports decryption, see the
|
125
|
+
# api for the cipher.
|
126
|
+
def can_decrypt?
|
127
|
+
encrypted? && cipher.can_decrypt?
|
128
|
+
end
|
129
|
+
|
130
|
+
# Tests whether the other object is equal to this one. Encrypted strings
|
131
|
+
# will be tested not only on their encrypted strings, but also by
|
132
|
+
# decrypting them and running tests against the decrypted value.
|
133
|
+
#
|
134
|
+
# == Equality with strings
|
135
|
+
#
|
136
|
+
# password = 'shhhh'
|
137
|
+
# password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
138
|
+
# password # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
139
|
+
# password == "shhhh" # => true
|
140
|
+
#
|
141
|
+
# == Equality with encrypted strings
|
142
|
+
#
|
143
|
+
# password = 'shhhh'
|
144
|
+
# password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
145
|
+
# password # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
146
|
+
# password == 'shhhh' # => true
|
147
|
+
#
|
148
|
+
# another_password = 'shhhh'
|
149
|
+
# another_password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
150
|
+
# password == another_password # => true
|
151
|
+
def equals_with_encryption(other)
|
152
|
+
if !(is_equal = equals_without_encryption(other)) && String === other
|
153
|
+
if encrypted?
|
154
|
+
if other.encrypted?
|
155
|
+
# We're both encrypted, so check if:
|
156
|
+
# (1) The other string is the encrypted value of this string
|
157
|
+
# (2) This string is the encrypted value of the other string
|
158
|
+
# (3) The other string is the encrypted value of this string, decrypted
|
159
|
+
# (4) This string is the encrypted value of the other string, decrypted
|
160
|
+
is_string_equal?(self, other) || is_string_equal?(other, self) || self.can_decrypt? && is_string_equal?(self.decrypt, other) || other.can_decrypt? && is_string_equal?(other.decrypt, self)
|
161
|
+
else
|
162
|
+
# Only we're encrypted
|
163
|
+
is_string_equal?(other, self)
|
164
|
+
end
|
165
|
+
else
|
166
|
+
if other.encrypted?
|
167
|
+
# Only the other string is encrypted
|
168
|
+
is_string_equal?(self, other)
|
169
|
+
else
|
170
|
+
# Neither are encrypted and equality test didn't work before, so
|
171
|
+
# they can't be equal
|
172
|
+
false
|
173
|
+
end
|
174
|
+
end
|
175
|
+
else
|
176
|
+
# The other value wasn't a string, so we can't check encryption equality
|
177
|
+
is_equal
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
private
|
182
|
+
def is_string_equal?(value, encrypted_value) #:nodoc:
|
183
|
+
# If the encrypted value can be decrypted, then test against the decrypted value
|
184
|
+
if encrypted_value.can_decrypt?
|
185
|
+
encrypted_value.decrypt.equals_without_encryption(value)
|
186
|
+
else
|
187
|
+
# Otherwise encrypt this value based on the cipher used on the encrypted value
|
188
|
+
# and test the equality of those strings
|
189
|
+
encrypted_value.equals_without_encryption(encrypted_value.cipher.encrypt(value))
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# Builds the cipher to use from the given arguments
|
194
|
+
def cipher_from_args(*args) #:nodoc:
|
195
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
196
|
+
name = (args.first || :sha).to_s.gsub(/(?:^|_)(.)/) {$1.upcase}
|
197
|
+
EncryptedStrings.const_get("#{name}Cipher").new(options)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
::String.class_eval do
|
204
|
+
include EncryptedStrings::Extensions::String
|
205
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
|
3
|
+
module EncryptedStrings
|
4
|
+
# Encrypts a string using a Secure Hash Algorithm (SHA), specifically SHA-1.
|
5
|
+
#
|
6
|
+
# == Encrypting
|
7
|
+
#
|
8
|
+
# To encrypt a string using an SHA cipher, the salt used to seed the
|
9
|
+
# algorithm must be specified. You can define the default for this value
|
10
|
+
# like so:
|
11
|
+
#
|
12
|
+
# EncryptedStrings::ShaCipher.default_salt = 'secret'
|
13
|
+
#
|
14
|
+
# If these configuration options are not passed in to #encrypt, then the
|
15
|
+
# default values will be used. You can override the default values like so:
|
16
|
+
#
|
17
|
+
# password = 'shhhh'
|
18
|
+
# password.encrypt(:sha, :salt => 'secret') # => "ae645b35bb5dfea6c9133ac872e6adfa92a3c2bd"
|
19
|
+
#
|
20
|
+
# == Decrypting
|
21
|
+
#
|
22
|
+
# SHA-encrypted strings cannot be decrypted. The only way to determine
|
23
|
+
# whether an unencrypted value is equal to an SHA-encrypted string is to
|
24
|
+
# encrypt the value with the same salt. For example,
|
25
|
+
#
|
26
|
+
# password = 'shhhh'.encrypt(:sha, :salt => 'secret') # => "3b22cbe4acde873c3efc82681096f3ae69aff828"
|
27
|
+
# input = 'shhhh'.encrypt(:sha, :salt => 'secret') # => "3b22cbe4acde873c3efc82681096f3ae69aff828"
|
28
|
+
# password == input # => true
|
29
|
+
class ShaCipher < Cipher
|
30
|
+
class << self
|
31
|
+
# The default salt value to use during encryption
|
32
|
+
attr_accessor :default_salt
|
33
|
+
end
|
34
|
+
|
35
|
+
# Set defaults
|
36
|
+
@default_salt = 'salt'
|
37
|
+
|
38
|
+
# The salt value to use for encryption
|
39
|
+
attr_accessor :salt
|
40
|
+
|
41
|
+
# Creates a new cipher that uses an SHA encryption strategy.
|
42
|
+
#
|
43
|
+
# Configuration options:
|
44
|
+
# * <tt>:salt</tt> - Random bytes used as one of the inputs for generating
|
45
|
+
# the encrypted string
|
46
|
+
def initialize(options = {})
|
47
|
+
invalid_options = options.keys - [:salt]
|
48
|
+
raise ArgumentError, "Unknown key(s): #{invalid_options.join(", ")}" unless invalid_options.empty?
|
49
|
+
|
50
|
+
options = {:salt => ShaCipher.default_salt}.merge(options)
|
51
|
+
|
52
|
+
self.salt = options[:salt].to_s
|
53
|
+
|
54
|
+
super()
|
55
|
+
end
|
56
|
+
|
57
|
+
# Decryption is not supported
|
58
|
+
def can_decrypt?
|
59
|
+
false
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the encrypted value of the data
|
63
|
+
def encrypt(data)
|
64
|
+
Digest::SHA1.hexdigest(data + salt)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module EncryptedStrings
|
2
|
+
# Indicates no password was specified for the symmetric cipher
|
3
|
+
class NoPasswordError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
# Symmetric encryption uses a specific algorithm and password to encrypt
|
7
|
+
# the string. As long as the algorithm and password are known, the string
|
8
|
+
# can be decrypted.
|
9
|
+
#
|
10
|
+
# Source: http://support.microsoft.com/kb/246071
|
11
|
+
#
|
12
|
+
# == Encrypting
|
13
|
+
#
|
14
|
+
# To encrypt a string using a symmetric cipher, the algorithm and password
|
15
|
+
# must be specified. You can define the defaults for these values like so:
|
16
|
+
#
|
17
|
+
# EncryptedStrings::SymmetricCipher.default_algorithm = 'des-ecb'
|
18
|
+
# EncryptedStrings::SymmetricCipher.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') # => "S/sEkViX3v4=\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 cipher, the algorithm and password
|
31
|
+
# must be specified. Defaults for these values can be defined as show above.
|
32
|
+
#
|
33
|
+
# If these configuration options are not passed in to #decrypt, then the
|
34
|
+
# default values will be used. You can override the default values like so:
|
35
|
+
#
|
36
|
+
# password = "S/sEkViX3v4=\n"
|
37
|
+
# password.decrypt(:symmetric, :algorithm => 'des-ecb', :password => 'secret') # => "shhhh"
|
38
|
+
#
|
39
|
+
# An exception will be raised if no password is specified.
|
40
|
+
class SymmetricCipher < Cipher
|
41
|
+
class << self
|
42
|
+
# The default algorithm to use for encryption. Default is DES-EDE3-CBC.
|
43
|
+
attr_accessor :default_algorithm
|
44
|
+
|
45
|
+
# The default password to use for generating the key and initialization
|
46
|
+
# vector. Default is nil.
|
47
|
+
attr_accessor :default_password
|
48
|
+
end
|
49
|
+
|
50
|
+
# Set default values
|
51
|
+
@default_algorithm = 'DES-EDE3-CBC'
|
52
|
+
|
53
|
+
# The algorithm to use for encryption/decryption
|
54
|
+
attr_accessor :algorithm
|
55
|
+
|
56
|
+
# The password that generates the key/initialization vector for the
|
57
|
+
# algorithm
|
58
|
+
attr_accessor :password
|
59
|
+
|
60
|
+
# Creates a new cipher that uses a symmetric encryption strategy.
|
61
|
+
#
|
62
|
+
# Configuration options:
|
63
|
+
# * <tt>:algorithm</tt> - The algorithm to use for generating the encrypted string
|
64
|
+
# * <tt>:password</tt> - The secret value to use for generating the
|
65
|
+
# key/initialization vector for the algorithm
|
66
|
+
def initialize(options = {})
|
67
|
+
invalid_options = options.keys - [:algorithm, :password]
|
68
|
+
raise ArgumentError, "Unknown key(s): #{invalid_options.join(", ")}" unless invalid_options.empty?
|
69
|
+
|
70
|
+
options = {
|
71
|
+
:algorithm => SymmetricCipher.default_algorithm,
|
72
|
+
:password => SymmetricCipher.default_password
|
73
|
+
}.merge(options)
|
74
|
+
|
75
|
+
self.algorithm = options[:algorithm]
|
76
|
+
self.password = options[:password]
|
77
|
+
raise NoPasswordError if password.nil?
|
78
|
+
|
79
|
+
super()
|
80
|
+
end
|
81
|
+
|
82
|
+
# Decrypts the current string using the current key and algorithm specified
|
83
|
+
def decrypt(data)
|
84
|
+
cipher = build_cipher(:decrypt)
|
85
|
+
cipher.update(data.unpack('m')[0]) + cipher.final
|
86
|
+
end
|
87
|
+
|
88
|
+
# Encrypts the current string using the current key and algorithm specified
|
89
|
+
def encrypt(data)
|
90
|
+
cipher = build_cipher(:encrypt)
|
91
|
+
[cipher.update(data) + cipher.final].pack('m')
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
def build_cipher(type) #:nodoc:
|
96
|
+
cipher = OpenSSL::Cipher::Cipher.new(algorithm).send(type)
|
97
|
+
cipher.pkcs5_keyivgen(password)
|
98
|
+
cipher
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class NoPrivateKeyErrorTest < Test::Unit::TestCase
|
4
|
+
def test_should_exist
|
5
|
+
assert_not_nil EncryptedStrings::NoPrivateKeyError
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class NoPublicKeyErrorTest < Test::Unit::TestCase
|
10
|
+
def test_should_exist
|
11
|
+
assert_not_nil EncryptedStrings::NoPublicKeyError
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class AsymmetricCipherByDefaultTest < Test::Unit::TestCase
|
16
|
+
def setup
|
17
|
+
@asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:public_key_file => File.dirname(__FILE__) + '/keys/public')
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_should_raise_an_exception
|
21
|
+
assert_raise(ArgumentError) {EncryptedStrings::AsymmetricCipher.new}
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_should_not_have_a_public_key_file
|
25
|
+
@asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:private_key_file => File.dirname(__FILE__) + '/keys/private')
|
26
|
+
assert_nil @asymmetric_cipher.public_key_file
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_should_not_have_a_private_key_file
|
30
|
+
assert_nil @asymmetric_cipher.private_key_file
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_should_not_have_an_algorithm
|
34
|
+
assert_nil @asymmetric_cipher.algorithm
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_should_not_have_a_password
|
38
|
+
assert_nil @asymmetric_cipher.password
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class AsymmetricCipherWithCustomDefaultsTest < Test::Unit::TestCase
|
43
|
+
def setup
|
44
|
+
@original_default_public_key_file = EncryptedStrings::AsymmetricCipher.default_public_key_file
|
45
|
+
@original_default_private_key_file = EncryptedStrings::AsymmetricCipher.default_private_key_file
|
46
|
+
|
47
|
+
EncryptedStrings::AsymmetricCipher.default_public_key_file = File.dirname(__FILE__) + '/keys/public'
|
48
|
+
EncryptedStrings::AsymmetricCipher.default_private_key_file = File.dirname(__FILE__) + '/keys/private'
|
49
|
+
|
50
|
+
@asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_should_use_default_public_key_file
|
54
|
+
assert_equal File.dirname(__FILE__) + '/keys/public', @asymmetric_cipher.public_key_file
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_should_use_default_private_key_file
|
58
|
+
assert_equal File.dirname(__FILE__) + '/keys/private', @asymmetric_cipher.private_key_file
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_should_not_have_an_algorithm
|
62
|
+
assert_nil @asymmetric_cipher.algorithm
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_should_not_have_a_password
|
66
|
+
assert_nil @asymmetric_cipher.password
|
67
|
+
end
|
68
|
+
|
69
|
+
def teardown
|
70
|
+
EncryptedStrings::AsymmetricCipher.default_public_key_file = @original_default_public_key_file
|
71
|
+
EncryptedStrings::AsymmetricCipher.default_private_key_file = @original_default_private_key_file
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class AsymmetricCipherWithInvalidOptionsTest < Test::Unit::TestCase
|
76
|
+
def test_should_throw_an_exception
|
77
|
+
assert_raise(ArgumentError) {EncryptedStrings::AsymmetricCipher.new(:invalid => true)}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class AsymmetricCipherTest < Test::Unit::TestCase
|
82
|
+
def setup
|
83
|
+
@asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:public_key_file => File.dirname(__FILE__) + '/keys/public')
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_should_be_able_to_decrypt
|
87
|
+
assert @asymmetric_cipher.can_decrypt?
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class AsymmetricCipherWithoutPublicKeyTest < Test::Unit::TestCase
|
92
|
+
def setup
|
93
|
+
@asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:public_key_file => nil, :private_key_file => File.dirname(__FILE__) + '/keys/private')
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_should_not_be_public
|
97
|
+
assert !@asymmetric_cipher.public?
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_should_not_be_able_to_encrypt
|
101
|
+
assert_raise(EncryptedStrings::NoPublicKeyError) {@asymmetric_cipher.encrypt('test')}
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class AsymmetricCipherWithPublicKeyTest < Test::Unit::TestCase
|
106
|
+
def setup
|
107
|
+
@asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:public_key_file => File.dirname(__FILE__) + '/keys/public')
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_should_be_public
|
111
|
+
assert @asymmetric_cipher.public?
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_should_not_be_private
|
115
|
+
assert !@asymmetric_cipher.private?
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_should_be_able_to_encrypt
|
119
|
+
assert_equal 90, @asymmetric_cipher.encrypt('test').length
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_should_not_be_able_to_decrypt
|
123
|
+
assert_raise(EncryptedStrings::NoPrivateKeyError) {@asymmetric_cipher.decrypt("HbEh0Hwri26S7SWYqO26DBbzfhR1h/0pXYLjSKUpxF5DOaOCtD9oRN748+Na\nrfNaVN5Eg7RUhbRFZE+UnNHo6Q==\n")}
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class AsymmetricCipherWithoutPrivateKeyTest < Test::Unit::TestCase
|
128
|
+
def setup
|
129
|
+
@asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:private_key_file => nil, :public_key_file => File.dirname(__FILE__) + '/keys/public')
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_should_not_be_private
|
133
|
+
assert !@asymmetric_cipher.private?
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_should_not_be_able_to_decrypt
|
137
|
+
assert_raise(EncryptedStrings::NoPrivateKeyError) {@asymmetric_cipher.decrypt("HbEh0Hwri26S7SWYqO26DBbzfhR1h/0pXYLjSKUpxF5DOaOCtD9oRN748+Na\nrfNaVN5Eg7RUhbRFZE+UnNHo6Q==\n")}
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class AsymmetricCipherWithPrivateKeyTest < Test::Unit::TestCase
|
142
|
+
def setup
|
143
|
+
@asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:private_key_file => File.dirname(__FILE__) + '/keys/private')
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_should_not_be_public
|
147
|
+
assert !@asymmetric_cipher.public?
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_should_be_private
|
151
|
+
assert @asymmetric_cipher.private?
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_not_should_be_able_to_encrypt
|
155
|
+
assert_raise(EncryptedStrings::NoPublicKeyError) {@asymmetric_cipher.encrypt('test')}
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_should_be_able_to_decrypt
|
159
|
+
assert_equal 'test', @asymmetric_cipher.decrypt("HbEh0Hwri26S7SWYqO26DBbzfhR1h/0pXYLjSKUpxF5DOaOCtD9oRN748+Na\nrfNaVN5Eg7RUhbRFZE+UnNHo6Q==\n")
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
class AsymmetricCipherWithEncryptedPrivateKeyTest < Test::Unit::TestCase
|
164
|
+
def setup
|
165
|
+
@asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:private_key_file => File.dirname(__FILE__) + '/keys/encrypted_private', :algorithm => 'DES-EDE3-CBC', :password => 'secret')
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_should_not_be_public
|
169
|
+
assert !@asymmetric_cipher.public?
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_should_be_private
|
173
|
+
assert @asymmetric_cipher.private?
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_should_not_be_able_to_encrypt
|
177
|
+
assert_raise(EncryptedStrings::NoPublicKeyError) {@asymmetric_cipher.encrypt('test')}
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_should_be_able_to_decrypt
|
181
|
+
assert_equal 'test', @asymmetric_cipher.decrypt("HbEh0Hwri26S7SWYqO26DBbzfhR1h/0pXYLjSKUpxF5DOaOCtD9oRN748+Na\nrfNaVN5Eg7RUhbRFZE+UnNHo6Q==\n")
|
182
|
+
end
|
183
|
+
end
|