encrypted_strings 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,68 +1,66 @@
1
1
  require 'digest/sha1'
2
2
 
3
- module PluginAWeek #:nodoc:
4
- module EncryptedStrings
5
- # Encrypts a string using a Secure Hash Algorithm (SHA), specifically SHA-1.
6
- #
7
- # == Encrypting
8
- #
9
- # To encrypt a string using an SHA cipher, the salt used to seed the
10
- # algorithm must be specified. You can define the default for this value
11
- # like so:
12
- #
13
- # PluginAWeek::EncryptedStrings::ShaCipher.default_salt = 'secret'
14
- #
15
- # If these configuration options are not passed in to #encrypt, then the
16
- # default values will be used. You can override the default values like so:
17
- #
18
- # password = 'shhhh'
19
- # password.encrypt(:sha, :salt => 'secret') # => "ae645b35bb5dfea6c9133ac872e6adfa92a3c2bd"
20
- #
21
- # == Decrypting
22
- #
23
- # SHA-encrypted strings cannot be decrypted. The only way to determine
24
- # whether an unencrypted value is equal to an SHA-encrypted string is to
25
- # encrypt the value with the same salt. For example,
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.
26
42
  #
27
- # password = 'shhhh'.encrypt(:sha, :salt => 'secret') # => "3b22cbe4acde873c3efc82681096f3ae69aff828"
28
- # input = 'shhhh'.encrypt(:sha, :salt => 'secret') # => "3b22cbe4acde873c3efc82681096f3ae69aff828"
29
- # password == input # => true
30
- class ShaCipher < Cipher
31
- class << self
32
- # The default salt value to use during encryption
33
- attr_accessor :default_salt
34
- end
35
-
36
- # Set defaults
37
- @default_salt = 'salt'
43
+ # Configuration options:
44
+ # * +salt+ - Random bytes used as one of the inputs for generating the encrypted string
45
+ def initialize(options = {})
46
+ invalid_options = options.keys - [:salt]
47
+ raise ArgumentError, "Unknown key(s): #{invalid_options.join(", ")}" unless invalid_options.empty?
38
48
 
39
- # The salt value to use for encryption
40
- attr_accessor :salt
49
+ options = {:salt => ShaCipher.default_salt}.merge(options)
41
50
 
42
- # Creates a new cipher that uses an SHA encryption strategy.
43
- #
44
- # Configuration options:
45
- # * +salt+ - Random bytes used as one of the inputs for generating 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
51
+ self.salt = options[:salt].to_s
56
52
 
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
53
+ super()
54
+ end
55
+
56
+ # Decryption is not supported
57
+ def can_decrypt?
58
+ false
59
+ end
60
+
61
+ # Returns the encrypted value of the data
62
+ def encrypt(data)
63
+ Digest::SHA1.hexdigest(data + salt)
66
64
  end
67
65
  end
68
66
  end
@@ -1,102 +1,100 @@
1
- module PluginAWeek #:nodoc:
2
- module EncryptedStrings
3
- # Indicates no password was specified for the symmetric cipher
4
- class NoPasswordError < StandardError
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
5
48
  end
6
49
 
7
- # Symmetric encryption uses a specific algorithm and password to encrypt
8
- # the string. As long as the algorithm and password are known, the string
9
- # can be decrypted.
10
- #
11
- # Source: http://support.microsoft.com/kb/246071
12
- #
13
- # == Encrypting
14
- #
15
- # To encrypt a string using a symmetric cipher, the algorithm and password
16
- # must be specified. You can define the defaults for these values like so:
17
- #
18
- # PluginAWeek::EncryptedStrings::SymmetricCipher.default_algorithm = 'des-ecb'
19
- # PluginAWeek::EncryptedStrings::SymmetricCipher.default_password = 'secret'
20
- #
21
- # If these configuration options are not passed in to #encrypt, then the
22
- # default values will be used. You can override the default values like so:
23
- #
24
- # password = 'shhhh'
25
- # password.encrypt(:symmetric, :algorithm => 'des-ecb', :password => 'secret') # => "S/sEkViX3v4=\n"
26
- #
27
- # An exception will be raised if no password is specified.
28
- #
29
- # == Decrypting
30
- #
31
- # To decrypt a string using an symmetric cipher, the algorithm and password
32
- # must be specified. Defaults for these values can be 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 = "S/sEkViX3v4=\n"
38
- # password.decrypt(:symmetric, :algorithm => 'des-ecb', :password => 'secret') # => "shhhh"
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.
39
61
  #
