spikex-strongbox 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 Joseph A. Ilacqua, Jr
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,177 @@
1
+ h1. Strongbox
2
+
3
+ Strongbox provides Public Key Encryption for ActiveRecord. By using a public key
4
+ sensitive information can be encrypted and stored automatically. Once stored a
5
+ password is required to access the information.
6
+
7
+ Because the largest amount of data that can practically be encrypted with a public
8
+ key is 245 byte, by default Strongbox uses a two layer approach. First it encrypts
9
+ the attribute using symmetric encryption with a randomly generated key and
10
+ initialization vector (IV) (which can just be through to as a second key), then it
11
+ encrypts those with the public key.
12
+
13
+ Strongbox stores the encrypted attribute in a database column by the same name, i.e.
14
+ if you tell Strongbox to encrypt "secret" then it will be store in "secret" in the
15
+ database, just as the unencrypted attribute would be. If symmetric encryption is used
16
+ (the default) two additional columns "secret_key" and "secret_iv" are needed as well.
17
+
18
+ The attribute is automatically encrypted simply by setting it:
19
+
20
+ user.secret = "Shhhhhhh..."
21
+
22
+ and decrypted by calling the "decrypt" method with the private key password.
23
+
24
+ plain_text = user.secret.decrypt 'letmein'
25
+
26
+ h2. Quick Start
27
+
28
+ In your model:
29
+
30
+ class User < ActiveRecord::Base
31
+ encrypt_with_public_key :secret,
32
+ :key_pair => File.join(RAILS_ROOT,'config','keypair.pem'),
33
+ end
34
+
35
+ In your migrations:
36
+ class AddSecretColumnsToUser < ActiveRecord::Migration
37
+ def self.up
38
+ add_column :users, :secret, binary
39
+ add_column :users, :secret_key, binary
40
+ add_column :users, :secret_iv, binary
41
+ end
42
+
43
+ def self.down
44
+ remove_column :users, :secret
45
+ remove_column :users, :secret_key
46
+ remove_column :users, :secret_iv
47
+ end
48
+
49
+ Generate a key pair:
50
+
51
+ (Choose a strong password.)
52
+ openssl genrsa -des3 -out config/private.pem 2048
53
+ openssl rsa -in config/private.pem -out config/public.pem -outform PEM -pubout
54
+ cat config/private.pem config/public.pem >> config/keypair.pem
55
+
56
+ In your views and forms you don't need to do anything special to encrypt data. To
57
+ decrypt call:
58
+
59
+ user.secret.decrypt 'password'
60
+
61
+ h2. Gem installation (Rails 2.1+)
62
+
63
+ In config/environment.rb:
64
+
65
+ config.gem "spikex-strongbox",
66
+ :lib => 'strongbox',
67
+ :source => 'http://gems.github.com',
68
+
69
+ h2. Usage
70
+
71
+ _encrypt_with_public_key_ sets up the attribute it's called on for automatic
72
+ encryption. It's simplest form is:
73
+
74
+ class User < ActiveRecord::Base
75
+ encrypt_with_public_key :secret,
76
+ :key_pair => File.join(RAILS_ROOT,'config','keypair.pem')
77
+ end
78
+ end
79
+
80
+ Which will encrypt the attribute "secret". The attribute will be encrypted using
81
+ symmetric encryption with an automatically generated key and IV encrypted using the
82
+ public key. This requires three columns in the database "secret", "secret_key", and
83
+ "secret_iv" (see below).
84
+
85
+ Options to encrypt_with_public_key are:
86
+
87
+ :public_key - Path to the public key file. Overrides :keypair.
88
+
89
+ :private_key - Path to the private key file. Overrides :keypair.
90
+
91
+ :keypair - Path to a file containing both the public and private keys.
92
+
93
+ :symmetric :always/:never - Encrypt the date using symmetric encryption. The public
94
+ key is used to encrypt an automatically generated key and IV. This allows for large
95
+ amounts of data to be encrypted. The size of data that can be encrypted directly with
96
+ the public is limit to key size (in bytes) - 11. So a 2048 key can encrypt *245
97
+ bytes*. Defaults to *:always*
98
+
99
+ :symmetric_cipher - Cipher to use for symmetric encryption. Defaults to *'aes-256-cbc'*. Other ciphers support by OpenSSL may be used.
100
+
101
+ :base64 true/false - Use Base64 encoding to convert encrypted data to text. Use when
102
+ binary save data storage is not available. Defaults to *false*
103
+
104
+ :padding - Method used to pad data encrypted with the public key. Defaults to
105
+ RSA_PKCS1_PADDING. The default should be find unless you are dealing with legacy
106
+ data.
107
+
108
+ For example, encrypting a small attribute, providing only the public key for extra
109
+ security, and Base64 encoding the encrypted data:
110
+
111
+ class User < ActiveRecord::Base
112
+ validates_length_of :pin_code,
113
+ encrypt_with_public_key :pin_code, :is => 4
114
+ :symmetric => :never
115
+ :base64 => true
116
+ :public_key => File.join(RAILS_ROOT,'config','public.pem'),
117
+ end
118
+ end
119
+
120
+ h2. Key Generation
121
+
122
+ Generate a key pair:
123
+
124
+ openssl genrsa -des3 -out config/private.pem 2048
125
+ Generating RSA private key, 2048 bit long modulus
126
+ ......+++
127
+ .+++
128
+ e is 65537 (0x10001)
129
+ Enter pass phrase for config/private.pem:
130
+ Verifying - Enter pass phrase for config/private.pem:
131
+
132
+ and extract the the public key:
133
+
134
+ openssl rsa -in config/private.pem -out config/public.pem -outform PEM -pubout
135
+ Enter pass phrase for config/private.pem:
136
+ writing RSA key
137
+
138
+ If you are going to leave the private key installed it's easiest to create a single
139
+ key pair file:
140
+
141
+ cat config/private.pem config/public.pem >> config/keypair.pem
142
+
143
+ Or, for added security, store the private key file else where, leaving only the public key.
144
+
145
+ h2. Table Creation
146
+
147
+ In it's default configuration Strongbox requires three columns, one the encrypted
148
+ data, one for the encrypted symmetric key, and one for the encrypted symmetric IV. If
149
+ symmetric encryption is disabled then only the columns for the data being encrypted
150
+ is needed.
151
+
152
+ If your underlying database allows, use the *binary* column type. If you must store
153
+ your data in text format be sure to enable Base64 encoding and to use the *text*
154
+ column type. The _string_ column type is likely to be too small to hold the encrypted
155
+ string.
156
+
157
+ h2. Security Caveats
158
+
159
+ If you don't encrypt your data, then an attacker only needs to steal that data to get
160
+ your secrets.
161
+
162
+ If encrypt your data using symmetric encrypts and a stored key, then the attacker
163
+ needs the data and the key stored on the server.
164
+
165
+ If you use public key encryption, the attacker needs the data, the private key, and
166
+ the password. This means the attacker has to sniff the password somehow, so that's
167
+ what you need to protect against.
168
+
169
+ h2. Authors
170
+
171
+ Spike Ilacqua
172
+
173
+ h2. Thanks
174
+
175
+ Strongbox's implementation drew inspiration from Thoughtbot's Paperclip gem
176
+ http://www.thoughtbot.com/projects/paperclip
177
+
data/Rakefile ADDED
@@ -0,0 +1,43 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ $LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
6
+ require 'strongbox'
7
+
8
+ desc 'Default: run tests.'
9
+ task :default => :test
10
+
11
+ desc 'Test the strongbox gem.'
12
+ Rake::TestTask.new(:test) do |t|
13
+ t.libs << 'lib' << 'profile'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = true
16
+ end
17
+
18
+ desc 'Generate documentation for the strongbox gem.'
19
+ Rake::RDocTask.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'doc'
21
+ rdoc.title = 'Strongbox'
22
+ rdoc.options << '--line-numbers' << '--inline-source'
23
+ rdoc.rdoc_files.include('README*')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
26
+
27
+ spec = Gem::Specification.new do |s|
28
+ s.name = "strongbox"
29
+ s.version = Strongbox::VERSION
30
+ s.summary = "Secures ActiveRecord fields with public key encryption."
31
+ s.authors = ["Spike Ilacqua"]
32
+ s.email = "spike@stuff-things.net"
33
+ s.homepage = "http://stuff-things.net/strongbox"
34
+ s.files = FileList["[A-Z]*", "{lib,rails,test}/**/*"]
35
+ s.add_development_dependency 'thoughtbot-shoulda'
36
+ end
37
+
38
+ desc "Generate a gemspec file for GitHub"
39
+ task :gemspec do
40
+ File.open("#{spec.name}.gemspec", 'w') do |f|
41
+ f.write spec.to_yaml
42
+ end
43
+ end
data/lib/strongbox.rb ADDED
@@ -0,0 +1,69 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+
4
+ require 'strongbox/lock'
5
+
6
+ module Strongbox
7
+
8
+ VERSION = "0.1.1"
9
+
10
+ RSA_PKCS1_PADDING = OpenSSL::PKey::RSA::PKCS1_PADDING
11
+ RSA_SSLV23_PADDING = OpenSSL::PKey::RSA::SSLV23_PADDING
12
+ RSA_NO_PADDING = OpenSSL::PKey::RSA::NO_PADDING
13
+ RSA_PKCS1_OAEP_PADDING = OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
14
+
15
+ class << self
16
+ # Provides for setting the default options for Strongbox
17
+ def options
18
+ @options ||= {
19
+ :base64 => false,
20
+ :symmetric => :always,
21
+ :padding => RSA_PKCS1_PADDING,
22
+ :symmetric_cipher => 'aes-256-cbc'
23
+ }
24
+ end
25
+
26
+ def included base #:nodoc:
27
+ base.extend ClassMethods
28
+ end
29
+ end
30
+
31
+ class StrongboxError < StandardError #:nodoc:
32
+ end
33
+
34
+ module ClassMethods
35
+ # +encrypt_with_public_key+ gives the class it is called on an attribute that
36
+ # when assigned is automatically encrypted using a public key. This allows the
37
+ # unattended encryption of data, without exposing the information need to decrypt
38
+ # it (as would be the case when using symmetric key encryption alone). Small
39
+ # amounts of data may be encrypted directly with the public key. Larger data is
40
+ # encrypted using symmetric encryption. The encrypted data is stored in the
41
+ # database column of the same name as the attibute. If symmetric encryption is
42
+ # used (the default) additional column are need to store the generated password
43
+ # and IV.
44
+ def encrypt_with_public_key(name, options = {})
45
+ include InstanceMethods
46
+
47
+ options = options.symbolize_keys.reverse_merge Strongbox.options
48
+
49
+ define_method name do
50
+ @_lock ||= Lock.new(name, self, options)
51
+ end
52
+
53
+ define_method "#{name}=" do | plaintext |
54
+ @_lock ||= Lock.new(name, self, options)
55
+ @_lock.encrypt plaintext
56
+ end
57
+
58
+ end
59
+ end
60
+
61
+ module InstanceMethods
62
+
63
+ end
64
+ end
65
+
66
+ if Object.const_defined?("ActiveRecord")
67
+ ActiveRecord::Base.send(:include, Strongbox)
68
+ end
69
+
@@ -0,0 +1,85 @@
1
+ module Strongbox
2
+ # The Lock class encrypts and decrypts the protected attribute. It
3
+ # automatically encrypts the data when set and decrypts it when the private
4
+ # key password is provided.
5
+ class Lock
6
+
7
+ def initialize name, instance, options = {}
8
+ @name = name
9
+ @instance = instance
10
+
11
+ options = Strongbox.options.merge(options)
12
+
13
+ @base64 = options[:base64]
14
+ @public_key = options[:public_key] || options[:key_pair]
15
+ @private_key = options[:private_key] || options[:key_pair]
16
+ @padding = options[:padding]
17
+ @symmetric = options[:symmetric]
18
+ @symmetric_cipher = options[:symmetric_cipher]
19
+ @symmetric_key = options[:symmetric_key] || "#{name}_key"
20
+ @symmetric_iv = options[:symmetric_iv] || "#{name}_iv"
21
+ end
22
+
23
+ def encrypt plaintext
24
+ unless @public_key
25
+ raise StrongboxError.new("#{@instance.class} model does not have public key_file")
26
+ end
27
+ if !plaintext.blank?
28
+ # Using a blank password in OpenSSL::PKey::RSA.new prevents reading
29
+ # the private key if the file is a key pair
30
+ public_key = OpenSSL::PKey::RSA.new(File.read(@public_key),"")
31
+ if @symmetric == :always
32
+ cipher = OpenSSL::Cipher::Cipher.new(@symmetric_cipher)
33
+ cipher.encrypt
34
+ cipher.key = random_key = cipher.random_key
35
+ cipher.iv = random_iv = cipher.random_iv
36
+
37
+ ciphertext = cipher.update(plaintext)
38
+ ciphertext << cipher.final
39
+
40
+ @instance.write_attribute(@symmetric_key,public_key.public_encrypt(random_key,@padding))
41
+ @instance.write_attribute(@symmetric_iv,public_key.public_encrypt(random_iv,@padding))
42
+ else
43
+ ciphertext = public_key.public_encrypt(plaintext,@padding)
44
+ end
45
+ ciphertext = Base64.encode64(ciphertext) if @base64
46
+ @instance.write_attribute(@name,ciphertext)
47
+ end
48
+ end
49
+
50
+ # Given the private key password decrypts the attribute. Will raise
51
+ # OpenSSL::PKey::RSAError if the password is wrong.
52
+
53
+ def decrypt password = ""
54
+ # Given a private key and a nil password OpenSSL::PKey::RSA.new() will
55
+ # *prompt* for a password, we default to an empty string to avoid that.
56
+ return "*encrypted*" if password.blank?
57
+
58
+ unless @private_key
59
+ raise StrongboxError.new("#{@instance.class} model does not have public key_file")
60
+ end
61
+
62
+ ciphertext = @instance.read_attribute(@name)
63
+ if ciphertext
64
+ ciphertext = Base64.decode64(ciphertext) if @base64
65
+ private_key = OpenSSL::PKey::RSA.new(File.read(@private_key),password)
66
+ if @symmetric == :always
67
+ cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
68
+ cipher.decrypt
69
+ cipher.key = private_key.private_decrypt(@instance.read_attribute(@symmetric_key),@padding)
70
+ cipher.iv = private_key.private_decrypt(@instance.read_attribute(@symmetric_iv),@padding)
71
+ plaintext = cipher.update(ciphertext)
72
+ plaintext << cipher.final
73
+ else
74
+ plaintext = private_key.private_decrypt(ciphertext,@padding)
75
+ end
76
+ else
77
+ nil
78
+ end
79
+ end
80
+
81
+ def to_s
82
+ decrypt
83
+ end
84
+ end
85
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__),'../init.rb')
data/test/database.yml ADDED
@@ -0,0 +1,4 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: ":memory:"
4
+
@@ -0,0 +1,24 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ Proc-Type: 4,ENCRYPTED
3
+ DEK-Info: DES-EDE3-CBC,317921A00FB0882F
4
+
5
+ f+GWBkcLJLsBUElOEKhqrtYgT1X4nixaZHD5x0VhmW2FrREz4vcqXrxwLTaRQJK/
6
+ vHFJ/7IVmEHScwEognSfw/wX2HMIHczoQT3ugsa29Nt7t1VLGy9jvN1+1f+g90xe
7
+ 02jC7CYEKUJ3agZPox49i0/UN9OCIgdtKfecdDHYWyziob8yYTsUdDGyAXlPv0Kx
8
+ 0MPSCRDtEh4UJ2PIFyw2HowkYeNss6uIte9rxJGINI11D9vmXR0pH0XyCwHQn+2T
9
+ ScHWg8BJ1rkBKydbKQ4vnfhGMjG+bZyrJXrJSoazXroseuhHu8QRUONm5Kl/zW1f
10
+ GP1CjIfTCQQZECYIa2tXTFdL9y2ZOCn8xit57SwEpmJMvZC58PkQX5+/aHPcOXhl
11
+ YrF+6FEfNpdBz9PUmv4Af2kTa88xZqm1Q3GtTOk7wsJpfeTMhU71KjA1pL9xNPrT
12
+ DnKhtfLGvcgo8Z9BGOiLFe9uQvhhprX7isc1XdysbMigsVIWLvZp9RxRp/zAn7fy
13
+ y56C6mc3tUwcq89RcxAn+bC75gwZO/hyVrnkhManOMfHTEiZXVybU9Ril3SZ+ry6
14
+ 8AxMid0ZWbbtCHdDc5rHfXsGeFhJZxBbg/WtMxBPGHNByqs8sWUM9Z8YoK8WMYxV
15
+ GvC9RB4m0jgA4S3MEOMmKOXDuJxa7IgTgApVmLPl+sDOHGK3xAItYJJawJqOZQ1f
16
+ r+x/8g19CuehuflCxDo+D4/RJMqkOEq+0FGUqI8lHv6vR6+YpkGdrQQXUohBy67f
17
+ 3Qym1ztZ8ygsttgJwnhwAfMh8FdIrVJc7NZ8pDiBZbg=
18
+ -----END RSA PRIVATE KEY-----
19
+ -----BEGIN PUBLIC KEY-----
20
+ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9F1ipsLL+V68bGSJFqFLQKgXq
21
+ Glyyplx0s9KxgLbmbDICXpV7DceKaIBUkPZDx2DrlvjZmG+rG5ehdWNI7q/hupao
22
+ NF0WzEiOp+30gISeyl81Z/NAmhcwcOnZpbS9nl4JLaWrN7iGC1geNBNDo+lVbsm1
23
+ O2+Tlt8rjHsNjzgIzQIDAQAB
24
+ -----END PUBLIC KEY-----
@@ -0,0 +1,111 @@
1
+ require 'test/test_helper'
2
+
3
+ class StrongboxTest < Test::Unit::TestCase
4
+ context "A Class with a secured field" do
5
+ setup do
6
+ rebuild_model :key_pair => File.join(FIXTURES_DIR,'keypair.pem')
7
+ end
8
+
9
+ should "not error when trying to also create a secure field" do
10
+ assert_nothing_raised do
11
+ Dummy.class_eval do
12
+ encrypt_with_public_key :secret,
13
+ :key_pair => File.join(FIXTURES_DIR,'keypair.pem')
14
+ end
15
+ end
16
+ end
17
+
18
+ context "that is valid" do
19
+ setup do
20
+ @dummy = Dummy.new
21
+ @dummy.secret = 'Shhhh'
22
+ @dummy.in_the_clear = 'Hey you guys!'
23
+ end
24
+
25
+ should "not change unencrypted fields" do
26
+ assert_equal 'Hey you guys!', @dummy.in_the_clear
27
+ end
28
+
29
+ should "return '*encrypted*' when locked" do
30
+ assert_equal "*encrypted*", @dummy.secret.decrypt
31
+ end
32
+
33
+ should "return secret when unlocked" do
34
+ assert_equal "Shhhh", @dummy.secret.decrypt('boost facile')
35
+ end
36
+
37
+ should "generate and store symmetric encryption key and IV" do
38
+ assert_not_nil @dummy.attributes['secret_key']
39
+ assert_not_nil @dummy.attributes['secret_iv']
40
+ end
41
+
42
+ should "raise on bad password" do
43
+ assert_raises(OpenSSL::PKey::RSAError) do
44
+ @dummy.secret.decrypt('letmein')
45
+ end
46
+ end
47
+
48
+ context "with symmetric encryption disabled" do
49
+ setup do
50
+ rebuild_class(:key_pair => File.join(FIXTURES_DIR,'keypair.pem'),
51
+ :symmetric => :never)
52
+ @dummy = Dummy.new
53
+ @dummy.secret = 'Shhhh'
54
+ end
55
+
56
+ should "return '*encrypted*' when locked" do
57
+ assert_equal "*encrypted*", @dummy.secret.decrypt
58
+ end
59
+
60
+ should "return secret when unlocked" do
61
+ assert_equal "Shhhh", @dummy.secret.decrypt('boost facile')
62
+ end
63
+
64
+ should "not generate and store symmetric encryption key and IV" do
65
+ assert_nil @dummy.attributes['secret_key']
66
+ assert_nil @dummy.attributes['secret_iv']
67
+ end
68
+
69
+ end
70
+
71
+ context "with Base64 encoding enabled" do
72
+ setup do
73
+ rebuild_class(:key_pair => File.join(FIXTURES_DIR,'keypair.pem'),
74
+ :base64 => true)
75
+ @dummy = Dummy.new
76
+ @dummy.secret = 'Shhhh'
77
+ end
78
+
79
+ should 'Base64 encode the ciphertext' do
80
+ # Base64 encoded text is limited to the charaters A–Z, a–z, and 0–9,
81
+ # and is padded with 0 to 2 equal-signs
82
+ assert @dummy.attributes['secret'] =~ /^[0-9A-Za-z+\/]+={0,2}$/
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ context "when a key_pair is not provided" do
89
+ setup do
90
+ rebuild_class
91
+ @dummy = Dummy.new
92
+ end
93
+
94
+ should "raise on encrypt" do
95
+ assert_raises(Strongbox::StrongboxError) do
96
+ @dummy.secret = 'Shhhh'
97
+ end
98
+ end
99
+
100
+ should "raise on decrypt with a password" do
101
+ assert_raises(Strongbox::StrongboxError) do
102
+ @dummy.secret.decrypt('boost facile')
103
+ end
104
+ end
105
+
106
+ should "return '*encrypted*' when still locked" do
107
+ assert_equal "*encrypted*", @dummy.secret.decrypt
108
+ end
109
+ end
110
+ end
111
+
@@ -0,0 +1,50 @@
1
+ ROOT = File.join(File.dirname(__FILE__), '..')
2
+ RAILS_ROOT = ROOT
3
+ $LOAD_PATH << File.join(ROOT, 'lib')
4
+
5
+ require 'rubygems'
6
+ require 'test/unit'
7
+ require 'activerecord'
8
+ gem 'thoughtbot-shoulda', ">= 2.9.0"
9
+ require 'shoulda'
10
+ begin require 'redgreen'; rescue LoadError; end
11
+
12
+ require 'strongbox'
13
+
14
+ ENV['RAILS_ENV'] ||= 'test'
15
+
16
+ FIXTURES_DIR = File.join(File.dirname(__FILE__), "fixtures")
17
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
18
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
19
+ ActiveRecord::Base.establish_connection(config['test'])
20
+
21
+
22
+ # rebuild_model and rebuild_class are borrowed directly from the Paperclip gem
23
+ #
24
+ # http://thoughtbot.com/projects/paperclip
25
+
26
+ # rebuild_model (re)creates a database table for our Dummy model.
27
+ # Call this to initial create a model, or to reset the database.
28
+
29
+ def rebuild_model options = {}
30
+ ActiveRecord::Base.connection.create_table :dummies, :force => true do |table|
31
+ table.string :in_the_clear
32
+ table.binary :secret
33
+ table.binary :secret_key
34
+ table.binary :secret_iv
35
+ end
36
+ rebuild_class options
37
+ end
38
+
39
+ # rebuild_class creates or replaces the Dummy ActiveRecord Model.
40
+ # Call this when changing the options to encrypt_with_public_key
41
+
42
+ def rebuild_class options = {}
43
+ ActiveRecord::Base.send(:include, Strongbox)
44
+ Object.send(:remove_const, "Dummy") rescue nil
45
+ Object.const_set("Dummy", Class.new(ActiveRecord::Base))
46
+ Dummy.class_eval do
47
+ include Strongbox
48
+ encrypt_with_public_key :secret, options
49
+ end
50
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spikex-strongbox
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Spike Ilacqua
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-04-15 23:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description:
26
+ email: spike@stuff-things.net
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - LICENSE
35
+ - Rakefile
36
+ - README.textile
37
+ - lib/strongbox
38
+ - lib/strongbox/lock.rb
39
+ - lib/strongbox.rb
40
+ - rails/init.rb
41
+ - test/database.yml
42
+ - test/fixtures
43
+ - test/fixtures/keypair.pem
44
+ - test/strongbox_test.rb
45
+ - test/test_helper.rb
46
+ has_rdoc: false
47
+ homepage: http://stuff-things.net/strongbox
48
+ post_install_message:
49
+ rdoc_options: []
50
+
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.2.0
69
+ signing_key:
70
+ specification_version: 2
71
+ summary: Secures ActiveRecord fields with public key encryption.
72
+ test_files: []
73
+