encrypted_strings 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +15 -0
- data/README +23 -28
- data/Rakefile +3 -3
- data/lib/encrypted_strings/asymmetric_encryptor.rb +57 -17
- data/lib/encrypted_strings/encryptor.rb +18 -17
- data/lib/encrypted_strings/extensions/string.rb +98 -25
- data/lib/encrypted_strings/no_key_error.rb +2 -2
- data/lib/encrypted_strings/no_private_key_error.rb +2 -2
- data/lib/encrypted_strings/no_public_key_error.rb +2 -2
- data/lib/encrypted_strings/sha_encryptor.rb +26 -2
- data/lib/encrypted_strings/symmetric_encryptor.rb +35 -4
- data/test/asymmetric_encryptor_test.rb +5 -5
- data/test/encryptor_test.rb +14 -14
- data/test/string_test.rb +105 -77
- data/test/symmetric_encryptor_test.rb +5 -5
- metadata +24 -23
data/CHANGELOG
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
*SVN*
|
2
|
+
|
3
|
+
*0.0.2* (August 23rd, 2007)
|
4
|
+
|
5
|
+
* Fix not allowing the decryption mode to be overriden if the string already has an encryptor
|
6
|
+
|
7
|
+
* Convert dos newlines to unix newlines
|
8
|
+
|
9
|
+
*0.0.1* (August 5th, 2007)
|
10
|
+
|
11
|
+
* Official public release
|
12
|
+
|
13
|
+
* Add api documentation
|
14
|
+
|
15
|
+
* Refactor unit test names
|
data/README
CHANGED
@@ -12,26 +12,28 @@ Wiki
|
|
12
12
|
|
13
13
|
* http://wiki.pluginaweek.org/Encrypted_strings
|
14
14
|
|
15
|
-
|
15
|
+
Announcement
|
16
16
|
|
17
17
|
* http://www.pluginaweek.org/
|
18
18
|
|
19
|
-
|
19
|
+
Source
|
20
20
|
|
21
21
|
* http://svn.pluginaweek.org/trunk/plugins/ruby/string/encrypted_strings
|
22
22
|
|
23
|
-
|
23
|
+
Development
|
24
24
|
|
25
25
|
* http://dev.pluginaweek.org/browse/trunk/plugins/ruby/string/encrypted_strings
|
26
26
|
|
27
|
-
==
|
27
|
+
== Description
|
28
28
|
|
29
|
-
|
29
|
+
Encrypting and decrypting data is not exactly the most straightforward and DRY
|
30
|
+
way. encrypted_strings greatly improves upon this syntax and adds
|
31
|
+
straightforward support for encrypting values using SHA-1, Symmetric, and
|
32
|
+
Asymmetric modes.
|
30
33
|
|
31
|
-
==
|
34
|
+
== Usage
|
32
35
|
|
33
|
-
|
34
|
-
class, giving you the ability to easily encrypt strings.
|
36
|
+
=== SHA Encryption
|
35
37
|
|
36
38
|
>> password = "shhhh"
|
37
39
|
=> "shhhh"
|
@@ -55,7 +57,7 @@ SHA-1 encryption. For encryption modes that do not support decryption, equality
|
|
55
57
|
with other strings is tested by encrypting the other string and checking whether
|
56
58
|
the resulting encrypted value is the same.
|
57
59
|
|
58
|
-
|
60
|
+
=== Symmetric Encryption
|
59
61
|
|
60
62
|
>> password = "shhhh"
|
61
63
|
=> "shhhh"
|
@@ -70,28 +72,21 @@ If you wanted to use symmetric encryption, you could do so with the following:
|
|
70
72
|
|
71
73
|
=== Asymmetric encryption
|
72
74
|
|
73
|
-
The public and private key file names can be set via the following:
|
74
|
-
|
75
|
-
PluginAWeek::EncryptedStrings::AsymmetricEncryptor.default_public_key_file = "./public.key"
|
76
|
-
PluginAWeek::EncryptedStrings::AsymmetricEncryptor.default_private_key_file = "./private.key"
|
77
|
-
|
78
|
-
== In-place editing
|
79
|
-
|
80
|
-
In addition to generating the encrypted/decrypted strings, you can also
|
81
|
-
replace the original string by using the bang:
|
82
|
-
|
83
75
|
>> password = "shhhh"
|
84
76
|
=> "shhhh"
|
85
|
-
>> password.encrypt
|
86
|
-
=> "
|
87
|
-
>>
|
88
|
-
=>
|
89
|
-
>>
|
90
|
-
=>
|
91
|
-
>> password
|
77
|
+
>> crypted_password = password.encrypt(:asymmetric, :public_key_file => "./public.key", :private_key_file => "./private.key")
|
78
|
+
=> "NEwVzcikYUKfS8HTc9L9eg/dMxBCLZ/nFr7J1aQYjkl3I2MPUD0lmjr/saC6\nTJEPwOl60Ki24H8TUwnGtZy14A==\n"
|
79
|
+
>> crypted_password.class
|
80
|
+
=> String
|
81
|
+
>> crypted_password == "shhhh"
|
82
|
+
=> true
|
83
|
+
>> password = crypted_password.decrypt
|
92
84
|
=> "shhhh"
|
93
85
|
|
86
|
+
== Dependencies
|
87
|
+
|
88
|
+
This plugin does not depend on the presence of any other plugins.
|
89
|
+
|
94
90
|
== References
|
95
91
|
|
96
|
-
|
97
|
-
Much of this plugin's code is based on his work.
|
92
|
+
* Rick Olson - http://svn.techno-weenie.net/projects/plugins/sentry/
|
data/Rakefile
CHANGED
@@ -4,7 +4,7 @@ require 'rake/gempackagetask'
|
|
4
4
|
require 'rake/contrib/sshpublisher'
|
5
5
|
|
6
6
|
PKG_NAME = 'encrypted_strings'
|
7
|
-
PKG_VERSION = '0.0.
|
7
|
+
PKG_VERSION = '0.0.2'
|
8
8
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
9
9
|
RUBY_FORGE_PROJECT = 'pluginaweek'
|
10
10
|
|
@@ -33,7 +33,7 @@ spec = Gem::Specification.new do |s|
|
|
33
33
|
s.platform = Gem::Platform::RUBY
|
34
34
|
s.summary = 'Dead-simple string encryption/decryption syntax.'
|
35
35
|
|
36
|
-
s.files = FileList['{lib,
|
36
|
+
s.files = FileList['{lib,test}/**/*'].to_a + %w(CHANGELOG init.rb MIT-LICENSE Rakefile README)
|
37
37
|
s.require_path = 'lib'
|
38
38
|
s.autorequire = 'encrypted_strings'
|
39
39
|
s.has_rdoc = true
|
@@ -77,4 +77,4 @@ task :release => [:gem, :package] do
|
|
77
77
|
|
78
78
|
ruby_forge.add_release(RUBY_FORGE_PROJECT, PKG_NAME, PKG_VERSION, file)
|
79
79
|
end
|
80
|
-
end
|
80
|
+
end
|
@@ -2,14 +2,52 @@ require 'encrypted_strings/no_private_key_error'
|
|
2
2
|
require 'encrypted_strings/no_public_key_error'
|
3
3
|
|
4
4
|
module PluginAWeek #:nodoc:
|
5
|
-
module EncryptedStrings
|
6
|
-
# Encryption in which the keys used to encrypt/decrypt come in pairs. Also
|
7
|
-
# as public key encryption. Anything that's encrypted using the
|
8
|
-
# only be decrypted with the same algorithm and a matching
|
9
|
-
# Any message that is encrypted with the private key can only
|
10
|
-
# with the matching public key.
|
5
|
+
module EncryptedStrings
|
6
|
+
# Encryption in which the keys used to encrypt/decrypt come in pairs. Also
|
7
|
+
# known as public key encryption. Anything that's encrypted using the
|
8
|
+
# public key can only be decrypted with the same algorithm and a matching
|
9
|
+
# private key. Any message that is encrypted with the private key can only
|
10
|
+
# be decrypted with the matching public key.
|
11
11
|
#
|
12
|
-
# http://support.microsoft.com/kb/246071
|
12
|
+
# Source: http://support.microsoft.com/kb/246071
|
13
|
+
#
|
14
|
+
# == Encrypting
|
15
|
+
#
|
16
|
+
# To encrypt a string using an asymmetric algorithm, the location of the
|
17
|
+
# public key file must be specified. You can define the default for this
|
18
|
+
# value like so:
|
19
|
+
#
|
20
|
+
# PluginAWeek::EncryptedStrings::AsymmetricEncryptor.default_public_key_file = "./public.key"
|
21
|
+
#
|
22
|
+
# If these configuration options are not passed in to #encrypt, then the
|
23
|
+
# default values will be used. You can override the default values like so:
|
24
|
+
#
|
25
|
+
# password = "shhhh"
|
26
|
+
# password.encrypt(:asymmetic, :public_key_file => "./encrypted_public.key") # => "INy95irZ8AlHmvc6ZAF/ARsTpbqPIB/4bEAKKOebjsayB7NYWtIzpswvzxqf\nNJ5yyuvxfMODrcg7RimEMFkFlg==\n"
|
27
|
+
#
|
28
|
+
# An exception will be raised if either the public key file could not be
|
29
|
+
# found or the key could not decrypt the public key file.
|
30
|
+
#
|
31
|
+
# == Decrypting
|
32
|
+
#
|
33
|
+
# To decrypt a string using an asymmetric algorithm, the location of the
|
34
|
+
# private key file must be specified. If this file is itself encrypted, you
|
35
|
+
# must also specify the algorithm and key used to seed the symmetric
|
36
|
+
# algorithm that will decrypt the plublic key file. You can define defaults
|
37
|
+
# for these values like so:
|
38
|
+
#
|
39
|
+
# PluginAWeek::EncryptedStrings::AsymmetricEncryptor.default_private_key_file = "./private.key"
|
40
|
+
# PluginAWeek::EncryptedStrings::SymmetricEncryptor.default_algorithm = "DES-EDE3-CBC"
|
41
|
+
# PluginAWeek::EncryptedStrings::SymmetricEncryptor.default_key = "secret_key"
|
42
|
+
#
|
43
|
+
# If these configuration options are not passed in to #decrypt, then the
|
44
|
+
# default values will be used. You can override the default values like so:
|
45
|
+
#
|
46
|
+
# password = "INy95irZ8AlHmvc6ZAF/ARsTpbqPIB/4bEAKKOebjsayB7NYWtIzpswvzxqf\nNJ5yyuvxfMODrcg7RimEMFkFlg==\n"
|
47
|
+
# password.decrypt(:asymmetic, :public_key_file => "./encrypted_private.key", :key => "secret") # => "shhhh"
|
48
|
+
#
|
49
|
+
# An exception will be raised if either the private key file could not be
|
50
|
+
# found or the key could not decrypt the private key file.
|
13
51
|
class AsymmetricEncryptor < Encryptor
|
14
52
|
# The default private key to use during encryption. Default is nil.
|
15
53
|
@@default_private_key_file = nil
|
@@ -100,7 +138,7 @@ module PluginAWeek #:nodoc:
|
|
100
138
|
end
|
101
139
|
|
102
140
|
private
|
103
|
-
def load_private_key
|
141
|
+
def load_private_key
|
104
142
|
@private_rsa = nil
|
105
143
|
|
106
144
|
if @private_key_file && File.file?(@private_key_file)
|
@@ -108,7 +146,7 @@ module PluginAWeek #:nodoc:
|
|
108
146
|
end
|
109
147
|
end
|
110
148
|
|
111
|
-
def load_public_key
|
149
|
+
def load_public_key
|
112
150
|
@public_rsa = nil
|
113
151
|
|
114
152
|
if @public_key_file && File.file?(@public_key_file)
|
@@ -116,18 +154,20 @@ module PluginAWeek #:nodoc:
|
|
116
154
|
end
|
117
155
|
end
|
118
156
|
|
119
|
-
# Retrieves private RSA from the
|
120
|
-
def private_rsa
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
157
|
+
# Retrieves private RSA from the private key
|
158
|
+
def private_rsa
|
159
|
+
if @key
|
160
|
+
private_key = @private_key.decrypt(:symmetric, :key => @key, :algorithm => @algorithm)
|
161
|
+
OpenSSL::PKey::RSA.new(private_key)
|
162
|
+
else
|
163
|
+
@private_rsa ||= OpenSSL::PKey::RSA.new(@private_key)
|
164
|
+
end
|
125
165
|
end
|
126
166
|
|
127
167
|
# Retrieves the public RSA
|
128
|
-
def public_rsa
|
168
|
+
def public_rsa
|
129
169
|
@public_rsa ||= OpenSSL::PKey::RSA.new(@public_key)
|
130
170
|
end
|
131
171
|
end
|
132
172
|
end
|
133
|
-
end
|
173
|
+
end
|
@@ -1,17 +1,18 @@
|
|
1
|
-
module PluginAWeek #:nodoc:
|
2
|
-
module EncryptedStrings
|
3
|
-
# Represents an encryptor for strings. Certain encryption algorithms
|
4
|
-
# do not allow for strings to be decrypted.
|
5
|
-
class Encryptor
|
6
|
-
# Can this string be decrypted?
|
7
|
-
def can_decrypt?
|
8
|
-
true
|
9
|
-
end
|
10
|
-
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
1
|
+
module PluginAWeek #:nodoc:
|
2
|
+
module EncryptedStrings
|
3
|
+
# Represents an encryptor for strings. Certain encryption algorithms
|
4
|
+
# do not allow for strings to be decrypted.
|
5
|
+
class Encryptor
|
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
|
18
|
+
end
|
@@ -2,9 +2,9 @@ require 'openssl'
|
|
2
2
|
require 'base64'
|
3
3
|
|
4
4
|
module PluginAWeek #:nodoc:
|
5
|
-
module EncryptedStrings
|
5
|
+
module EncryptedStrings
|
6
6
|
module Extensions #:nodoc:
|
7
|
-
# Adds encryption/decryption
|
7
|
+
# Adds support for encryption/decryption of strings
|
8
8
|
module String
|
9
9
|
def self.included(base) #:nodoc:
|
10
10
|
base.class_eval do
|
@@ -15,19 +15,36 @@ module PluginAWeek #:nodoc:
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
# Encrypts
|
19
|
-
def encrypt!(*args)
|
20
|
-
encrypted_string = encrypt(*args)
|
21
|
-
self.encryptor = encrypted_string.encryptor
|
22
|
-
|
23
|
-
replace(encrypted_string)
|
24
|
-
end
|
25
|
-
|
26
|
-
# Encrypts the current string using the encryption algorithm specified.
|
18
|
+
# Encrypts the current string using the specified encryption mode.
|
27
19
|
# The default encryption mode is sha.
|
28
20
|
#
|
29
|
-
# Configuration options are encryption-
|
30
|
-
# class for that
|
21
|
+
# Configuration options are encryption-specific. See the encryptor
|
22
|
+
# class for that mode to find out the options available.
|
23
|
+
#
|
24
|
+
# == Example
|
25
|
+
#
|
26
|
+
# The following uses SHA mode to encrypt the string:
|
27
|
+
#
|
28
|
+
# password = "shhhh"
|
29
|
+
# password.encrypt # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
30
|
+
#
|
31
|
+
# == Custom encryption mode
|
32
|
+
#
|
33
|
+
# The following uses Symmetric mode (with a default key) to encrypt the
|
34
|
+
# string:
|
35
|
+
#
|
36
|
+
# PluginAWeek::EncryptedStrings::SymmetricEncryptor.default_key = "my_key"
|
37
|
+
# password = "shhhh"
|
38
|
+
# password.encrypt(:symmetric) # => "jDACXI5hMPI=\n"
|
39
|
+
#
|
40
|
+
# == Custom encryption options
|
41
|
+
#
|
42
|
+
# Some encryption modes also support additional configuration options
|
43
|
+
# that determine how to encrypt the string. For example, SHA supports
|
44
|
+
# a salt which seeds the algorithm:
|
45
|
+
#
|
46
|
+
# password = "shhhh"
|
47
|
+
# password.encrypt(:sha, :salt => "secret") # => "3b22cbe4acde873c3efc82681096f3ae69aff828"
|
31
48
|
def encrypt(*args)
|
32
49
|
encryptor = encryptor_from_args(*args)
|
33
50
|
encrypted_string = encryptor.encrypt(self)
|
@@ -36,14 +53,33 @@ module PluginAWeek #:nodoc:
|
|
36
53
|
encrypted_string
|
37
54
|
end
|
38
55
|
|
39
|
-
#
|
40
|
-
|
41
|
-
|
56
|
+
# Encrypts this string and replaces it with the encrypted value. This
|
57
|
+
# takes the same parameters as #encrypt, but returns the same string
|
58
|
+
# instead of a different one.
|
59
|
+
#
|
60
|
+
# For example,
|
61
|
+
#
|
62
|
+
# password = "shhhh"
|
63
|
+
# password.encrypt!(:symmetric, :key => "my_key") # => "jDACXI5hMPI=\n"
|
64
|
+
# password # => "jDACXI5hMPI=\n"
|
65
|
+
def encrypt!(*args)
|
66
|
+
encrypted_string = encrypt(*args)
|
67
|
+
self.encryptor = encrypted_string.encryptor
|
68
|
+
|
69
|
+
replace(encrypted_string)
|
42
70
|
end
|
43
71
|
|
44
|
-
#
|
45
|
-
|
46
|
-
|
72
|
+
# Is this string encrypted? This will return true if the string is the
|
73
|
+
# result of a call to #encrypt or #encrypt! was previously invoked.
|
74
|
+
#
|
75
|
+
# For example,
|
76
|
+
#
|
77
|
+
# password = "shhhh"
|
78
|
+
# password.encrypted? # => false
|
79
|
+
# password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
80
|
+
# password.encrypted? # => true
|
81
|
+
def encrypted?
|
82
|
+
!@encryptor.nil?
|
47
83
|
end
|
48
84
|
|
49
85
|
# Decrypts this string. If this is not a string that was previously encrypted,
|
@@ -52,18 +88,55 @@ module PluginAWeek #:nodoc:
|
|
52
88
|
def decrypt(*args)
|
53
89
|
raise ArgumentError, "An encrypt algorithm must be specified since we can't figure it out" if args.empty? && !@encryptor
|
54
90
|
|
55
|
-
encryptor = @encryptor || encryptor_from_args(*args)
|
56
|
-
encryptor.decrypt(self)
|
91
|
+
encryptor = args.any? ? encryptor_from_args(*args) : (@encryptor || encryptor_from_args(*args))
|
92
|
+
encrypted_string = encryptor.decrypt(self)
|
93
|
+
encrypted_string.encryptor = nil
|
94
|
+
|
95
|
+
encrypted_string
|
57
96
|
end
|
58
97
|
|
59
|
-
#
|
98
|
+
# Decrypts this string and replaces it with the decrypted value This
|
99
|
+
# takes the same parameters as #decrypt, but returns the same string
|
100
|
+
# instead of a different one.
|
101
|
+
#
|
102
|
+
# For example,
|
103
|
+
#
|
104
|
+
# password = "jDACXI5hMPI=\n"
|
105
|
+
# password.decrypt!(:symmetric, :key => "my_key") # => "shhhh"
|
106
|
+
# password # => "shhhh"
|
107
|
+
def decrypt!(*args)
|
108
|
+
replace(decrypt(*args))
|
109
|
+
end
|
110
|
+
|
111
|
+
# Can this string be decrypted? Strings can only be decrypted if they
|
112
|
+
# have previously been decrypted +and+ the encryption algorithm supports
|
113
|
+
# decryption. To determine whether or not the encryption algorithm
|
114
|
+
# supports decryption, see the api for the algorithm's encryptor class.
|
60
115
|
def can_decrypt?
|
61
|
-
|
116
|
+
encrypted? && @encryptor.can_decrypt?
|
62
117
|
end
|
63
118
|
|
64
119
|
# Tests whether the other object is equal to this one. Encrypted strings
|
65
120
|
# will be tested not only on their encrypted strings, but also by
|
66
|
-
# decrypting them and running tests against the decrypted value
|
121
|
+
# decrypting them and running tests against the decrypted value.
|
122
|
+
#
|
123
|
+
# == Equality with strings
|
124
|
+
#
|
125
|
+
# password = "shhhh"
|
126
|
+
# password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
127
|
+
# password # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
128
|
+
# password == "shhhh" # => true
|
129
|
+
#
|
130
|
+
# == Equality with encrypted strings
|
131
|
+
#
|
132
|
+
# password = "shhhh"
|
133
|
+
# password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
134
|
+
# password # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
135
|
+
# password == "shhhh" # => true
|
136
|
+
#
|
137
|
+
# another_password = "shhhh"
|
138
|
+
# another_password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
|
139
|
+
# password == another_password # => true
|
67
140
|
def equals_with_encryption(other)
|
68
141
|
if !(is_equal = equals_without_encryption(other)) && String === other
|
69
142
|
if encrypted?
|
@@ -105,4 +178,4 @@ end
|
|
105
178
|
|
106
179
|
::String.class_eval do
|
107
180
|
include PluginAWeek::EncryptedStrings::Extensions::String
|
108
|
-
end
|
181
|
+
end
|
@@ -1,8 +1,32 @@
|
|
1
1
|
require 'digest/sha1'
|
2
2
|
|
3
3
|
module PluginAWeek #:nodoc:
|
4
|
-
module EncryptedStrings
|
4
|
+
module EncryptedStrings
|
5
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 algorithm, the salt used to seed the
|
10
|
+
# encrypting must be specified. You can define the default for this
|
11
|
+
# value like so:
|
12
|
+
#
|
13
|
+
# PluginAWeek::EncryptedStrings::ShaEncryptor.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 => "my_salt") # => "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,
|
26
|
+
#
|
27
|
+
# password = "shhhh".encrypt(:sha, :salt => "secret") # => "3b22cbe4acde873c3efc82681096f3ae69aff828"
|
28
|
+
# input = "shhhh".encrypt(:sha, :salt => "secret") # => "3b22cbe4acde873c3efc82681096f3ae69aff828"
|
29
|
+
# password == input # => true
|
6
30
|
class ShaEncryptor < Encryptor
|
7
31
|
# The default salt value to use during encryption
|
8
32
|
@@default_salt = 'salt'
|
@@ -32,4 +56,4 @@ module PluginAWeek #:nodoc:
|
|
32
56
|
end
|
33
57
|
end
|
34
58
|
end
|
35
|
-
end
|
59
|
+
end
|
@@ -1,12 +1,43 @@
|
|
1
1
|
require 'encrypted_strings/no_key_error'
|
2
2
|
|
3
3
|
module PluginAWeek #:nodoc:
|
4
|
-
module EncryptedStrings
|
4
|
+
module EncryptedStrings
|
5
5
|
# Symmetric encryption uses a key and a specific algorithm to encrypt the
|
6
6
|
# string. As long as the key and algorithm are known, the string can be
|
7
7
|
# decrypted.
|
8
8
|
#
|
9
|
-
# http://support.microsoft.com/kb/246071
|
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
|
+
# key must be specified. You can define the defaults for these values like
|
15
|
+
# so:
|
16
|
+
#
|
17
|
+
# PluginAWeek::EncryptedStrings::SymmetricEncryptor.default_algorithm = "des-ecb"
|
18
|
+
# PluginAWeek::EncryptedStrings::SymmetricEncryptor.default_key = "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(:symmetic, :algorithm => "des-ecb", :key => "secret") # => "sUG6tYSn0mI=\n"
|
25
|
+
#
|
26
|
+
# An exception will be raised if no key is specified.
|
27
|
+
#
|
28
|
+
# == Decrypting
|
29
|
+
#
|
30
|
+
# To decrypt a string using an symmetric algorithm, the type of algorithm
|
31
|
+
# and key must also be specified. Defaults for these values can be defined
|
32
|
+
# 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(:symmetic, :algorithm => "des-ecb", :key => "secret") # => "shhhh"
|
39
|
+
#
|
40
|
+
# An exception will be raised if no key is specified.
|
10
41
|
class SymmetricEncryptor < Encryptor
|
11
42
|
# The default algorithm to use for encryption. Default is DES
|
12
43
|
@@default_algorithm = 'DES-EDE3-CBC'
|
@@ -29,7 +60,7 @@ module PluginAWeek #:nodoc:
|
|
29
60
|
:algorithm
|
30
61
|
)
|
31
62
|
options.reverse_merge!(:key => @@default_key)
|
32
|
-
options[:algorithm] ||= @@default_algorithm
|
63
|
+
options[:algorithm] ||= @@default_algorithm
|
33
64
|
|
34
65
|
@key = options[:key]
|
35
66
|
raise NoKeyError if @key.nil?
|
@@ -61,4 +92,4 @@ module PluginAWeek #:nodoc:
|
|
61
92
|
end
|
62
93
|
end
|
63
94
|
end
|
64
|
-
end
|
95
|
+
end
|
@@ -34,7 +34,7 @@ class AsymmetricEncryptorTest < Test::Unit::TestCase
|
|
34
34
|
assert encryptor.public?
|
35
35
|
assert encryptor.private?
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
def test_should_read_encrypted_key_files
|
39
39
|
encryptor = PluginAWeek::EncryptedStrings::AsymmetricEncryptor.new(
|
40
40
|
:public_key_file => @encrypted_public_key_file,
|
@@ -43,7 +43,7 @@ class AsymmetricEncryptorTest < Test::Unit::TestCase
|
|
43
43
|
assert encryptor.public?
|
44
44
|
assert encryptor.private?
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
def test_should_decrypt_files
|
48
48
|
encryptor = PluginAWeek::EncryptedStrings::AsymmetricEncryptor.new(
|
49
49
|
:public_key_file => @public_key_file,
|
@@ -52,7 +52,7 @@ class AsymmetricEncryptorTest < Test::Unit::TestCase
|
|
52
52
|
|
53
53
|
assert_equal @data, encryptor.decrypt(@encrypted_data)
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
def test_should_decrypt_files_with_encrypted_key
|
57
57
|
encryptor = PluginAWeek::EncryptedStrings::AsymmetricEncryptor.new(
|
58
58
|
:public_key_file => @encrypted_public_key_file,
|
@@ -62,7 +62,7 @@ class AsymmetricEncryptorTest < Test::Unit::TestCase
|
|
62
62
|
|
63
63
|
assert_equal @data, encryptor.decrypt(@encrypted_data_with_encrypted_keys)
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
def test_should_decrypt_files_with_default_key
|
67
67
|
set_default_key_files @public_key_file, @private_key_file
|
68
68
|
assert_equal @data, PluginAWeek::EncryptedStrings::AsymmetricEncryptor.new.decrypt(@encrypted_data)
|
@@ -94,4 +94,4 @@ class AsymmetricEncryptorTest < Test::Unit::TestCase
|
|
94
94
|
PluginAWeek::EncryptedStrings::AsymmetricEncryptor.default_public_key_file = public_key
|
95
95
|
PluginAWeek::EncryptedStrings::AsymmetricEncryptor.default_private_key_file = private_key
|
96
96
|
end
|
97
|
-
end
|
97
|
+
end
|
data/test/encryptor_test.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
-
|
3
|
-
class EncryptorTest < Test::Unit::TestCase
|
4
|
-
def setup
|
5
|
-
@encryptor = PluginAWeek::EncryptedStrings::Encryptor.new
|
6
|
-
end
|
7
|
-
|
8
|
-
def test_should_be_able_to_decrypt_by_default
|
9
|
-
assert @encryptor.can_decrypt?
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_should_raise_exception_if_decrypt_not_implemented
|
13
|
-
assert_raises(NotImplementedError) { @encryptor.decrypt('test') }
|
14
|
-
end
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
class EncryptorTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@encryptor = PluginAWeek::EncryptedStrings::Encryptor.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_should_be_able_to_decrypt_by_default
|
9
|
+
assert @encryptor.can_decrypt?
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_should_raise_exception_if_decrypt_not_implemented
|
13
|
+
assert_raises(NotImplementedError) { @encryptor.decrypt('test') }
|
14
|
+
end
|
15
15
|
end
|
data/test/string_test.rb
CHANGED
@@ -1,77 +1,105 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
-
|
3
|
-
class EncryptedStringsTest < Test::Unit::TestCase
|
4
|
-
def test_should_use_sha_for_default_encryption
|
5
|
-
assert_instance_of PluginAWeek::EncryptedStrings::ShaEncryptor, 'test'.encrypt.encryptor
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
encrypted_string.
|
37
|
-
|
38
|
-
assert !
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
assert_equal
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
class EncryptedStringsTest < Test::Unit::TestCase
|
4
|
+
def test_should_use_sha_for_default_encryption
|
5
|
+
assert_instance_of PluginAWeek::EncryptedStrings::ShaEncryptor, 'test'.encrypt.encryptor
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_should_use_configuration_options_for_default_encryption
|
9
|
+
encrypted_string = 'test'.encrypt(:salt => 'different_salt')
|
10
|
+
assert_instance_of PluginAWeek::EncryptedStrings::ShaEncryptor, encrypted_string.encryptor
|
11
|
+
assert_equal 'different_salt', encrypted_string.encryptor.salt
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_use_custom_encryptor_if_mode_specified
|
15
|
+
encrypted_string = 'test'.encrypt(:symmetric, :key => 'key')
|
16
|
+
assert_instance_of PluginAWeek::EncryptedStrings::SymmetricEncryptor, encrypted_string.encryptor
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_replace_string_with_bang_encryption
|
20
|
+
encrypted_string = 'test'
|
21
|
+
encrypted_string.encrypt!
|
22
|
+
|
23
|
+
assert !'test'.equals_without_encryption(encrypted_string)
|
24
|
+
assert_instance_of PluginAWeek::EncryptedStrings::ShaEncryptor, encrypted_string.encryptor
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_be_encrypted_if_string_has_been_encrypted
|
28
|
+
assert 'test'.encrypt.encrypted?
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_should_not_be_encrypted_if_string_has_not_been_encrypted
|
32
|
+
assert !'test'.encrypted?
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_should_not_be_encrypted_after_being_decrypted
|
36
|
+
encrypted_string = 'test'.encrypt(:symmetric, :key => 'secret')
|
37
|
+
decrypted_string = encrypted_string.decrypt
|
38
|
+
assert !decrypted_string.encrypted?
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_should_use_encryptor_for_decryption_by_default
|
42
|
+
encrypted_string = 'test'.encrypt(:symmetric, :key => 'secret')
|
43
|
+
assert 'test'.equals_without_encryption(encrypted_string.decrypt)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_should_allow_custom_mode_when_decrypting
|
47
|
+
assert_equal 'test', "MU6e/5LvhKA=\n".decrypt(:symmetric, :key => 'secret')
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_should_replace_string_with_bang_decryption
|
51
|
+
encrypted_string = "MU6e/5LvhKA=\n"
|
52
|
+
encrypted_string.decrypt!(:symmetric, :key => 'secret')
|
53
|
+
|
54
|
+
assert !"MU6e/5LvhKA=\n".equals_without_encryption(encrypted_string)
|
55
|
+
assert 'test'.equals_without_encryption(encrypted_string)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_should_be_able_to_decrypt_if_encryptor_can_decrypt
|
59
|
+
assert 'test'.encrypt(:symmetric, :key => 'secret').can_decrypt?
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_should_not_be_able_to_decrypt_if_encryptor_cant_decrypt
|
63
|
+
assert !'test'.encrypt(:sha).can_decrypt?
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_should_not_be_able_to_decrypt_if_never_encrypted
|
67
|
+
assert !'test'.can_decrypt?
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_should_be_able_to_check_equality_without_decryption_support
|
71
|
+
value = 'test'
|
72
|
+
encrypted_string = 'test'.encrypt(:sha)
|
73
|
+
encrypted_encrypted_string = encrypted_string.encrypt(:sha)
|
74
|
+
|
75
|
+
assert_equal value, encrypted_string
|
76
|
+
assert_equal encrypted_string, value
|
77
|
+
assert_equal encrypted_string, encrypted_encrypted_string
|
78
|
+
assert_equal encrypted_encrypted_string, encrypted_string
|
79
|
+
assert_equal encrypted_string.to_s, encrypted_string
|
80
|
+
assert_equal encrypted_string, encrypted_string.to_s
|
81
|
+
assert_equal encrypted_string, encrypted_string
|
82
|
+
|
83
|
+
assert_not_equal value, encrypted_encrypted_string
|
84
|
+
assert_not_equal encrypted_encrypted_string, value
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_should_be_able_to_check_equality_with_decryption_support
|
88
|
+
PluginAWeek::EncryptedStrings::SymmetricEncryptor.default_key = 'secret'
|
89
|
+
|
90
|
+
value = 'test'
|
91
|
+
encrypted_string = value.encrypt(:symmetric)
|
92
|
+
encrypted_encrypted_string = encrypted_string.encrypt(:symmetric)
|
93
|
+
|
94
|
+
assert_equal value, encrypted_string
|
95
|
+
assert_equal encrypted_string, value
|
96
|
+
assert_equal encrypted_string, encrypted_encrypted_string
|
97
|
+
assert_equal encrypted_encrypted_string, encrypted_string
|
98
|
+
assert_equal encrypted_string.to_s, encrypted_string
|
99
|
+
assert_equal encrypted_string, encrypted_string.to_s
|
100
|
+
assert_equal encrypted_string, encrypted_string
|
101
|
+
|
102
|
+
assert_not_equal value, encrypted_encrypted_string
|
103
|
+
assert_not_equal encrypted_encrypted_string, value
|
104
|
+
end
|
105
|
+
end
|
@@ -12,15 +12,15 @@ class SymmetricallyEncryptedStringTest < Test::Unit::TestCase
|
|
12
12
|
assert_raises(PluginAWeek::EncryptedStrings::NoKeyError) { PluginAWeek::EncryptedStrings::SymmetricEncryptor.new }
|
13
13
|
end
|
14
14
|
|
15
|
-
def test_should_encrypt_with_custom_key_if_key_specified
|
16
|
-
assert_equal @encrypted, PluginAWeek::EncryptedStrings::SymmetricEncryptor.new(:key => @key).encrypt(@data)
|
17
|
-
end
|
18
|
-
|
19
15
|
def test_encrypt_with_default_key_if_key_not_specified
|
20
16
|
PluginAWeek::EncryptedStrings::SymmetricEncryptor.default_key = @key
|
21
17
|
assert_equal @encrypted, PluginAWeek::EncryptedStrings::SymmetricEncryptor.new.encrypt(@data)
|
22
18
|
end
|
23
19
|
|
20
|
+
def test_should_encrypt_with_custom_key_if_key_specified
|
21
|
+
assert_equal @encrypted, PluginAWeek::EncryptedStrings::SymmetricEncryptor.new(:key => @key).encrypt(@data)
|
22
|
+
end
|
23
|
+
|
24
24
|
def test_should_be_able_to_decrypt
|
25
25
|
assert PluginAWeek::EncryptedStrings::SymmetricEncryptor.new(:key => @key).can_decrypt?
|
26
26
|
end
|
@@ -33,4 +33,4 @@ class SymmetricallyEncryptedStringTest < Test::Unit::TestCase
|
|
33
33
|
PluginAWeek::EncryptedStrings::SymmetricEncryptor.default_key = @key
|
34
34
|
assert_equal @data, PluginAWeek::EncryptedStrings::SymmetricEncryptor.new.decrypt(@encrypted)
|
35
35
|
end
|
36
|
-
end
|
36
|
+
end
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.0
|
3
3
|
specification_version: 1
|
4
4
|
name: encrypted_strings
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
7
|
-
date: 2007-08-
|
6
|
+
version: 0.0.2
|
7
|
+
date: 2007-08-23 00:00:00 -04:00
|
8
8
|
summary: Dead-simple string encryption/decryption syntax.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -29,44 +29,45 @@ post_install_message:
|
|
29
29
|
authors:
|
30
30
|
- Aaron Pfeifer, Neil Abraham
|
31
31
|
files:
|
32
|
+
- lib/encrypted_strings.rb
|
32
33
|
- lib/encrypted_strings
|
33
|
-
- lib/encrypted_strings/asymmetric_encryptor.rb
|
34
|
-
- lib/encrypted_strings/encryptor.rb
|
35
34
|
- lib/encrypted_strings/extensions
|
36
|
-
- lib/encrypted_strings/
|
37
|
-
- lib/encrypted_strings/no_key_error.rb
|
38
|
-
- lib/encrypted_strings/no_private_key_error.rb
|
35
|
+
- lib/encrypted_strings/asymmetric_encryptor.rb
|
39
36
|
- lib/encrypted_strings/no_public_key_error.rb
|
37
|
+
- lib/encrypted_strings/no_key_error.rb
|
40
38
|
- lib/encrypted_strings/sha_encryptor.rb
|
39
|
+
- lib/encrypted_strings/no_private_key_error.rb
|
40
|
+
- lib/encrypted_strings/encryptor.rb
|
41
41
|
- lib/encrypted_strings/symmetric_encryptor.rb
|
42
|
-
- lib/encrypted_strings.rb
|
43
|
-
- test/
|
44
|
-
- test/encryptor_test.rb
|
45
|
-
- test/keys
|
46
|
-
- test/keys/encrypted_private
|
47
|
-
- test/keys/encrypted_public
|
48
|
-
- test/keys/private
|
49
|
-
- test/keys/public
|
50
|
-
- test/no_key_error_test.rb
|
42
|
+
- lib/encrypted_strings/extensions/string.rb
|
43
|
+
- test/test_helper.rb
|
51
44
|
- test/no_private_key_error_test.rb
|
52
45
|
- test/no_public_key_error_test.rb
|
53
46
|
- test/sha_encryptor_test.rb
|
54
|
-
- test/string_test.rb
|
55
47
|
- test/symmetric_encryptor_test.rb
|
56
|
-
- test/
|
48
|
+
- test/string_test.rb
|
49
|
+
- test/encryptor_test.rb
|
50
|
+
- test/asymmetric_encryptor_test.rb
|
51
|
+
- test/keys
|
52
|
+
- test/no_key_error_test.rb
|
53
|
+
- test/keys/private
|
54
|
+
- test/keys/public
|
55
|
+
- test/keys/encrypted_public
|
56
|
+
- test/keys/encrypted_private
|
57
|
+
- CHANGELOG
|
57
58
|
- init.rb
|
58
59
|
- MIT-LICENSE
|
59
60
|
- Rakefile
|
60
61
|
- README
|
61
62
|
test_files:
|
62
|
-
- test/asymmetric_encryptor_test.rb
|
63
|
-
- test/encryptor_test.rb
|
64
|
-
- test/no_key_error_test.rb
|
65
63
|
- test/no_private_key_error_test.rb
|
66
64
|
- test/no_public_key_error_test.rb
|
67
65
|
- test/sha_encryptor_test.rb
|
68
|
-
- test/string_test.rb
|
69
66
|
- test/symmetric_encryptor_test.rb
|
67
|
+
- test/string_test.rb
|
68
|
+
- test/encryptor_test.rb
|
69
|
+
- test/asymmetric_encryptor_test.rb
|
70
|
+
- test/no_key_error_test.rb
|
70
71
|
rdoc_options: []
|
71
72
|
|
72
73
|
extra_rdoc_files: []
|