spikex-strongbox 0.1.1

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.
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
+