pivotal-sentry 0.4.0
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/.gitignore +3 -0
- data/CHANGELOG +58 -0
- data/MIT-LICENSE +20 -0
- data/README +94 -0
- data/RUNNING_UNIT_TESTS +42 -0
- data/Rakefile +192 -0
- data/VERSION +1 -0
- data/init.rb +1 -0
- data/lib/active_record/sentry.rb +94 -0
- data/lib/sentry.rb +46 -0
- data/lib/sentry/asymmetric_sentry.rb +144 -0
- data/lib/sentry/asymmetric_sentry_callback.rb +17 -0
- data/lib/sentry/sha_sentry.rb +41 -0
- data/lib/sentry/symmetric_sentry.rb +79 -0
- data/lib/sentry/symmetric_sentry_callback.rb +17 -0
- data/tasks/sentry.rake +9 -0
- data/test/abstract_unit.rb +44 -0
- data/test/asymmetric_sentry_callback_test.rb +72 -0
- data/test/asymmetric_sentry_test.rb +88 -0
- data/test/database.yml +18 -0
- data/test/fixtures/user.rb +26 -0
- data/test/fixtures/users.yml +10 -0
- data/test/keys/encrypted_private +12 -0
- data/test/keys/encrypted_public +4 -0
- data/test/keys/private +9 -0
- data/test/keys/public +4 -0
- data/test/schema.rb +10 -0
- data/test/sha_sentry_test.rb +35 -0
- data/test/symmetric_sentry_callback_test.rb +38 -0
- data/test/symmetric_sentry_test.rb +37 -0
- data/test/tests.rb +2 -0
- metadata +92 -0
data/.gitignore
ADDED
data/CHANGELOG
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
*0.3.1* (7 Jan 2006)
|
2
|
+
|
3
|
+
* removed useless breakpoint [Solomon White]
|
4
|
+
|
5
|
+
*0.3* (29 Oct 2005)
|
6
|
+
|
7
|
+
* added rake task for generating asymmetric keys
|
8
|
+
* Switch to migrations and schema for testing setup
|
9
|
+
|
10
|
+
*0.2.9* (18 Sep 2005)
|
11
|
+
|
12
|
+
* First RubyForge release.
|
13
|
+
|
14
|
+
*0.2.8* (17 Sep 2005)
|
15
|
+
|
16
|
+
* Added Active Record unit tests
|
17
|
+
|
18
|
+
*0.2.7* (17 Sep 2005)
|
19
|
+
|
20
|
+
* Added rdocs and stubs for AR unit tests
|
21
|
+
|
22
|
+
*0.2.6* (2 Aug 2005)
|
23
|
+
|
24
|
+
* Fixed generates_crypted so it adds attribute accessors
|
25
|
+
|
26
|
+
*0.2.5* (27 Jul 2005)
|
27
|
+
|
28
|
+
* Set ActiveRecord callback objects to only encrypt fields when they are not empty.
|
29
|
+
|
30
|
+
*0.2.4* (11 Jul 2005)
|
31
|
+
|
32
|
+
* Split ActiveRecord callback methods into their own classes.
|
33
|
+
* Set AR virtual columns to fail silently on errors.
|
34
|
+
|
35
|
+
*0.2.3* (11 Jul 2005)
|
36
|
+
|
37
|
+
* Added ActiveRecord callback objects for SymmetricSentry and AsymmetricSentry. +one_way_encrypt+ is depreciated.
|
38
|
+
* Readme doc added too
|
39
|
+
|
40
|
+
*0.2.1* (9 Jul 2005)
|
41
|
+
|
42
|
+
* vastly simplified one_way_encrypt at danp's suggestion. Use this in your model to try it out:
|
43
|
+
|
44
|
+
+one_way_encrypt :password*
|
45
|
+
|
46
|
+
That generates an SHA hash of model.password to model.crypted_password which is saved in the DB.
|
47
|
+
model.password is a virtual field. Continue using validates_confirmation_of for confirmation.
|
48
|
+
|
49
|
+
|
50
|
+
*0.2* (9 Jul 2005)
|
51
|
+
|
52
|
+
* added ActiveRecord::Base#one_way_encrypt class method to hash passwords with SHA
|
53
|
+
* Renamed core classes to SymmetricSentry and AsymmetricSentry
|
54
|
+
* Test Suite added
|
55
|
+
|
56
|
+
*0.1*
|
57
|
+
|
58
|
+
* Initial Import
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2005 Rick Olson
|
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.
|
data/README
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
= Sentry lib - painless encryption library
|
2
|
+
|
3
|
+
Sentry is a simple wrapper around the mostly undocumented OpenSSL encryption classes.
|
4
|
+
For now, look at the pseudo test cases in sentry.rb until I can get more examples written out.
|
5
|
+
|
6
|
+
== Resources
|
7
|
+
|
8
|
+
Install
|
9
|
+
|
10
|
+
* gem install sentry
|
11
|
+
|
12
|
+
Rubyforge project
|
13
|
+
|
14
|
+
* http://rubyforge.org/projects/sentry
|
15
|
+
|
16
|
+
RDocs
|
17
|
+
|
18
|
+
* http://sentry.rubyforge.org
|
19
|
+
|
20
|
+
Subversion
|
21
|
+
|
22
|
+
* http://techno-weenie.net/svn/projects/sentry
|
23
|
+
|
24
|
+
Collaboa
|
25
|
+
|
26
|
+
* http://collaboa.techno-weenie.net/repository/browse/sentry
|
27
|
+
|
28
|
+
== Using with ActiveRecord
|
29
|
+
|
30
|
+
I wrote this for the purpose of encrypting ActiveRecord attributes. Just <tt>require 'sentry'</tt>, and some new
|
31
|
+
class methods will be available to you:
|
32
|
+
|
33
|
+
=== generates_crypted
|
34
|
+
|
35
|
+
generates_crypted :password, :mode => :sha | :symmetric | :asymmetric
|
36
|
+
|
37
|
+
This is the generic class method to use. Default mode is :sha.
|
38
|
+
|
39
|
+
=== generates_crypted_hash_of
|
40
|
+
|
41
|
+
generates_crypted_hash_of :password
|
42
|
+
|
43
|
+
This is a shortcut for using SHA encryption. No different than specifying <tt>generates_crypted :password</tt>. In the above
|
44
|
+
example, model.password is a virtual field, and the SHA hash is saved to model.crypted_password
|
45
|
+
|
46
|
+
=== asymmetrically_encrypts
|
47
|
+
|
48
|
+
asymmetrically_encrypts :password
|
49
|
+
|
50
|
+
This is a shortcut for using an asymmetrical algorithm with a private/public key file. To use this, generate a public and
|
51
|
+
private key with Sentry::AsymmetricalSentry.save_random_rsa_key(private_key_file, public_key_file). If you want to encrypt the
|
52
|
+
private key file with a symmetrical algorithm, pass a secret key (neither the key nor the decrypted value will be stored).
|
53
|
+
|
54
|
+
Sentry::AsymmetricSentry.save_random_rsa_key(private_key_file, public_key_file, :key => 'secret_password')
|
55
|
+
|
56
|
+
What that does, is requires you to pass in that same secret password when accesing the method.
|
57
|
+
|
58
|
+
class Model < ActiveRecord::Base
|
59
|
+
generates_crypted :password, :mode => :asymmetric
|
60
|
+
end
|
61
|
+
|
62
|
+
model.password = '5234523453425'
|
63
|
+
model.save # password is encrypted and saved to crypted_password in the database,
|
64
|
+
# model.password is cleared and becomes a virtual field.
|
65
|
+
model.password('secret_password')
|
66
|
+
=> '5234523453425'
|
67
|
+
|
68
|
+
The public and private key file names can be set in config/environment.rb
|
69
|
+
|
70
|
+
Sentry::AsymmetricSentry.default_public_key_file = "#{RAILS_ROOT}/config/public.key"
|
71
|
+
Sentry::AsymmetricSentry.default_private_key_file = "#{RAILS_ROOT}/config/private.key"
|
72
|
+
|
73
|
+
If the private key was encrypted with the Sentry::AsymmetricalSentry#save_random_rsa_key, you must provide that same key
|
74
|
+
when accessing the AR model.
|
75
|
+
|
76
|
+
=== symmetrically_encrypts
|
77
|
+
|
78
|
+
symmetrically_encrypts :password
|
79
|
+
|
80
|
+
This is a shortcut for using a symmetrical algorithm with a secret password to encrypt the field.
|
81
|
+
|
82
|
+
class Model < ActiveRecord::Base
|
83
|
+
generates_crypted :password, :mode => :symmetric
|
84
|
+
end
|
85
|
+
|
86
|
+
model.password = '5234523453425'
|
87
|
+
model.save # password is encrypted and saved to crypted_password in the database,
|
88
|
+
# model.password is cleared and becomes a virtual field.
|
89
|
+
model.password
|
90
|
+
=> '5234523453425'
|
91
|
+
|
92
|
+
The secret password can be set in config/environment.rb
|
93
|
+
|
94
|
+
Sentry::SymmetricSentry.default_key = "secret_password"
|
data/RUNNING_UNIT_TESTS
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
== Creating the test database
|
2
|
+
|
3
|
+
The default name for the test databases is "sentry_plugin_test". If you
|
4
|
+
want to use another database name then be sure to update the connection
|
5
|
+
adapter setups you want to test with in test/database.yml.
|
6
|
+
|
7
|
+
Make sure that you create database objects with the same user that you specified in i
|
8
|
+
database.yml otherwise (on Postgres, at least) tests for default values will fail.
|
9
|
+
|
10
|
+
== Running with Rake
|
11
|
+
|
12
|
+
The easiest way to run the unit tests is through Rake. The default task runs
|
13
|
+
the entire test suite for the sqlite adapter. You can also run the suite on just
|
14
|
+
one adapter by passing the DB environment variable.
|
15
|
+
|
16
|
+
rake test DB=mysql
|
17
|
+
|
18
|
+
For more information, checkout the full array of rake tasks with "rake -T"
|
19
|
+
|
20
|
+
Rake can be found at http://rake.rubyforge.org
|
21
|
+
|
22
|
+
== Running by hand
|
23
|
+
|
24
|
+
Unit tests are located in test directory. If you only want to run a single test suite,
|
25
|
+
or don't want to bother with Rake, you can do so with something like:
|
26
|
+
|
27
|
+
cd test; DB=mysql ruby base_test.rb
|
28
|
+
|
29
|
+
That'll run the base suite using the MySQL adapter. Change the adapter
|
30
|
+
and test suite name as needed.
|
31
|
+
|
32
|
+
== Faster tests
|
33
|
+
|
34
|
+
If you are using a database that supports transactions, you can set the
|
35
|
+
"AR_TX_FIXTURES" environment variable to "yes" to use transactional fixtures.
|
36
|
+
This gives a very large speed boost. With rake:
|
37
|
+
|
38
|
+
rake AR_TX_FIXTURES=yes
|
39
|
+
|
40
|
+
Or, by hand:
|
41
|
+
|
42
|
+
AR_TX_FIXTURES=yes ruby -I connections/native_sqlite3 base_test.rb
|
data/Rakefile
ADDED
@@ -0,0 +1,192 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
Gem::manage_gems
|
4
|
+
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require 'rake/packagetask'
|
7
|
+
require 'rake/gempackagetask'
|
8
|
+
require 'rake/testtask'
|
9
|
+
require 'rake/contrib/rubyforgepublisher'
|
10
|
+
|
11
|
+
PKG_NAME = 'sentry'
|
12
|
+
PKG_VERSION = '0.3.1'
|
13
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
14
|
+
PROD_HOST = "technoweenie@bidwell.textdrive.com"
|
15
|
+
RUBY_FORGE_PROJECT = 'sentry'
|
16
|
+
RUBY_FORGE_USER = 'technoweenie'
|
17
|
+
|
18
|
+
task :default => [:test]
|
19
|
+
Rake::TestTask.new("test") do |t|
|
20
|
+
t.libs << "test"
|
21
|
+
t.pattern = "test/*_test.rb"
|
22
|
+
t.verbose = true
|
23
|
+
end
|
24
|
+
|
25
|
+
load 'tasks/sentry.rake'
|
26
|
+
|
27
|
+
Rake::RDocTask.new do |rdoc|
|
28
|
+
rdoc.rdoc_dir = 'doc'
|
29
|
+
rdoc.title = "#{PKG_NAME} -- painless encryption for Active Record"
|
30
|
+
rdoc.options << '--line-numbers --inline-source --accessor cattr_accessor=object'
|
31
|
+
rdoc.template = "#{ENV['template']}.rb" if ENV['template']
|
32
|
+
rdoc.rdoc_files.include('README', 'CHANGELOG', 'RUNNING_UNIT_TESTS')
|
33
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
34
|
+
end
|
35
|
+
|
36
|
+
spec = Gem::Specification.new do |s|
|
37
|
+
s.name = PKG_NAME
|
38
|
+
s.version = PKG_VERSION
|
39
|
+
s.platform = Gem::Platform::RUBY
|
40
|
+
s.summary = "Sentry provides painless encryption services with a wrapper around some OpenSSL classes"
|
41
|
+
s.files = FileList["{lib,test}/**/*"].to_a + %w(README MIT-LICENSE CHANGELOG RUNNING_UNIT_TESTS)
|
42
|
+
s.files.delete "test/sentry_plugin.sqlite.db"
|
43
|
+
s.files.delete "test/sentry_plugin.sqlite3.db"
|
44
|
+
s.require_path = 'lib'
|
45
|
+
s.autorequire = 'sentry'
|
46
|
+
s.has_rdoc = true
|
47
|
+
s.test_file = 'test/tests.rb'
|
48
|
+
s.author = "Rick Olson"
|
49
|
+
s.email = "technoweenie@gmail.com"
|
50
|
+
s.homepage = "http://techno-weenie.net"
|
51
|
+
end
|
52
|
+
|
53
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
54
|
+
pkg.need_tar = true
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "Publish the API documentation"
|
58
|
+
task :pdoc => [:rdoc] do
|
59
|
+
Rake::RubyForgePublisher.new(RUBY_FORGE_PROJECT, RUBY_FORGE_USER).upload
|
60
|
+
end
|
61
|
+
|
62
|
+
desc 'Publish the gem and API docs'
|
63
|
+
task :publish => [:pdoc, :rubyforge_upload]
|
64
|
+
|
65
|
+
desc "Publish the release files to RubyForge."
|
66
|
+
task :rubyforge_upload => :package do
|
67
|
+
files = %w(gem tgz).map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
|
68
|
+
|
69
|
+
if RUBY_FORGE_PROJECT then
|
70
|
+
require 'net/http'
|
71
|
+
require 'open-uri'
|
72
|
+
|
73
|
+
project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
|
74
|
+
project_data = open(project_uri) { |data| data.read }
|
75
|
+
group_id = project_data[/[?&]group_id=(\d+)/, 1]
|
76
|
+
raise "Couldn't get group id" unless group_id
|
77
|
+
|
78
|
+
# This echos password to shell which is a bit sucky
|
79
|
+
if ENV["RUBY_FORGE_PASSWORD"]
|
80
|
+
password = ENV["RUBY_FORGE_PASSWORD"]
|
81
|
+
else
|
82
|
+
print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
|
83
|
+
password = STDIN.gets.chomp
|
84
|
+
end
|
85
|
+
|
86
|
+
login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
|
87
|
+
data = [
|
88
|
+
"login=1",
|
89
|
+
"form_loginname=#{RUBY_FORGE_USER}",
|
90
|
+
"form_pw=#{password}"
|
91
|
+
].join("&")
|
92
|
+
http.post("/account/login.php", data)
|
93
|
+
end
|
94
|
+
|
95
|
+
cookie = login_response["set-cookie"]
|
96
|
+
raise "Login failed" unless cookie
|
97
|
+
headers = { "Cookie" => cookie }
|
98
|
+
|
99
|
+
release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
|
100
|
+
release_data = open(release_uri, headers) { |data| data.read }
|
101
|
+
package_id = release_data[/[?&]package_id=(\d+)/, 1]
|
102
|
+
raise "Couldn't get package id" unless package_id
|
103
|
+
|
104
|
+
first_file = true
|
105
|
+
release_id = ""
|
106
|
+
|
107
|
+
files.each do |filename|
|
108
|
+
basename = File.basename(filename)
|
109
|
+
file_ext = File.extname(filename)
|
110
|
+
file_data = File.open(filename, "rb") { |file| file.read }
|
111
|
+
|
112
|
+
puts "Releasing #{basename}..."
|
113
|
+
|
114
|
+
release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
|
115
|
+
release_date = Time.now.strftime("%Y-%m-%d %H:%M")
|
116
|
+
type_map = {
|
117
|
+
".zip" => "3000",
|
118
|
+
".tgz" => "3110",
|
119
|
+
".gz" => "3110",
|
120
|
+
".gem" => "1400"
|
121
|
+
}; type_map.default = "9999"
|
122
|
+
type = type_map[file_ext]
|
123
|
+
boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
|
124
|
+
|
125
|
+
query_hash = if first_file then
|
126
|
+
{
|
127
|
+
"group_id" => group_id,
|
128
|
+
"package_id" => package_id,
|
129
|
+
"release_name" => PKG_FILE_NAME,
|
130
|
+
"release_date" => release_date,
|
131
|
+
"type_id" => type,
|
132
|
+
"processor_id" => "8000", # Any
|
133
|
+
"release_notes" => "",
|
134
|
+
"release_changes" => "",
|
135
|
+
"preformatted" => "1",
|
136
|
+
"submit" => "1"
|
137
|
+
}
|
138
|
+
else
|
139
|
+
{
|
140
|
+
"group_id" => group_id,
|
141
|
+
"release_id" => release_id,
|
142
|
+
"package_id" => package_id,
|
143
|
+
"step2" => "1",
|
144
|
+
"type_id" => type,
|
145
|
+
"processor_id" => "8000", # Any
|
146
|
+
"submit" => "Add This File"
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
query = "?" + query_hash.map do |(name, value)|
|
151
|
+
[name, URI.encode(value)].join("=")
|
152
|
+
end.join("&")
|
153
|
+
|
154
|
+
data = [
|
155
|
+
"--" + boundary,
|
156
|
+
"Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
|
157
|
+
"Content-Type: application/octet-stream",
|
158
|
+
"Content-Transfer-Encoding: binary",
|
159
|
+
"", file_data, ""
|
160
|
+
].join("\x0D\x0A")
|
161
|
+
|
162
|
+
release_headers = headers.merge(
|
163
|
+
"Content-Type" => "multipart/form-data; boundary=#{boundary}"
|
164
|
+
)
|
165
|
+
|
166
|
+
target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
|
167
|
+
http.post(target + query, data, release_headers)
|
168
|
+
end
|
169
|
+
|
170
|
+
if first_file then
|
171
|
+
release_id = release_response.body[/release_id=(\d+)/, 1]
|
172
|
+
raise("Couldn't get release id") unless release_id
|
173
|
+
end
|
174
|
+
|
175
|
+
first_file = false
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
begin
|
181
|
+
require 'jeweler'
|
182
|
+
Jeweler::Tasks.new do |gemspec|
|
183
|
+
gemspec.name = "sentry"
|
184
|
+
gemspec.summary = "Asymmetric encryption of active record fields"
|
185
|
+
gemspec.description = "Asymmetric encryption of active record fields"
|
186
|
+
gemspec.email = "commoncode@pivotallabs.com"
|
187
|
+
gemspec.homepage = "http://github.com/pivotal/sentry"
|
188
|
+
gemspec.authors = ["John Pelly", "David Stevenson"]
|
189
|
+
end
|
190
|
+
rescue LoadError
|
191
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
192
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.0
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'sentry'
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module ActiveRecord # :nodoc:
|
2
|
+
module Sentry
|
3
|
+
def self.included(base) # :nodoc:
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def generates_crypted(attr_name, options = {})
|
9
|
+
mode = options[:mode] || :asymmetric
|
10
|
+
case mode
|
11
|
+
#when :sha
|
12
|
+
# generates_crypted_hash_of(attr_name)
|
13
|
+
when :asymmetric, :asymmetrical
|
14
|
+
asymmetrically_encrypts(attr_name)
|
15
|
+
#when :symmetric, :symmetrical
|
16
|
+
# symmetrically_encrypts(attr_name)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
#def generates_crypted_hash_of(attribute)
|
21
|
+
# before_validation ::Sentry::ShaSentry.new(attribute)
|
22
|
+
# attr_accessor attribute
|
23
|
+
#end
|
24
|
+
|
25
|
+
def asymmetrically_encrypts(attr_name, options = {})
|
26
|
+
#temp_sentry = ::Sentry::AsymmetricSentryCallback.new(attr_name)
|
27
|
+
#before_validation temp_sentry
|
28
|
+
#after_save temp_sentry
|
29
|
+
unless instance_methods.include?("#{attr_name}_with_decryption")
|
30
|
+
define_read_methods
|
31
|
+
|
32
|
+
define_method("#{attr_name}_with_decryption") do |*optional|
|
33
|
+
begin
|
34
|
+
return decrypted_values[attr_name] unless decrypted_values[attr_name].nil?
|
35
|
+
crypted_value = self.send("#{attr_name}_without_decryption")
|
36
|
+
return nil if crypted_value.nil?
|
37
|
+
key = optional.shift || (options[:key].is_a?(Proc) ? options[:key].call : options[:key])
|
38
|
+
decrypted_values[attr_name] = ::Sentry::AsymmetricSentry.decrypt_from_base64(crypted_value, key)
|
39
|
+
return decrypted_values[attr_name]
|
40
|
+
rescue
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
alias_method_chain attr_name, :decryption
|
46
|
+
alias_method "crypted_#{attr_name}", "#{attr_name}_without_decryption"
|
47
|
+
alias_method "#{attr_name}_before_type_cast", "#{attr_name}_with_decryption"
|
48
|
+
|
49
|
+
define_method("#{attr_name}_with_encryption=") do |value|
|
50
|
+
decrypted_values[attr_name] = value
|
51
|
+
self.send("#{attr_name}_without_encryption=", ::Sentry::SymmetricSentry.encrypt_to_base64(decrypted_values[attr_name]))
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
alias_method_chain "#{attr_name}=", :encryption
|
56
|
+
#define_method("crypted_#{attr_name}") do
|
57
|
+
# self.attributes[attr_name.to_s]
|
58
|
+
#end
|
59
|
+
#
|
60
|
+
private
|
61
|
+
define_method(:decrypted_values) do
|
62
|
+
@decrypted_values ||= {}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
#def symmetrically_encrypts(attr_name)
|
68
|
+
# temp_sentry = ::Sentry::SymmetricSentryCallback.new(attr_name)
|
69
|
+
# before_validation temp_sentry
|
70
|
+
# after_save temp_sentry
|
71
|
+
#
|
72
|
+
# define_method(attr_name) do
|
73
|
+
# send("#{attr_name}!") rescue nil
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# define_method("#{attr_name}!") do
|
77
|
+
# return decrypted_values[attr_name] unless decrypted_values[attr_name].nil?
|
78
|
+
# return nil if send("crypted_#{attr_name}").nil?
|
79
|
+
# ::Sentry::SymmetricSentry.decrypt_from_base64(send("crypted_#{attr_name}"))
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# define_method("#{attr_name}=") do |value|
|
83
|
+
# decrypted_values[attr_name] = value
|
84
|
+
# nil
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
# private
|
88
|
+
# define_method(:decrypted_values) do
|
89
|
+
# @decrypted_values ||= {}
|
90
|
+
# end
|
91
|
+
#end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|