40
- # An exception will be raised if no password is specified.
41
- class SymmetricCipher < Cipher
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
- end
50
-
51
- # Set default values
52
- @default_algorithm = 'DES-EDE3-CBC'
53
-
54
- # The algorithm to use for encryption/decryption
55
- attr_accessor :algorithm
62
+ # Configuration options:
63
+ # * +algorithm+ - The algorithm to use for generating the encrypted string
64
+ # * +password+ - The secret value to use for generating the key/initialization vector for the algorithm
65
+ def initialize(options = {})
66
+ invalid_options = options.keys - [:algorithm, :password]
67
+ raise ArgumentError, "Unknown key(s): #{invalid_options.join(", ")}" unless invalid_options.empty?
56
68
 
57
- # The password that generates the key/initialization vector for the
58
- # algorithm
59
- attr_accessor :password
69
+ options = {
70
+ :algorithm => SymmetricCipher.default_algorithm,
71
+ :password => SymmetricCipher.default_password
72
+ }.merge(options)
60
73
 
61
- # Creates a new cipher that uses a symmetric encryption strategy.
62
- #
63
- # Configuration options:
64
- # * +algorithm+ - The algorithm to use for generating the encrypted string
65
- # * +password+ - The secret value to use for generating the 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(Base64.decode64(data)) + cipher.final
86
- end
74
+ self.algorithm = options[:algorithm]
75
+ self.password = options[:password]
76
+ raise NoPasswordError if password.nil?
87
77
 
88
- # Encrypts the current string using the current key and algorithm specified
89
- def encrypt(data)
90
- cipher = build_cipher(:encrypt)
91
- Base64.encode64(cipher.update(data) + cipher.final)
92
- end
93
-
94
- private
95
- def build_cipher(type) #:nodoc:
96
- cipher = OpenSSL::Cipher.new(algorithm).send(type)
97
- cipher.pkcs5_keyivgen(password)
98
- cipher
99
- end
78
+ super()
79
+ end
80
+
81
+ # Decrypts the current string using the current key and algorithm specified
82
+ def decrypt(data)
83
+ cipher = build_cipher(:decrypt)
84
+ cipher.update(Base64.decode64(data)) + cipher.final
100
85
  end
86
+
87
+ # Encrypts the current string using the current key and algorithm specified
88
+ def encrypt(data)
89
+ cipher = build_cipher(:encrypt)
90
+ Base64.encode64(cipher.update(data) + cipher.final)
91
+ end
92
+
93
+ private
94
+ def build_cipher(type) #:nodoc:
95
+ cipher = OpenSSL::Cipher.new(algorithm).send(type)
96
+ cipher.pkcs5_keyivgen(password)
97
+ cipher
98
+ end
101
99
  end
102
100
  end
@@ -2,27 +2,27 @@ require File.dirname(__FILE__) + '/test_helper'
2
2
 
3
3
  class NoPrivateKeyErrorTest < Test::Unit::TestCase
4
4
  def test_should_exist
5
- assert_not_nil PluginAWeek::EncryptedStrings::NoPrivateKeyError
5
+ assert_not_nil EncryptedStrings::NoPrivateKeyError
6
6
  end
7
7
  end
8
8
 
9
9
  class NoPublicKeyErrorTest < Test::Unit::TestCase
10
10
  def test_should_exist
11
- assert_not_nil PluginAWeek::EncryptedStrings::NoPublicKeyError
11
+ assert_not_nil EncryptedStrings::NoPublicKeyError
12
12
  end
13
13
  end
14
14
 
15
15
  class AsymmetricCipherByDefaultTest < Test::Unit::TestCase
16
16
  def setup
17
- @asymmetric_cipher = PluginAWeek::EncryptedStrings::AsymmetricCipher.new(:public_key_file => File.dirname(__FILE__) + '/keys/public')
17
+ @asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:public_key_file => File.dirname(__FILE__) + '/keys/public')
18
18
  end
19
19
 
20
20
  def test_should_raise_an_exception
21
- assert_raise(ArgumentError) {PluginAWeek::EncryptedStrings::AsymmetricCipher.new}
21
+ assert_raise(ArgumentError) {EncryptedStrings::AsymmetricCipher.new}
22
22
  end
23
23
 
24
24
  def test_should_not_have_a_public_key_file
25
- @asymmetric_cipher = PluginAWeek::EncryptedStrings::AsymmetricCipher.new(:private_key_file => File.dirname(__FILE__) + '/keys/private')
25
+ @asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:private_key_file => File.dirname(__FILE__) + '/keys/private')
26
26
  assert_nil @asymmetric_cipher.public_key_file
