pluginaweek-encrypted_strings 0.3.2

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.
@@ -0,0 +1,59 @@
1
+ == master
2
+
3
+ == 0.3.2 / 2009-01-11
4
+
5
+ * Use Array#pack/String#unpack instead of Base64 to be compatible with Ruby 1.9+
6
+
7
+ == 0.3.1 / 2008-12-4
8
+
9
+ * Fix symmetric ciphers not working on Ruby 1.8.6 and below
10
+
11
+ == 0.3.0 / 2008-12-14
12
+
13
+ * Remove the PluginAWeek namespace
14
+
15
+ == 0.2.1 / 2008-12-04
16
+
17
+ * Fix class-level defaults not working when inherited
18
+
19
+ == 0.2.0 / 2008-12-01
20
+
21
+ * Remove AsymmetricEncryptor.default_algorithm, instead relying on SymmetricEncryptor.default_algorithm
22
+ * Rename NoKeyError to NoPasswordError
23
+ * Rename Encryptors to Ciphers
24
+ * Remove deprecated SymmetricEncryptor#key option
25
+ * Require that symmetric encryption be PKCS #5 compliant
26
+
27
+ == 0.1.1 / 2008-12-01
28
+
29
+ * Fix non-compliant PKCS #5 algorithm being used for symmetric encryption. Use :pkcs5_compliant => true for better security.
30
+ * Rename SymmetricEncryptor#key to #password
31
+ * Fix deprecation messages for Cipher#encrypt/decrypt
32
+
33
+ == 0.1.0 / 2008-07-06
34
+
35
+ * Remove dependency on active_support
36
+
37
+ == 0.0.5 / 2008-07-05
38
+
39
+ * Add automatic stringification of salts for SHA encryption
40
+ * Fix not resetting the encryptor after calling decrypt!
41
+
42
+ == 0.0.4 / 2008-05-05
43
+
44
+ * Updated documentation
45
+
46
+ == 0.0.3 / 2007-09-18
47
+
48
+ * Remove gem dependency on activesupport
49
+
50
+ == 0.0.2 / 2007-08-23
51
+
52
+ * Fix not allowing the decryption mode to be overriden if the string already has an encryptor
53
+ * Convert dos newlines to unix newlines
54
+
55
+ == 0.0.1 / 2007-08-05
56
+
57
+ * Official public release
58
+ * Add api documentation
59
+ * Refactor unit test names
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2005 Rick Olson, 2006-2009 Aaron Pfeifer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,88 @@
1
+ = encrypted_strings
2
+
3
+ +encrypted_strings+ provides dead-simple string encryption/decryption syntax.
4
+
5
+ == Resources
6
+
7
+ API
8
+
9
+ * http://api.pluginaweek.org/encrypted_strings
10
+
11
+ Bugs
12
+
13
+ * http://pluginaweek.lighthouseapp.com/projects/13270-encrypted_strings
14
+
15
+ Development
16
+
17
+ * http://github.com/pluginaweek/encrypted_strings
18
+
19
+ Source
20
+
21
+ * git://github.com/pluginaweek/encrypted_strings.git
22
+
23
+ == Description
24
+
25
+ Encrypting and decrypting data is not exactly the most straightforward and DRY
26
+ way. encrypted_strings improves the syntax and reduces the complexity, adding
27
+ straightforward support for encrypting values using SHA-1, Symmetric, and
28
+ Asymmetric ciphers.
29
+
30
+ == Usage
31
+
32
+ === SHA Encryption
33
+
34
+ >> password = 'shhhh'
35
+ => "shhhh"
36
+ >> encrypted_password = password.encrypt
37
+ => "66c85d26dadde7e1db27e15a0776c921e27143bd"
38
+ >> encrypted_password.class
39
+ => String
40
+ >> encrypted_password.cipher
41
+ => #<EncryptedStrings::ShaCipher:0x2b9238889460 @salt="salt">
42
+ >> encrypted_password == 'shhhh'
43
+ => true
44
+ >> encrypted_password.decrypt
45
+ NotImplementedError: Decryption is not supported using a(n) EncryptedStrings::ShaCipher
46
+ from ./script/../config/../config/../vendor/plugins/encrypted_strings/lib/encrypted_strings/cipher.rb:13:in `decrypt'
47
+ from ./script/../config/../config/../vendor/plugins/encrypted_strings/lib/encrypted_strings/extensions/string.rb:52:in `decrypt'
48
+ from (irb):40
49
+
50
+ When encrypt is called, it creates a +cipher+ instance which is used for
51
+ future encryption and decryption of the string. The default cipher uses
52
+ SHA-1 encryption. For ciphers that do not support decryption, equality with
53
+ other strings is tested by encrypting the other string and checking whether the
54
+ resulting encrypted value is the same.
55
+
56
+ === Symmetric Encryption
57
+
58
+ >> password = 'shhhh'
59
+ => "shhhh"
60
+ >> crypted_password = password.encrypt(:symmetric, :password => 'secret_key')
61
+ => "qSg8vOo6QfU=\n"
62
+ >> crypted_password.class
63
+ => String
64
+ >> crypted_password == 'shhhh'
65
+ => true
66
+ >> password = crypted_password.decrypt
67
+ => "shhhh"
68
+
69
+ === Asymmetric encryption
70
+
71
+ >> password = 'shhhh'
72
+ => "shhhh"
73
+ >> crypted_password = password.encrypt(:asymmetric, :public_key_file => './public.key', :private_key_file => './private.key')
74
+ => "NEwVzcikYUKfS8HTc9L9eg/dMxBCLZ/nFr7J1aQYjkl3I2MPUD0lmjr/saC6\nTJEPwOl60Ki24H8TUwnGtZy14A==\n"
75
+ >> crypted_password.class
76
+ => String
77
+ >> crypted_password == 'shhhh'
78
+ => true
79
+ >> password = crypted_password.decrypt
80
+ => "shhhh"
81
+
82
+ == Dependencies
83
+
84
+ None.
85
+
86
+ == References
87
+
88
+ * Rick Olson - sentry[http://github.com/technoweenie/sentry]
@@ -0,0 +1,96 @@
1
+ require 'rake/testtask'
2
+ require 'rake/rdoctask'
3
+ require 'rake/gempackagetask'
4
+ require 'rake/contrib/sshpublisher'
5
+
6
+ spec = Gem::Specification.new do |s|
7
+ s.name = 'encrypted_strings'
8
+ s.version = '0.3.2'
9
+ s.platform = Gem::Platform::RUBY
10
+ s.summary = 'Dead-simple string encryption/decryption syntax'
11
+ s.description = s.summary
12
+
13
+ s.files = FileList['{lib,test}/**/*'] + %w(CHANGELOG.rdoc init.rb LICENSE Rakefile README.rdoc)
14
+ s.require_path = 'lib'
15
+ s.has_rdoc = true
16
+ s.test_files = Dir['test/**/*_test.rb']
17
+
18
+ s.author = 'Aaron Pfeifer'
19
+ s.email = 'aaron@pluginaweek.org'
20
+ s.homepage = 'http://www.pluginaweek.org'
21
+ s.rubyforge_project = 'pluginaweek'
22
+ end
23
+
24
+ desc 'Default: run all tests.'
25
+ task :default => :test
26
+
27
+ desc "Test the #{spec.name} plugin."
28
+ Rake::TestTask.new(:test) do |t|
29
+ t.libs << 'lib'
30
+ t.test_files = spec.test_files
31
+ t.verbose = true
32
+ end
33
+
34
+ begin
35
+ require 'rcov/rcovtask'
36
+ namespace :test do
37
+ desc "Test the #{spec.name} plugin with Rcov."
38
+ Rcov::RcovTask.new(:rcov) do |t|
39
+ t.libs << 'lib'
40
+ t.test_files = spec.test_files
41
+ t.rcov_opts << '--exclude="^(?!lib/)"'
42
+ t.verbose = true
43
+ end
44
+ end
45
+ rescue LoadError
46
+ end
47
+
48
+ desc "Generate documentation for the #{spec.name} plugin."
49
+ Rake::RDocTask.new(:rdoc) do |rdoc|
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = spec.name
52
+ rdoc.template = '../rdoc_template.rb'
53
+ rdoc.options << '--line-numbers'
54
+ rdoc.rdoc_files.include('README.rdoc', 'CHANGELOG.rdoc', 'LICENSE', 'lib/**/*.rb')
55
+ end
56
+
57
+ desc 'Generate a gemspec file.'
58
+ task :gemspec do
59
+ File.open("#{spec.name}.gemspec", 'w') do |f|
60
+ f.write spec.to_ruby
61
+ end
62
+ end
63
+
64
+ Rake::GemPackageTask.new(spec) do |p|
65
+ p.gem_spec = spec
66
+ p.need_tar = true
67
+ p.need_zip = true
68
+ end
69
+
70
+ desc 'Publish the beta gem.'
71
+ task :pgem => [:package] do
72
+ Rake::SshFilePublisher.new('aaron@pluginaweek.org', '/home/aaron/gems.pluginaweek.org/public/gems', 'pkg', "#{spec.name}-#{spec.version}.gem").upload
73
+ end
74
+
75
+ desc 'Publish the API documentation.'
76
+ task :pdoc => [:rdoc] do
77
+ Rake::SshDirPublisher.new('aaron@pluginaweek.org', "/home/aaron/api.pluginaweek.org/public/#{spec.name}", 'rdoc').upload
78
+ end
79
+
80
+ desc 'Publish the API docs and gem'
81
+ task :publish => [:pgem, :pdoc, :release]
82
+
83
+ desc 'Publish the release files to RubyForge.'
84
+ task :release => [:gem, :package] do
85
+ require 'rubyforge'
86
+
87
+ ruby_forge = RubyForge.new.configure
88
+ ruby_forge.login
89
+
90
+ %w(gem tgz zip).each do |ext|
91
+ file = "pkg/#{spec.name}-#{spec.version}.#{ext}"
92
+ puts "Releasing #{File.basename(file)}..."
93
+
94
+ ruby_forge.add_release(spec.rubyforge_project, spec.name, spec.version, file)
95
+ end
96
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'encrypted_strings'
@@ -0,0 +1,7 @@
1
+ require 'openssl'
2
+
3
+ require 'encrypted_strings/extensions/string'
4
+ require 'encrypted_strings/cipher'
5
+ require 'encrypted_strings/symmetric_cipher'
6
+ require 'encrypted_strings/asymmetric_cipher'
7
+ require 'encrypted_strings/sha_cipher'
@@ -0,0 +1,185 @@
1
+ module EncryptedStrings
2
+ # Indicates no public key was found
3
+ class NoPublicKeyError < StandardError
4
+ end
5
+
6
+ # Indicates no private key was found
7
+ class NoPrivateKeyError < StandardError
8
+ end
9
+
10
+ # Encryption in which the keys used to encrypt/decrypt come in pairs. Also
11
+ # known as public key encryption. Anything that's encrypted using the
12
+ # public key can only be decrypted with the same algorithm and a matching
13
+ # private key. Any message that is encrypted with the private key can only
14
+ # be decrypted with the matching public key.
15
+ #
16
+ # Source: http://support.microsoft.com/kb/246071
17
+ #
18
+ # == Encrypting
19
+ #
20
+ # To encrypt a string using an asymmetric cipher, the location of the
21
+ # public key file must be specified. You can define the default for this
22
+ # value like so:
23
+ #
24
+ # EncryptedStrings::AsymmetricCipher.default_public_key_file = './public.key'
25
+ #
26
+ # If these configuration options are not passed in to #encrypt, then the
27
+ # default values will be used. You can override the default values like so:
28
+ #
29
+ # password = 'shhhh'
30
+ # password.encrypt(:asymmetric, :public_key_file => './encrypted_public.key') # => "INy95irZ8AlHmvc6ZAF/ARsTpbqPIB/4bEAKKOebjsayB7NYWtIzpswvzxqf\nNJ5yyuvxfMODrcg7RimEMFkFlg==\n"
31
+ #
32
+ # An exception will be raised if either the public key file could not be
33
+ # found or the key could not decrypt the public key file.
34
+ #
35
+ # == Decrypting
36
+ #
37
+ # To decrypt a string using an asymmetric cipher, the location of the
38
+ # private key file must be specified. If this file is itself encrypted, you
39
+ # must also specify the algorithm and password used to seed the symmetric
40
+ # algorithm that will decrypt the plublic key file. You can define defaults
41
+ # for these values like so:
42
+ #
43
+ # EncryptedStrings::AsymmetricCipher.default_private_key_file = './private.key'
44
+ # EncryptedStrings::SymmetricCipher.default_algorithm = 'DES-EDE3-CBC'
45
+ # EncryptedStrings::SymmetricCipher.default_password = 'secret'
46
+ #
47
+ # If these configuration options are not passed in to #decrypt, then the
48
+ # default values will be used. You can override the default values like so:
49
+ #
50
+ # password = "INy95irZ8AlHmvc6ZAF/ARsTpbqPIB/4bEAKKOebjsayB7NYWtIzpswvzxqf\nNJ5yyuvxfMODrcg7RimEMFkFlg==\n"
51
+ # password.decrypt(:asymmetric, :public_key_file => './encrypted_public.key', :password => 'secret') # => "shhhh"
52
+ #
53
+ # An exception will be raised if either the private key file could not be
54
+ # found or the password could not decrypt the private key file.
55
+ class AsymmetricCipher < Cipher
56
+ class << self
57
+ # The default private key to use during encryption. Default is nil.
58
+ attr_accessor :default_private_key_file
59
+
60
+ # The default public key to use during encryption. Default is nil.
61
+ attr_accessor :default_public_key_file
62
+ end
63
+
64
+ # Private key used for decrypting data
65
+ attr_reader :private_key_file
66
+
67
+ # Public key used for encrypting data
68
+ attr_reader :public_key_file
69
+
70
+ # The algorithm to use if the key files are encrypted themselves
71
+ attr_accessor :algorithm
72
+
73
+ # The password used during symmetric decryption of the key files
74
+ attr_accessor :password
75
+
76
+ # Creates a new cipher that uses an asymmetric encryption strategy.
77
+ #
78
+ # Configuration options:
79
+ # * <tt>:private_key_file</tt> - Encrypted private key file
80
+ # * <tt>:public_key_file</tt> - Public key file
81
+ # * <tt>:password</tt> - The password to use in the symmetric cipher
82
+ # * <tt>:algorithm</tt> - Algorithm to use symmetrically encrypted strings
83
+ def initialize(options = {})
84
+ invalid_options = options.keys - [:private_key_file, :public_key_file, :algorithm, :password]
85
+ raise ArgumentError, "Unknown key(s): #{invalid_options.join(", ")}" unless invalid_options.empty?
86
+
87
+ options = {
88
+ :private_key_file => AsymmetricCipher.default_private_key_file,
89
+ :public_key_file => AsymmetricCipher.default_public_key_file
90
+ }.merge(options)
91
+
92
+ @public_key = @private_key = nil
93
+
94
+ self.private_key_file = options[:private_key_file]
95
+ self.public_key_file = options[:public_key_file]
96
+ raise ArgumentError, 'At least one key file must be specified (:private_key_file or :public_key_file)' unless private_key_file || public_key_file
97
+
98
+ self.algorithm = options[:algorithm]
99
+ self.password = options[:password]
100
+
101
+ super()
102
+ end
103
+
104
+ # Encrypts the given data. If no public key file has been specified, then
105
+ # a NoPublicKeyError will be raised.
106
+ def encrypt(data)
107
+ raise NoPublicKeyError, "Public key file: #{public_key_file}" unless public?
108
+
109
+ encrypted_data = public_rsa.public_encrypt(data)
110
+ [encrypted_data].pack('m')
111
+ end
112
+
113
+ # Decrypts the given data. If no private key file has been specified, then
114
+ # a NoPrivateKeyError will be raised.
115
+ def decrypt(data)
116
+ raise NoPrivateKeyError, "Private key file: #{private_key_file}" unless private?
117
+
118
+ decrypted_data = data.unpack('m')[0]
119
+ private_rsa.private_decrypt(decrypted_data)
120
+ end
121
+
122
+ # Sets the location of the private key and loads it
123
+ def private_key_file=(file)
124
+ @private_key_file = file and load_private_key
125
+ end
126
+
127
+ # Sets the location of the public key and loads it
128
+ def public_key_file=(file)
129
+ @public_key_file = file and load_public_key
130
+ end
131
+
132
+ # Does this cipher have a public key available?
133
+ def public?
134
+ return true if @public_key
135
+
136
+ load_public_key
137
+ !@public_key.nil?
138
+ end
139
+
140
+ # Does this cipher have a private key available?
141
+ def private?
142
+ return true if @private_key
143
+
144
+ load_private_key
145
+ !@private_key.nil?
146
+ end
147
+
148
+ private
149
+ # Loads the private key from the configured file
150
+ def load_private_key
151
+ @private_rsa = nil
152
+
153
+ if private_key_file && File.file?(private_key_file)
154
+ @private_key = File.read(private_key_file)
155
+ end
156
+ end
157
+
158
+ # Loads the public key from the configured file
159
+ def load_public_key
160
+ @public_rsa = nil
161
+
162
+ if public_key_file && File.file?(public_key_file)
163
+ @public_key = File.read(public_key_file)
164
+ end
165
+ end
166
+
167
+ # Retrieves the private RSA from the private key
168
+ def private_rsa
169
+ if password
170
+ options = {:password => password}
171
+ options[:algorithm] = algorithm if algorithm
172
+
173
+ private_key = @private_key.decrypt(:symmetric, options)
174
+ OpenSSL::PKey::RSA.new(private_key)
175
+ else
176
+ @private_rsa ||= OpenSSL::PKey::RSA.new(@private_key)
177
+ end
178
+ end
179
+
180
+ # Retrieves the public RSA
181
+ def public_rsa
182
+ @public_rsa ||= OpenSSL::PKey::RSA.new(@public_key)
183
+ end
184
+ end
185
+ end