encrypted-attributes 0.0.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) 2012 Chris Lowder
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,11 @@
1
+ [![Build Status](https://secure.travis-ci.org/clowder/encrypted-attributes.png)](http://travis-ci.org/clowder/encrypted-attributes)
2
+
3
+ # EncryptedColumn
4
+
5
+ ## Contributing
6
+
7
+ 1. Fork it
8
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
9
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
10
+ 4. Push to the branch (`git push origin my-new-feature`)
11
+ 5. Create new Pull Request
@@ -0,0 +1,10 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'simple_aes'
4
+ require 'encrypted_attributes'
5
+
6
+ if defined?(Rails)
7
+ if Gem::Requirement.new('~> 3.0.0').satisfied_by? Gem::Version.new(Rails.version)
8
+ require 'lograge/railtie'
9
+ end
10
+ end
@@ -0,0 +1,27 @@
1
+ module EncryptedAttributes
2
+ def self.extended(base)
3
+ ar_version = Gem::Version.new(ActiveRecord::VERSION::STRING)
4
+
5
+ if Gem::Requirement.new('~> 2.3.0').satisfied_by? ar_version
6
+ require 'encrypted_attributes/ar_23'
7
+ base.send :extend, AR23
8
+ elsif Gem::Requirement.new('~> 3.2.0').satisfied_by? ar_version
9
+ require 'encrypted_attributes/ar_32'
10
+ base.send :extend, AR32
11
+ else
12
+ fail "Unsupported version of ActiveRecord."
13
+ end
14
+ end
15
+
16
+ def self.encrypt(value)
17
+ @encrypter.encrypt(value)
18
+ end
19
+
20
+ def self.decrypt(value)
21
+ @encrypter.decrypt(value)
22
+ end
23
+
24
+ def self.setup(attrs={})
25
+ @encrypter = SimpleAES.new(:key => attrs.fetch(:key), :iv => attrs.fetch(:iv))
26
+ end
27
+ end
data/lib/simple_aes.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'openssl'
2
+
3
+ class SimpleAES
4
+ attr_reader :cipher, :key, :iv
5
+
6
+ def initialize(args={})
7
+ @key = args.fetch(:key)
8
+ @iv = args.fetch(:iv)
9
+ @cipher = args[:cypher] || 'AES-128-CBC'
10
+ end
11
+
12
+ def decrypt(encrypted_data)
13
+ encrypted_data = Array(encrypted_data).pack('H*')
14
+ aes = OpenSSL::Cipher::Cipher.new(cipher)
15
+ aes.decrypt
16
+ aes.key = key
17
+ aes.iv = iv
18
+ aes.update(encrypted_data) + aes.final
19
+ end
20
+
21
+ def encrypt(data)
22
+ aes = OpenSSL::Cipher::Cipher.new(cipher)
23
+ aes.encrypt
24
+ aes.key = key
25
+ aes.iv = iv
26
+ (aes.update(data) + aes.final).unpack('H*').first
27
+ end
28
+ end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ describe EncryptedAttributes do
4
+ let(:key) { 'e0cfe841f51d29c0e0a1c51391ca04a6' }
5
+ let(:iv) { '7b94eae611106dc190b10f40e2d0fde0' }
6
+
7
+ let(:encrypto_class) {
8
+ Class.new(ActiveRecord::Base) do
9
+ self.table_name = 'encrypto'
10
+ extend EncryptedAttributes
11
+ end
12
+ }
13
+
14
+ let(:serialized_encrypto_class) {
15
+ Class.new(ActiveRecord::Base) do
16
+ self.table_name = 'encrypto'
17
+ extend EncryptedAttributes
18
+ serialize :description
19
+ encrypt :description
20
+ end
21
+ }
22
+
23
+ let(:strict_serialized_encrypto_class) {
24
+ Class.new(ActiveRecord::Base) do
25
+ self.table_name = 'encrypto'
26
+ extend EncryptedAttributes
27
+ serialize :description, Hash
28
+ encrypt :description
29
+ end
30
+ }
31
+
32
+ before(:all) do
33
+ EncryptedAttributes.setup(:key => key, :iv => iv)
34
+ end
35
+
36
+ it "allows you to specify the columns to be encrypted" do
37
+ encrypto_class.encrypt(:description)
38
+ encrypto_class.encrypted_attributes.should == ['description']
39
+ end
40
+
41
+ it "doesn't blow up if the encryption target is nil" do
42
+ foo = serialized_encrypto_class.new
43
+ foo.description = nil
44
+ foo.save!
45
+
46
+ serialized_encrypto_class.last.description.should be_nil
47
+ end
48
+
49
+ it "encrypts the data in the database" do
50
+ encrypto_class.encrypt(:description)
51
+ encrypto_class.create(:description => 'this is hidden')
52
+
53
+ raw_data = ActiveRecord::Base.connection.execute('SELECT * FROM encrypto').each(:symbolize_keys => true, :as => :hash) { |r| r }
54
+ raw_data[0][:description].should == 'e7bbb4d93712a6edb759ebf947000bdb'
55
+ end
56
+
57
+ it "decrypts the data from the database" do
58
+ encrypto_class.encrypt(:description)
59
+ encrypto_class.create(:description => 'this is hidden')
60
+
61
+ encrypto_class.last.description.should == 'this is hidden'
62
+ end
63
+
64
+ it "works on serialized columns too" do
65
+ serialized_encrypto_class.create(:description => { :foo => 'bar', :baz => 'bat' })
66
+
67
+ encrypto = serialized_encrypto_class.last
68
+ encrypto.description.should == { :foo => 'bar', :baz => 'bat' }
69
+ encrypto.description = { :foo => "This is my fancy class" }
70
+ encrypto.save
71
+
72
+ serialized_encrypto_class.last.description.should == { :foo => 'This is my fancy class' }
73
+ end
74
+
75
+ it "shoulsn't break serialized columns with type enforement" do
76
+ expect {
77
+ encrypto = serialized_encrypto_class.new
78
+ encrypto.description = { :foo => "This is my fancy class" }
79
+ encrypto.save!
80
+ }.not_to raise_error
81
+ end
82
+
83
+ it "makes it impossible to mutate encrypted serialized objects" do
84
+ expect {
85
+ serialized_encrypto_class.create(:description => { :foo => 'bar', :baz => 'bat' })
86
+
87
+ encrypto = serialized_encrypto_class.last
88
+ encrypto.description[:foo] = "This is my fancy class"
89
+ }.to raise_error(RuntimeError)
90
+ end
91
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleAES do
4
+ let(:key) { 'e0cfe841f51d29c0e0a1c51391ca04a6' }
5
+ let(:iv) { '7b94eae611106dc190b10f40e2d0fde0' }
6
+
7
+ it "allows you to simply encrypt data" do
8
+ encrypted = SimpleAES.new(:key => key, :iv => iv).encrypt('foo bar')
9
+ encrypted.should == '99ea4886246cb6ad15c236a2e5935af2'
10
+ end
11
+
12
+ it "allows you to decrypt data" do
13
+ message = '5e3a1d405c66f4541a0618bb9e428db9'
14
+ SimpleAES.new(:key => key, :iv => iv).decrypt(message).should == 'you got it!'
15
+ end
16
+ end
@@ -0,0 +1,41 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ require 'ostruct'
6
+ require 'pry'
7
+ Bundler.require(:default, :test)
8
+
9
+ ActiveRecord::Base.establish_connection({
10
+ :adapter => 'mysql2',
11
+ :host => 'localhost',
12
+ :database => 'encrypted_attributes_test',
13
+ :username => 'root',
14
+ :encoding => 'utf8'
15
+ })
16
+
17
+ class CreateSchema < ActiveRecord::Migration
18
+ def self.up
19
+ create_table :encrypto do |t|
20
+ t.binary :description
21
+ end
22
+ end
23
+
24
+ def self.down
25
+ drop_table :encrypto
26
+ end
27
+ end
28
+
29
+ RSpec.configure do |config|
30
+ config.before(:suite) do
31
+ CreateSchema.up
32
+ end
33
+
34
+ config.after(:each) do
35
+ ActiveRecord::Base.connection.execute('TRUNCATE encrypto')
36
+ end
37
+
38
+ config.after(:suite) do
39
+ CreateSchema.down
40
+ end
41
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: encrypted-attributes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris Lowder
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: pry
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: ! 'AES encrypted attributes with Rails. Behaves similarly to Rails''s
63
+ #serialize and works for versions 2.3.x & 3.2.x.'
64
+ email:
65
+ - clowder@gmail.com
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - lib/encrypted-attributes.rb
71
+ - lib/encrypted_attributes.rb
72
+ - lib/simple_aes.rb
73
+ - spec/encrypted_attributes_spec.rb
74
+ - spec/simple_aes_spec.rb
75
+ - spec/spec_helper.rb
76
+ - README.md
77
+ - LICENSE
78
+ homepage: http://github.com/clowder/encrypted-attributes
79
+ licenses: []
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 1.8.23
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: AES encrypted attributes with Rails.
102
+ test_files:
103
+ - spec/encrypted_attributes_spec.rb
104
+ - spec/simple_aes_spec.rb
105
+ - spec/spec_helper.rb