27
27
  end
28
28
 
@@ -41,13 +41,13 @@ end
41
41
 
42
42
  class AsymmetricCipherWithCustomDefaultsTest < Test::Unit::TestCase
43
43
  def setup
44
- @original_default_public_key_file = PluginAWeek::EncryptedStrings::AsymmetricCipher.default_public_key_file
45
- @original_default_private_key_file = PluginAWeek::EncryptedStrings::AsymmetricCipher.default_private_key_file
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
46
 
47
- PluginAWeek::EncryptedStrings::AsymmetricCipher.default_public_key_file = File.dirname(__FILE__) + '/keys/public'
48
- PluginAWeek::EncryptedStrings::AsymmetricCipher.default_private_key_file = File.dirname(__FILE__) + '/keys/private'
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
49
 
50
- @asymmetric_cipher = PluginAWeek::EncryptedStrings::AsymmetricCipher.new
50
+ @asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new
51
51
  end
52
52
 
53
53
  def test_should_use_default_public_key_file
@@ -67,20 +67,20 @@ class AsymmetricCipherWithCustomDefaultsTest < Test::Unit::TestCase
67
67
  end
68
68
 
69
69
  def teardown
70
- PluginAWeek::EncryptedStrings::AsymmetricCipher.default_public_key_file = @original_default_public_key_file
71
- PluginAWeek::EncryptedStrings::AsymmetricCipher.default_private_key_file = @original_default_private_key_file
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
72
  end
73
73
  end
74
74
 
75
75
  class AsymmetricCipherWithInvalidOptionsTest < Test::Unit::TestCase
76
76
  def test_should_throw_an_exception
77
- assert_raise(ArgumentError) {PluginAWeek::EncryptedStrings::AsymmetricCipher.new(:invalid => true)}
77
+ assert_raise(ArgumentError) {EncryptedStrings::AsymmetricCipher.new(:invalid => true)}
78
78
  end
79
79
  end
80
80
 
81
81
  class AsymmetricCipherTest < Test::Unit::TestCase
82
82
  def setup
83
- @asymmetric_cipher = PluginAWeek::EncryptedStrings::AsymmetricCipher.new(:public_key_file => File.dirname(__FILE__) + '/keys/public')
83
+ @asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:public_key_file => File.dirname(__FILE__) + '/keys/public')
84
84
  end
85
85
 
86
86
  def test_should_be_able_to_decrypt
@@ -90,7 +90,7 @@ end
90
90
 
91
91
  class AsymmetricCipherWithoutPublicKeyTest < Test::Unit::TestCase
92
92
  def setup
93
- @asymmetric_cipher = PluginAWeek::EncryptedStrings::AsymmetricCipher.new(:public_key_file => nil, :private_key_file => File.dirname(__FILE__) + '/keys/private')
93
+ @asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:public_key_file => nil, :private_key_file => File.dirname(__FILE__) + '/keys/private')
94
94
  end
95
95
 
96
96
  def test_should_not_be_public
@@ -98,13 +98,13 @@ class AsymmetricCipherWithoutPublicKeyTest < Test::Unit::TestCase
98
98
  end
99
99
 
100
100
  def test_should_not_be_able_to_encrypt
101
- assert_raise(PluginAWeek::EncryptedStrings::NoPublicKeyError) {@asymmetric_cipher.encrypt('test')}
101
+ assert_raise(EncryptedStrings::NoPublicKeyError) {@asymmetric_cipher.encrypt('test')}
102
102
  end
103
103
  end
104
104
 
105
105
  class AsymmetricCipherWithPublicKeyTest < Test::Unit::TestCase
106
106
  def setup
107
- @asymmetric_cipher = PluginAWeek::EncryptedStrings::AsymmetricCipher.new(:public_key_file => File.dirname(__FILE__) + '/keys/public')
107
+ @asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:public_key_file => File.dirname(__FILE__) + '/keys/public')
108
108
  end
109
109
 
110
110
  def test_should_be_public
@@ -120,13 +120,13 @@ class AsymmetricCipherWithPublicKeyTest < Test::Unit::TestCase
120
120
  end
121
121
 
122
122
  def test_should_not_be_able_to_decrypt
