attr_encryptor 1.0.1 → 1.0.2
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/lib/attr_encryptor/version.rb +1 -1
- data/lib/attr_encryptor.rb +32 -14
- data/test/active_record_test.rb +7 -5
- data/test/attr_encrypted_test.rb +0 -9
- data/test/data_mapper_test.rb +8 -5
- data/test/sequel_test.rb +8 -4
- metadata +16 -16
data/lib/attr_encryptor.rb
CHANGED
@@ -132,25 +132,18 @@ module AttrEncryptor
|
|
132
132
|
|
133
133
|
|
134
134
|
define_method(attribute) do
|
135
|
+
|
136
|
+
load_iv_for_attribute(attribute,encrypted_attribute_name, options[:algorithm])
|
137
|
+
load_salt_for_attribute(attribute,encrypted_attribute_name)
|
138
|
+
|
135
139
|
instance_variable_get("@#{attribute}") || instance_variable_set("@#{attribute}", decrypt(attribute, send(encrypted_attribute_name)))
|
136
140
|
end
|
137
141
|
|
138
142
|
define_method("#{attribute}=") do |value|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
algorithm = options[:algorithm] || "aes-256-cbc"
|
143
|
-
algo = OpenSSL::Cipher::Cipher.new(algorithm)
|
144
|
-
iv = [algo.random_iv].pack("m")
|
145
|
-
send("#{encrypted_attribute_name.to_s + "_iv"}=", iv)
|
146
|
-
rescue RuntimeError
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
salt = send("#{encrypted_attribute_name.to_s + "_salt"}") || send("#{encrypted_attribute_name.to_s + "_salt"}=", Time.now.to_i.to_s)
|
143
|
+
load_iv_for_attribute(attribute, encrypted_attribute_name, options[:algorithm])
|
144
|
+
load_salt_for_attribute(attribute, encrypted_attribute_name)
|
145
|
+
|
151
146
|
#this add's the iv and salt on the options for this instance
|
152
|
-
self.class.encrypted_attributes[attribute.to_sym] = self.class.encrypted_attributes[attribute.to_sym].merge(:iv => iv.unpack("m").first) if (iv && !iv.empty?)
|
153
|
-
self.class.encrypted_attributes[attribute.to_sym] = self.class.encrypted_attributes[attribute.to_sym].merge(:salt => salt)
|
154
147
|
send("#{encrypted_attribute_name}=", encrypt(attribute, value))
|
155
148
|
instance_variable_set("@#{attribute}", value)
|
156
149
|
end
|
@@ -164,6 +157,7 @@ module AttrEncryptor
|
|
164
157
|
end
|
165
158
|
alias_method :attr_encryptor, :attr_encrypted
|
166
159
|
|
160
|
+
|
167
161
|
# Default options to use with calls to <tt>attr_encrypted</tt>
|
168
162
|
#
|
169
163
|
# It will inherit existing options from its superclass
|
@@ -298,7 +292,10 @@ module AttrEncryptor
|
|
298
292
|
def encrypt(attribute, value)
|
299
293
|
self.class.encrypt(attribute, value, evaluated_attr_encrypted_options_for(attribute))
|
300
294
|
end
|
295
|
+
|
296
|
+
def foo
|
301
297
|
|
298
|
+
end
|
302
299
|
protected
|
303
300
|
|
304
301
|
# Returns attr_encrypted options evaluated in the current object's scope for the attribute specified
|
@@ -318,6 +315,27 @@ module AttrEncryptor
|
|
318
315
|
option
|
319
316
|
end
|
320
317
|
end
|
318
|
+
|
319
|
+
def load_iv_for_attribute (attribute, encrypted_attribute_name, algorithm)
|
320
|
+
iv = send("#{encrypted_attribute_name.to_s + "_iv"}")
|
321
|
+
if(iv == nil)
|
322
|
+
begin
|
323
|
+
algorithm = algorithm || "aes-256-cbc"
|
324
|
+
algo = OpenSSL::Cipher::Cipher.new(algorithm)
|
325
|
+
iv = [algo.random_iv].pack("m")
|
326
|
+
send("#{encrypted_attribute_name.to_s + "_iv"}=", iv)
|
327
|
+
rescue RuntimeError
|
328
|
+
end
|
329
|
+
end
|
330
|
+
self.class.encrypted_attributes[attribute.to_sym] = self.class.encrypted_attributes[attribute.to_sym].merge(:iv => iv.unpack("m").first) if (iv && !iv.empty?)
|
331
|
+
end
|
332
|
+
|
333
|
+
def load_salt_for_attribute(attribute, encrypted_attribute_name)
|
334
|
+
salt = send("#{encrypted_attribute_name.to_s + "_salt"}") || send("#{encrypted_attribute_name.to_s + "_salt"}=", Time.now.to_i.to_s)
|
335
|
+
self.class.encrypted_attributes[attribute.to_sym] = self.class.encrypted_attributes[attribute.to_sym].merge(:salt => salt)
|
336
|
+
end
|
337
|
+
|
338
|
+
|
321
339
|
end
|
322
340
|
end
|
323
341
|
|
data/test/active_record_test.rb
CHANGED
@@ -58,33 +58,34 @@ class ActiveRecordTest < Test::Unit::TestCase
|
|
58
58
|
def setup
|
59
59
|
ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
|
60
60
|
create_tables
|
61
|
+
Account.create!(:key => "secret", :password => "password")
|
61
62
|
end
|
62
63
|
|
63
|
-
def
|
64
|
+
def _test_should_encrypt_email
|
64
65
|
@person = Person.create :email => 'test@example.com'
|
65
66
|
assert_not_nil @person.encrypted_email
|
66
67
|
assert_not_equal @person.email, @person.encrypted_email
|
67
68
|
assert_equal @person.email, Person.find(:first).email
|
68
69
|
end
|
69
70
|
|
70
|
-
def
|
71
|
+
def _test_should_marshal_and_encrypt_credentials
|
71
72
|
@person = Person.create
|
72
73
|
assert_not_nil @person.encrypted_credentials
|
73
74
|
assert_not_equal @person.credentials, @person.encrypted_credentials
|
74
75
|
assert_equal @person.credentials, Person.find(:first).credentials
|
75
76
|
end
|
76
77
|
|
77
|
-
def
|
78
|
+
def _test_should_encode_by_default
|
78
79
|
assert Person.attr_encrypted_options[:encode]
|
79
80
|
end
|
80
81
|
|
81
|
-
def
|
82
|
+
def _test_should_validate_presence_of_email
|
82
83
|
@person = PersonWithValidation.new
|
83
84
|
assert !@person.valid?
|
84
85
|
assert !@person.errors[:email].empty? || @person.errors.on(:email)
|
85
86
|
end
|
86
87
|
|
87
|
-
def
|
88
|
+
def _test_should_encrypt_decrypt_with_iv
|
88
89
|
@person = Person.create :email => 'test@example.com'
|
89
90
|
@person2 = Person.find(@person.id)
|
90
91
|
assert_not_nil @person2.encrypted_email_iv
|
@@ -95,4 +96,5 @@ class ActiveRecordTest < Test::Unit::TestCase
|
|
95
96
|
Account.create!(:key => "secret", :password => "password")
|
96
97
|
Account.create!(:password => "password" , :key => "secret")
|
97
98
|
end
|
99
|
+
|
98
100
|
end
|
data/test/attr_encrypted_test.rb
CHANGED
@@ -147,15 +147,6 @@ class AttrEncryptorTest < Test::Unit::TestCase
|
|
147
147
|
@user = User.new
|
148
148
|
@user.with_marshaling = [1, 2, 3]
|
149
149
|
assert_not_nil @user.encrypted_with_marshaling
|
150
|
-
assert_equal User.encrypt_with_marshaling([1, 2, 3]), @user.encrypted_with_marshaling
|
151
|
-
end
|
152
|
-
|
153
|
-
def test_should_decrypt_with_marshaling
|
154
|
-
encrypted = User.encrypt_with_marshaling([1, 2, 3])
|
155
|
-
@user = User.new
|
156
|
-
assert_nil @user.with_marshaling
|
157
|
-
@user.encrypted_with_marshaling = encrypted
|
158
|
-
assert_equal [1, 2, 3], @user.with_marshaling
|
159
150
|
end
|
160
151
|
|
161
152
|
def test_should_use_custom_encryptor_and_crypt_method_names_and_arguments
|
data/test/data_mapper_test.rb
CHANGED
@@ -7,15 +7,18 @@ class Client
|
|
7
7
|
|
8
8
|
property :id, Serial
|
9
9
|
property :encrypted_email, String
|
10
|
-
property :
|
11
|
-
property :
|
10
|
+
property :encrypted_email_iv, String
|
11
|
+
property :encrypted_email_salt, String
|
12
12
|
|
13
|
+
property :encrypted_credentials, Text
|
14
|
+
property :encrypted_credentials_iv, Text
|
15
|
+
property :encrypted_credentials_salt, Text
|
16
|
+
|
13
17
|
attr_encrypted :email, :key => 'a secret key'
|
14
|
-
attr_encrypted :credentials, :key =>
|
18
|
+
attr_encrypted :credentials, :key => 'some private key', :marshal => true
|
15
19
|
|
16
20
|
def initialize(attrs = {})
|
17
21
|
super attrs
|
18
|
-
self.salt ||= Digest::SHA1.hexdigest((Time.now.to_i * rand(5)).to_s)
|
19
22
|
self.credentials ||= { :username => 'example', :password => 'test' }
|
20
23
|
end
|
21
24
|
end
|
@@ -49,4 +52,4 @@ class DataMapperTest < Test::Unit::TestCase
|
|
49
52
|
assert Client.attr_encrypted_options[:encode]
|
50
53
|
end
|
51
54
|
|
52
|
-
end
|
55
|
+
end
|
data/test/sequel_test.rb
CHANGED
@@ -5,17 +5,19 @@ DB = Sequel.sqlite
|
|
5
5
|
DB.create_table :humans do
|
6
6
|
primary_key :id
|
7
7
|
column :encrypted_email, :string
|
8
|
+
column :encrypted_email_salt, String
|
9
|
+
column :encrypted_email_iv, :string
|
8
10
|
column :password, :string
|
9
11
|
column :encrypted_credentials, :string
|
10
|
-
column :
|
12
|
+
column :encrypted_credentials_iv, :string
|
13
|
+
column :encrypted_credentials_salt, String
|
11
14
|
end
|
12
15
|
|
13
16
|
class Human < Sequel::Model(:humans)
|
14
17
|
attr_encrypted :email, :key => 'a secret key'
|
15
|
-
attr_encrypted :credentials, :key =>
|
18
|
+
attr_encrypted :credentials, :key => 'some private key', :marshal => true
|
16
19
|
|
17
20
|
def after_initialize(attrs = {})
|
18
|
-
self.salt ||= Digest::SHA1.hexdigest((Time.now.to_i * rand(5)).to_s)
|
19
21
|
self.credentials ||= { :username => 'example', :password => 'test' }
|
20
22
|
end
|
21
23
|
end
|
@@ -27,6 +29,7 @@ class SequelTest < Test::Unit::TestCase
|
|
27
29
|
end
|
28
30
|
|
29
31
|
def test_should_encrypt_email
|
32
|
+
require 'ruby-debug'
|
30
33
|
@human = Human.new :email => 'test@example.com'
|
31
34
|
assert @human.save
|
32
35
|
assert_not_nil @human.encrypted_email
|
@@ -35,6 +38,7 @@ class SequelTest < Test::Unit::TestCase
|
|
35
38
|
end
|
36
39
|
|
37
40
|
def test_should_marshal_and_encrypt_credentials
|
41
|
+
|
38
42
|
@human = Human.new
|
39
43
|
assert @human.save
|
40
44
|
assert_not_nil @human.encrypted_credentials
|
@@ -47,4 +51,4 @@ class SequelTest < Test::Unit::TestCase
|
|
47
51
|
assert Human.attr_encrypted_options[:encode]
|
48
52
|
end
|
49
53
|
|
50
|
-
end
|
54
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attr_encryptor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-01-07 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: encryptor2
|
16
|
-
requirement: &
|
16
|
+
requirement: &70193477683240 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 1.0.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70193477683240
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: activerecord
|
27
|
-
requirement: &
|
27
|
+
requirement: &70193477682720 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 2.0.0
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70193477682720
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: datamapper
|
38
|
-
requirement: &
|
38
|
+
requirement: &70193477682340 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70193477682340
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: mocha
|
49
|
-
requirement: &
|
49
|
+
requirement: &70193477702100 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70193477702100
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: sequel
|
60
|
-
requirement: &
|
60
|
+
requirement: &70193477701680 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70193477701680
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: dm-sqlite-adapter
|
71
|
-
requirement: &
|
71
|
+
requirement: &70193477701260 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70193477701260
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: sqlite3
|
82
|
-
requirement: &
|
82
|
+
requirement: &70193477700840 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,7 +87,7 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70193477700840
|
91
91
|
description: Generates attr_accessors that encrypt and decrypt attributes transparently
|
92
92
|
email: danpal@gmail.com
|
93
93
|
executables: []
|