encryption_accessor 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest ADDED
@@ -0,0 +1,6 @@
1
+ README
2
+ Rakefile
3
+ lib/aes_crypt.rb
4
+ lib/encryption_accessor.rb
5
+ tasks/encryption_accessor.rake
6
+ Manifest
data/README ADDED
@@ -0,0 +1,58 @@
1
+ = encryption_accessor
2
+
3
+ This is a gem for allowing encryption of data (using AES256) from the Ruby side, with a dead simple API and accessor methods.
4
+
5
+ == Usage
6
+
7
+ Let's say you have a model User and your data is stored as plain text. To encrypt that data you have to do the following:
8
+
9
+ class User < ActiveRecord::Base
10
+ ..
11
+ encryption_accessor :first_name, :last_name, :password
12
+ ..
13
+ end
14
+
15
+ By adding this declaration, now the User model has created a couple of new methods for you (and also modified the existing standard accessors) for each field, such us: first_name_encrypt!, first_name_decrypt!, first_name_encrypred .. and the same for last_name and password.
16
+
17
+ Then, you can encrypt your fields of records already stored on the database, as the following example suggests:
18
+
19
+ > u = User.find(1)
20
+ > u.first_name_encrypt!
21
+ > u.last_name_encrypt!
22
+ > u.password_encrypt!
23
+ > u.save(false)
24
+
25
+ Your data is now encrypted!
26
+
27
+ For new data, it's even simpler, as the old accessors has been redefined, look at this:
28
+
29
+ > u = User.create(:first_name => 'Marcelo', :last_name => 'Giorgi')
30
+
31
+ That's it! The data is stored encrypted. You can test it:
32
+
33
+ > u.first_name
34
+ => 'Marcelo'
35
+ > u.first_name_encrypted
36
+ => "57626921e35fa400b2ab3227abbfb98a"
37
+
38
+ Also it's important to notice that I didn't overwrite any finder methods. So if you want to query for an encrypted value you should do the following:
39
+
40
+ > u = User.find_by_first_name_and_last_name(AESCrypt.encrypt('Marcelo'), AESCrypt.encrypt('Giorgi'))
41
+ => #<User id: 1, first_name: "57626921e35fa400b2ab3227abbfb98a", last_name: "bc0059af127f097175f3aa5795841922", .. password: ...>
42
+
43
+ That's all I have to say. Let me know if it helps :)
44
+
45
+ == TODO
46
+
47
+ * Add specs !!
48
+ * Add more flexibility for another algorithms.
49
+
50
+ == License
51
+
52
+ Copyright (c) 2010 Marcelo Giorgi
53
+
54
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
55
+
56
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
57
+
58
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'echoe'
3
+
4
+ # PACKAGING ============================================================
5
+
6
+ Echoe.new('encryption_accessor', '0.0.1') do |p|
7
+ p.description = "Accessor's to encrypt/decrypt fields when data is stored encrypted on DB"
8
+ p.url = 'https://github.com/marklazz/encryption_accessor'
9
+ p.author = 'Marcelo Giorgi'
10
+ p.email = 'marklazz.uy@gmail.com'
11
+ p.ignore_pattern = [ 'tmp/*', 'script/*', '*.sh' ]
12
+ p.runtime_dependencies = []
13
+ p.development_dependencies = [ 'spec' ]
14
+ end
15
+
16
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{encryption_accessor}
5
+ s.version = "0.0.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Marcelo Giorgi"]
9
+ s.date = %q{2011-02-18}
10
+ s.description = %q{Accessor's to encrypt/decrypt fields when data is stored encrypted on DB}
11
+ s.email = %q{marklazz.uy@gmail.com}
12
+ s.extra_rdoc_files = ["README", "lib/aes_crypt.rb", "lib/encryption_accessor.rb", "tasks/encryption_accessor.rake"]
13
+ s.files = ["README", "Rakefile", "lib/aes_crypt.rb", "lib/encryption_accessor.rb", "tasks/encryption_accessor.rake", "Manifest", "encryption_accessor.gemspec"]
14
+ s.homepage = %q{https://github.com/marklazz/encryption_accessor}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Encryption_accessor", "--main", "README"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{encryption_accessor}
18
+ s.rubygems_version = %q{1.3.7}
19
+ s.summary = %q{Accessor's to encrypt/decrypt fields when data is stored encrypted on DB}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
26
+ s.add_development_dependency(%q<spec>, [">= 0"])
27
+ else
28
+ s.add_dependency(%q<spec>, [">= 0"])
29
+ end
30
+ else
31
+ s.add_dependency(%q<spec>, [">= 0"])
32
+ end
33
+ end
data/lib/aes_crypt.rb ADDED
@@ -0,0 +1,51 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'openssl'
4
+ require 'digest/sha1'
5
+
6
+ module AESCrypt
7
+ extend self
8
+
9
+ ALGORITHM = "AES-256-CBC"
10
+ SECRET = "add-your-way-eliasonmedia-02-10-2011"
11
+ ENCODE_DIRECTIVE = 'H*'
12
+
13
+ # ALGORITHM = "AES-256-ECB"
14
+ # Decrypts a block of data (encrypted_data) given an encryption key
15
+ # and an initialization vector (iv). Keys, iv's, and the data
16
+ # returned are all binary strings. Cipher_type should be
17
+ # "AES-256-CBC", "AES-256-ECB", or any of the cipher types
18
+ # supported by OpenSSL. Pass nil for the iv if the encryption type
19
+ # doesn't use iv's (like ECB).
20
+ #:return: => String
21
+ #:arg: encrypted_data => String
22
+ #:arg: key => String
23
+ #:arg: iv => String
24
+ #:arg: cipher_type => String
25
+ def decrypt(encrypted_data, key = SECRET, iv = nil, cipher_type = ALGORITHM)
26
+ aes = OpenSSL::Cipher::Cipher.new(cipher_type)
27
+ aes.decrypt
28
+ aes.key = key
29
+ aes.iv = iv if iv != nil
30
+ aes.update([encrypted_data].pack(ENCODE_DIRECTIVE)) + aes.final
31
+ end
32
+
33
+ # Encrypts a block of data given an encryption key and an
34
+ # initialization vector (iv). Keys, iv's, and the data returned
35
+ # are all binary strings. Cipher_type should be "AES-256-CBC",
36
+ # "AES-256-ECB", or any of the cipher types supported by OpenSSL.
37
+ # Pass nil for the iv if the encryption type doesn't use iv's (like
38
+ # ECB).
39
+ #:return: => String
40
+ #:arg: data => String
41
+ #:arg: key => String
42
+ #:arg: iv => String
43
+ #:arg: cipher_type => String
44
+ def encrypt(data, key = SECRET, iv = nil, cipher_type = ALGORITHM)
45
+ aes = OpenSSL::Cipher::Cipher.new(cipher_type)
46
+ aes.encrypt
47
+ aes.key = key
48
+ aes.iv = iv if iv != nil
49
+ (aes.update(data) + aes.final).unpack(ENCODE_DIRECTIVE)[0]
50
+ end
51
+ end
@@ -0,0 +1,61 @@
1
+ module EncryptionAccessor
2
+
3
+ VERSION = '0.0.1'
4
+
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+
11
+ def encryption_accessor(*fields)
12
+ fields.each do |field|
13
+ force_implement_field_setter!(field)
14
+
15
+ define_method(:"#{field}_with_encryption=") do |value|
16
+ self.send(:"#{field}_without_encryption=", value)
17
+ write_attribute(:"#{field}", AESCrypt.encrypt(read_attribute(:"#{field}"))) unless value.nil?
18
+ end
19
+
20
+ self.send :alias_method_chain, :"#{field}=", :encryption
21
+
22
+ define_method(:"#{field}_decrypt") do
23
+ blob_value = self.read_attribute(:"#{field}")
24
+ return if blob_value.nil?
25
+ AESCrypt.decrypt(blob_value)
26
+ end
27
+
28
+ define_method(:"#{field}") do
29
+ self.send(:"#{field}_decrypt")
30
+ end
31
+
32
+ define_method(:"#{field}_encrypted") do
33
+ self.attributes["#{field}"]
34
+ end
35
+ define_method(:"#{field}") do
36
+ self.send(:"#{field}_decrypt")
37
+ end
38
+ define_method(:"#{field}_encrypt!") do
39
+ self.send(:"#{field}_with_encryption=", self.attributes["#{field}"])
40
+ end
41
+ define_method(:"#{field}_decrypt!") do
42
+ self.send(:"#{field}=", self.send(:"#{field}_decrypt"))
43
+ end
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def force_implement_field_setter!(field)
50
+ new.send("#{field}=", nil)
51
+ end
52
+ end
53
+ end
54
+
55
+ module ActiveRecord
56
+ class Base
57
+ class << self
58
+ include EncryptionAccessor
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,147 @@
1
+ require 'rake/clean'
2
+ require 'fileutils'
3
+ require 'date'
4
+ require 'spec/rake/spectask'
5
+ require 'mocha'
6
+ require 'hanna/rdoctask'
7
+
8
+ # Removes spec task defiened in dependency gems
9
+ module Rake
10
+ def self.remove_task(task_name)
11
+ Rake.application.instance_variable_get('@tasks').delete(task_name.to_s)
12
+ end
13
+ end
14
+ Rake.remove_task 'spec'
15
+
16
+ def source_version
17
+ line = File.read('lib/encryption_accessor.rb')[/^\s*VERSION = .*/]
18
+ line.match(/.*VERSION = '(.*)'/)[1]
19
+ end
20
+
21
+ # SPECS ===============================================================
22
+
23
+ desc 'Run mysql, sqlite, and postgresql tests by default'
24
+ task :default => :spec
25
+
26
+ desc 'Run mysql, sqlite, and postgresql tests'
27
+ task :spec do
28
+ tasks = defined?(JRUBY_VERSION) ?
29
+ %w(spec_jdbcmysql spec_jdbcpostgresql) :
30
+ %w(spec_mysql spec_postgresql)
31
+ run_without_aborting(*tasks)
32
+ end
33
+
34
+ def run_without_aborting(*tasks)
35
+ errors = []
36
+
37
+ tasks.each do |task|
38
+ begin
39
+ Rake::Task[task].invoke
40
+ rescue Exception
41
+ errors << task
42
+ end
43
+ end
44
+
45
+ abort "Errors running #{errors.join(', ')}" if errors.any?
46
+ end
47
+
48
+ task :default => :spec
49
+
50
+ for adapter in %w( mysql postgresql )
51
+
52
+ Spec::Rake::SpecTask.new("spec_#{adapter}") do |t|
53
+ t.spec_opts = ['--color']
54
+ t.rcov = false
55
+ if adapter =~ /jdbc/
56
+ t.libs << "spec/connections/jdbc_#{adapter}"
57
+ else
58
+ t.libs << "spec/connections/#{adapter}"
59
+ end
60
+ t.spec_files = FileList[ 'spec/cases/**/*_spec.rb', 'spec/lib/**/*_spec.rb' ]
61
+ end
62
+
63
+ namespace adapter do
64
+ #task "spec_#{adapter}" => [ "rebuild_#{adapter}_databases" ]
65
+ task :spec => "spec_#{adapter}"
66
+ end
67
+ end
68
+
69
+ # DB ==================================================================
70
+ # CREATE USER yaml_conditions
71
+ MYSQL_DB_USER = 'yaml_conditions'
72
+
73
+ namespace :mysql do
74
+ desc 'Build the MySQL test databases'
75
+ task :build_databases do
76
+ %x( echo "create DATABASE yaml_conditions_db DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci " | mysql --user=#{MYSQL_DB_USER})
77
+ end
78
+
79
+ desc 'Drop the MySQL test databases'
80
+ task :drop_databases do
81
+ %x( mysqladmin -u#{MYSQL_DB_USER} -f drop yaml_conditions_db )
82
+ end
83
+
84
+ desc 'Rebuild the MySQL test databases'
85
+ task :rebuild_databases => [:drop_databases, :build_databases]
86
+ end
87
+
88
+ task :build_mysql_databases => 'mysql:build_databases'
89
+ task :drop_mysql_databases => 'mysql:drop_databases'
90
+ task :rebuild_mysql_databases => 'mysql:rebuild_databases'
91
+
92
+
93
+ namespace :postgresql do
94
+ desc 'Build the PostgreSQL test databases'
95
+ task :build_databases do
96
+ %x( createdb -E UTF8 yaml_conditions_db )
97
+ end
98
+
99
+ desc 'Drop the PostgreSQL test databases'
100
+ task :drop_databases do
101
+ %x( dropdb yaml_conditions_db )
102
+ end
103
+
104
+ desc 'Rebuild the PostgreSQL test databases'
105
+ task :rebuild_databases => [:drop_databases, :build_databases]
106
+ end
107
+
108
+ task :build_postgresql_databases => 'postgresql:build_databases'
109
+ task :drop_postgresql_databases => 'postgresql:drop_databases'
110
+ task :rebuild_postgresql_databases => 'postgresql:rebuild_databases'
111
+
112
+ # Rcov ================================================================
113
+ namespace :spec do
114
+ desc 'Mesures test coverage'
115
+ task :coverage do
116
+ rm_f "coverage"
117
+ rcov = "rcov --text-summary -Ilib"
118
+ system("#{rcov} --no-html --no-color spec/lib/*_spec.rb")
119
+ end
120
+ end
121
+
122
+ # Website =============================================================
123
+ # Building docs requires HAML and the hanna gem:
124
+ # gem install mislav-hanna --source=http://gems.github.com
125
+
126
+ desc 'Generate RDoc under doc/api'
127
+ task 'doc' => ['doc:api']
128
+
129
+ task 'doc:api' => ['doc/api/index.html']
130
+
131
+ file 'doc/api/index.html' => FileList['lib/**/*.rb','README.rdoc'] do |f|
132
+ require 'rbconfig'
133
+ hanna = RbConfig::CONFIG['ruby_install_name'].sub('ruby', 'hanna')
134
+ rb_files = f.prerequisites
135
+ sh((<<-end).gsub(/\s+/, ' '))
136
+ #{hanna}
137
+ --charset utf8
138
+ --fmt html
139
+ --inline-source
140
+ --line-numbers
141
+ --main README.rdoc
142
+ --op doc/api
143
+ --title 'RTT API Documentation'
144
+ #{rb_files.join(' ')}
145
+ end
146
+ end
147
+ CLEAN.include 'doc/api'
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: encryption_accessor
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Marcelo Giorgi
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-18 00:00:00 -02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: spec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ description: Accessor's to encrypt/decrypt fields when data is stored encrypted on DB
36
+ email: marklazz.uy@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README
43
+ - lib/aes_crypt.rb
44
+ - lib/encryption_accessor.rb
45
+ - tasks/encryption_accessor.rake
46
+ files:
47
+ - README
48
+ - Rakefile
49
+ - lib/aes_crypt.rb
50
+ - lib/encryption_accessor.rb
51
+ - tasks/encryption_accessor.rake
52
+ - Manifest
53
+ - encryption_accessor.gemspec
54
+ has_rdoc: true
55
+ homepage: https://github.com/marklazz/encryption_accessor
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options:
60
+ - --line-numbers
61
+ - --inline-source
62
+ - --title
63
+ - Encryption_accessor
64
+ - --main
65
+ - README
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ hash: 11
83
+ segments:
84
+ - 1
85
+ - 2
86
+ version: "1.2"
87
+ requirements: []
88
+
89
+ rubyforge_project: encryption_accessor
90
+ rubygems_version: 1.3.7
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: Accessor's to encrypt/decrypt fields when data is stored encrypted on DB
94
+ test_files: []
95
+