123
- assert_raise(PluginAWeek::EncryptedStrings::NoPrivateKeyError) {@asymmetric_cipher.decrypt("HbEh0Hwri26S7SWYqO26DBbzfhR1h/0pXYLjSKUpxF5DOaOCtD9oRN748+Na\nrfNaVN5Eg7RUhbRFZE+UnNHo6Q==\n")}
123
+ assert_raise(EncryptedStrings::NoPrivateKeyError) {@asymmetric_cipher.decrypt("HbEh0Hwri26S7SWYqO26DBbzfhR1h/0pXYLjSKUpxF5DOaOCtD9oRN748+Na\nrfNaVN5Eg7RUhbRFZE+UnNHo6Q==\n")}
124
124
  end
125
125
  end
126
126
 
127
127
  class AsymmetricCipherWithoutPrivateKeyTest < Test::Unit::TestCase
128
128
  def setup
129
- @asymmetric_cipher = PluginAWeek::EncryptedStrings::AsymmetricCipher.new(:private_key_file => nil, :public_key_file => File.dirname(__FILE__) + '/keys/public')
129
+ @asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:private_key_file => nil, :public_key_file => File.dirname(__FILE__) + '/keys/public')
130
130
  end
131
131
 
132
132
  def test_should_not_be_private
@@ -134,13 +134,13 @@ class AsymmetricCipherWithoutPrivateKeyTest < Test::Unit::TestCase
134
134
  end
135
135
 
136
136
  def test_should_not_be_able_to_decrypt
137
- assert_raise(PluginAWeek::EncryptedStrings::NoPrivateKeyError) {@asymmetric_cipher.decrypt("HbEh0Hwri26S7SWYqO26DBbzfhR1h/0pXYLjSKUpxF5DOaOCtD9oRN748+Na\nrfNaVN5Eg7RUhbRFZE+UnNHo6Q==\n")}
137
+ assert_raise(EncryptedStrings::NoPrivateKeyError) {@asymmetric_cipher.decrypt("HbEh0Hwri26S7SWYqO26DBbzfhR1h/0pXYLjSKUpxF5DOaOCtD9oRN748+Na\nrfNaVN5Eg7RUhbRFZE+UnNHo6Q==\n")}
138
138
  end
139
139
  end
140
140
 
141
141
  class AsymmetricCipherWithPrivateKeyTest < Test::Unit::TestCase
142
142
  def setup
143
- @asymmetric_cipher = PluginAWeek::EncryptedStrings::AsymmetricCipher.new(:private_key_file => File.dirname(__FILE__) + '/keys/private')
143
+ @asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:private_key_file => File.dirname(__FILE__) + '/keys/private')
144
144
  end
145
145
 
146
146
  def test_should_not_be_public
@@ -152,7 +152,7 @@ class AsymmetricCipherWithPrivateKeyTest < Test::Unit::TestCase
152
152
  end
153
153
 
154
154
  def test_not_should_be_able_to_encrypt
155
- assert_raise(PluginAWeek::EncryptedStrings::NoPublicKeyError) {@asymmetric_cipher.encrypt('test')}
155
+ assert_raise(EncryptedStrings::NoPublicKeyError) {@asymmetric_cipher.encrypt('test')}
156
156
  end
157
157
 
158
158
  def test_should_be_able_to_decrypt
@@ -162,7 +162,7 @@ end
162
162
 
163
163
  class AsymmetricCipherWithEncryptedPrivateKeyTest < Test::Unit::TestCase
164
164
  def setup
165
- @asymmetric_cipher = PluginAWeek::EncryptedStrings::AsymmetricCipher.new(:private_key_file => File.dirname(__FILE__) + '/keys/encrypted_private', :algorithm => 'DES-EDE3-CBC', :password => 'secret')
165
+ @asymmetric_cipher = EncryptedStrings::AsymmetricCipher.new(:private_key_file => File.dirname(__FILE__) + '/keys/encrypted_private', :algorithm => 'DES-EDE3-CBC', :password => 'secret')
166
166
  end
167
167
 
168
168
  def test_should_not_be_public
@@ -174,7 +174,7 @@ class AsymmetricCipherWithEncryptedPrivateKeyTest < Test::Unit::TestCase
174
174
  end
175
175
 
176
176
  def test_should_not_be_able_to_encrypt
177
- assert_raise(PluginAWeek::EncryptedStrings::NoPublicKeyError) {@asymmetric_cipher.encrypt('test')}
177
+ assert_raise(EncryptedStrings::NoPublicKeyError) {@asymmetric_cipher.encrypt('test')}
178
178
  end
179
179
 
180
180
  def test_should_be_able_to_decrypt