attr_encrypted 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +5 -0
- data/README.md +32 -8
- data/attr_encrypted.gemspec +5 -2
- data/lib/attr_encrypted.rb +3 -3
- data/lib/attr_encrypted/adapters/active_record.rb +8 -2
- data/lib/attr_encrypted/version.rb +1 -1
- data/test/active_record_test.rb +57 -49
- metadata +11 -5
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7818979e143dc8810acdc45dfe6ae67273be455d
|
4
|
+
data.tar.gz: 734c97e4b7d4109b40f4f6bdf7c34aace6e3be3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d8458d63ccd20fbeb9ae4d79689e0a90d3007bd0a212c428c9b95b44d20f39c5e038215bac1e5c7af1138f2517faf7a96973167b213be289a6b5fc7c1b75918
|
7
|
+
data.tar.gz: 57201322d4c3dcbf30bf5c74f931b47bf6478626e925620497fc842d87c393aeb507d277c92f524ff233d515acafad1d367ecb3427250ace7d125a9e3ecb1ab8
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# attr_encrypted #
|
2
2
|
|
3
|
+
## 3.0.0 ##
|
4
|
+
* Changed: Updated gemspec to use Encryptor v3.0.0. (@saghaulor)
|
5
|
+
* Changed: Updated README with instructions related to moving from v2.0.0 to v3.0.0. (@saghaulor)
|
6
|
+
* Fixed: ActiveModel::Dirty methods in the ActiveRecord adapter. (@saghaulor)
|
7
|
+
|
3
8
|
## 2.0.0 ##
|
4
9
|
* Added: Now using Encryptor v2.0.0 (@saghaulor)
|
5
10
|
* Added: Options are copied to the instance. (@saghaulor)
|
data/README.md
CHANGED
@@ -11,7 +11,7 @@ It works with ANY class, however, you get a few extra features when you're using
|
|
11
11
|
Add attr_encrypted to your gemfile:
|
12
12
|
|
13
13
|
```ruby
|
14
|
-
gem attr_encrypted, "~>
|
14
|
+
gem "attr_encrypted", "~> 3.0.0"
|
15
15
|
```
|
16
16
|
|
17
17
|
Then install the gem:
|
@@ -37,22 +37,22 @@ If you're using a PORO, you have to do a little bit more work by extending the c
|
|
37
37
|
extend AttrEncrypted
|
38
38
|
attr_accessor :name
|
39
39
|
attr_encrypted :ssn, key: 'This is a key that is 256 bits!!'
|
40
|
-
|
40
|
+
|
41
41
|
def load
|
42
42
|
# loads the stored data
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def save
|
46
46
|
# saves the :name and :encrypted_ssn attributes somewhere (e.g. filesystem, database, etc)
|
47
47
|
end
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
user = User.new
|
51
51
|
user.ssn = '123-45-6789'
|
52
52
|
user.ssn # returns the unencrypted object ie. '123-45-6789'
|
53
53
|
user.encrypted_ssn # returns the encrypted version of :ssn
|
54
54
|
user.save
|
55
|
-
|
55
|
+
|
56
56
|
user = User.load
|
57
57
|
user.ssn # decrypts :encrypted_ssn and returns '123-45-6789'
|
58
58
|
```
|
@@ -242,7 +242,7 @@ Lets suppose you'd like to use this custom encryptor class:
|
|
242
242
|
def self.silly_encrypt(options)
|
243
243
|
(options[:value] + options[:secret_key]).reverse
|
244
244
|
end
|
245
|
-
|
245
|
+
|
246
246
|
def self.silly_decrypt(options)
|
247
247
|
options[:value].reverse.gsub(/#{options[:secret_key]}$/, '')
|
248
248
|
end
|
@@ -374,12 +374,12 @@ Backwards compatibility is supported by providing a special option that is passe
|
|
374
374
|
The `:insecure_mode` option will allow encryptor to ignore the new security requirements. It is strongly advised that if you use this older insecure behavior that you migrate to the newer more secure behavior.
|
375
375
|
|
376
376
|
|
377
|
-
## Upgrading from attr_encrypted v1.x to
|
377
|
+
## Upgrading from attr_encrypted v1.x to v3.x
|
378
378
|
|
379
379
|
Modify your gemfile to include the new version of attr_encrypted:
|
380
380
|
|
381
381
|
```ruby
|
382
|
-
gem attr_encrypted, "~>
|
382
|
+
gem attr_encrypted, "~> 3.0.0"
|
383
383
|
```
|
384
384
|
|
385
385
|
The update attr_encrypted:
|
@@ -390,6 +390,30 @@ The update attr_encrypted:
|
|
390
390
|
|
391
391
|
Then modify your models using attr\_encrypted to account for the changes in default options. Specifically, pass in the `:mode` and `:algorithm` options that you were using if you had not previously done so. If your key is insufficient length relative to the algorithm that you use, you should also pass in `insecure_mode: true`; this will prevent Encryptor from raising an exception regarding insufficient key length. Please see the Deprecations sections for more details including an example of how to specify your model with default options from attr_encrypted v1.x.
|
392
392
|
|
393
|
+
## Upgrading from attr_encrypted v2.x to v3.x
|
394
|
+
|
395
|
+
A bug was discovered in Encryptor v2.0.0 that inccorectly set the IV when using an AES-\*-GCM algorithm. Unfornately fixing this major security issue results in the inability to decrypt records encrypted using an AES-*-GCM algorithm from Encryptor v2.0.0. Please see [Upgrading to Encryptor v3.0.0](https://github.com/attr-encrypted/encryptor#upgrading-from-v200-to-v300) for more info.
|
396
|
+
|
397
|
+
It is strongly advised that you re-encrypt your data encrypted with Encryptor v2.0.0. However, you'll have to take special care to re-encrypt. To decrypt data encrypted with Encryptor v2.0.0 using an AES-\*-GCM algorithm you can use the `:v2_gcm_iv` option.
|
398
|
+
|
399
|
+
It is recommended that you implement a strategy to insure that you do not mix the encryption implementations of Encryptor. One way to do this is to re-encrypt everything while your application is offline.Another way is to add a column that keeps track of what implementation was used. The path that you choose will depend on your situtation. Below is an example of how you might go about re-encrypting your data.
|
400
|
+
|
401
|
+
```ruby
|
402
|
+
class User
|
403
|
+
attr_encrypted :ssn, key: :encryption_key, v2_gcm_iv: :is_decrypting?(:ssn)
|
404
|
+
|
405
|
+
def is_decrypting?(attribute)
|
406
|
+
encrypted_atributes[attribute][operation] == :decrypting
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
User.all.each do |user|
|
411
|
+
old_ssn = user.ssn
|
412
|
+
user.ssn= old_ssn
|
413
|
+
user.save
|
414
|
+
end
|
415
|
+
```
|
416
|
+
|
393
417
|
## Things to consider before using attr_encrypted
|
394
418
|
|
395
419
|
#### Searching, joining, etc
|
data/attr_encrypted.gemspec
CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
|
|
28
28
|
|
29
29
|
s.required_ruby_version = '>= 2.0.0'
|
30
30
|
|
31
|
-
s.add_dependency('encryptor', ['~>
|
31
|
+
s.add_dependency('encryptor', ['~> 3.0.0'])
|
32
32
|
# support for testing with specific active record version
|
33
33
|
activerecord_version = if ENV.key?('ACTIVERECORD')
|
34
34
|
"~> #{ENV['ACTIVERECORD']}"
|
@@ -55,6 +55,9 @@ Gem::Specification.new do |s|
|
|
55
55
|
s.cert_chain = ['certs/saghaulor.pem']
|
56
56
|
s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/
|
57
57
|
|
58
|
-
s.post_install_message = "\n\n\nWARNING: Several insecure default options and features
|
58
|
+
s.post_install_message = "\n\n\nWARNING: Several insecure default options and features were deprecated in attr_encrypted v2.0.0.\n
|
59
|
+
Additionally, there was a bug in Encryptor v2.0.0 that insecurely encrypted data when using an AES-*-GCM algorithm.\n
|
60
|
+
This bug was fixed but introduced breaking changes between v2.x and v3.x.\n
|
61
|
+
Please see the README for more information regarding upgrading to attr_encrypted v3.0.0.\n\n\n"
|
59
62
|
|
60
63
|
end
|
data/lib/attr_encrypted.rb
CHANGED
@@ -350,7 +350,7 @@ module AttrEncrypted
|
|
350
350
|
def evaluated_attr_encrypted_options_for(attribute)
|
351
351
|
evaluated_options = Hash.new
|
352
352
|
attribute_option_value = encrypted_attributes[attribute.to_sym][:attribute]
|
353
|
-
|
353
|
+
encrypted_attributes[attribute.to_sym].map do |option, value|
|
354
354
|
evaluated_options[option] = evaluate_attr_encrypted_option(value)
|
355
355
|
end
|
356
356
|
|
@@ -383,7 +383,7 @@ module AttrEncrypted
|
|
383
383
|
def load_iv_for_attribute(attribute, options)
|
384
384
|
encrypted_attribute_name = options[:attribute]
|
385
385
|
encode_iv = options[:encode_iv]
|
386
|
-
iv = send("#{encrypted_attribute_name}_iv")
|
386
|
+
iv = options[:iv] || send("#{encrypted_attribute_name}_iv")
|
387
387
|
if options[:operation] == :encrypting
|
388
388
|
begin
|
389
389
|
iv = generate_iv(options[:algorithm])
|
@@ -407,7 +407,7 @@ module AttrEncrypted
|
|
407
407
|
def load_salt_for_attribute(attribute, options)
|
408
408
|
encrypted_attribute_name = options[:attribute]
|
409
409
|
encode_salt = options[:encode_salt]
|
410
|
-
salt = send("#{encrypted_attribute_name}_salt")
|
410
|
+
salt = options[:salt] || send("#{encrypted_attribute_name}_salt")
|
411
411
|
if (salt == nil)
|
412
412
|
salt = SecureRandom.random_bytes
|
413
413
|
salt = prefix_and_encode_salt(salt, encode_salt) if encode_salt
|
@@ -53,11 +53,17 @@ if defined?(ActiveRecord::Base)
|
|
53
53
|
options.merge! encrypted_attributes[attr]
|
54
54
|
|
55
55
|
define_method("#{attr}_changed?") do
|
56
|
-
|
56
|
+
if send("#{options[:attribute]}_changed?")
|
57
|
+
send(attr) != send("#{attr}_was")
|
58
|
+
end
|
57
59
|
end
|
58
60
|
|
59
61
|
define_method("#{attr}_was") do
|
60
|
-
|
62
|
+
iv_and_salt = { iv: send("#{options[:attribute]}_iv_was"), salt: send("#{options[:attribute]}_salt_was"), operation: :decrypting }
|
63
|
+
encrypted_attributes[attr].merge!(iv_and_salt)
|
64
|
+
evaluated_options = evaluated_attr_encrypted_options_for(attr)
|
65
|
+
[:iv, :salt, :operation].each { |key| encrypted_attributes[attr].delete(key) }
|
66
|
+
self.class.decrypt(attr, send("#{options[:attribute]}_was"), evaluated_options)
|
61
67
|
end
|
62
68
|
|
63
69
|
alias_method "#{attr}_before_type_cast", attr
|
data/test/active_record_test.rb
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
require_relative 'test_helper'
|
2
2
|
|
3
|
-
ActiveRecord::Base.establish_connection
|
3
|
+
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
|
4
4
|
|
5
5
|
def create_tables
|
6
6
|
silence_stream(STDOUT) do
|
7
|
-
ActiveRecord::Schema.define(:
|
7
|
+
ActiveRecord::Schema.define(version: 1) do
|
8
8
|
create_table :people do |t|
|
9
9
|
t.string :encrypted_email
|
10
10
|
t.string :password
|
11
11
|
t.string :encrypted_credentials
|
12
12
|
t.binary :salt
|
13
|
+
t.binary :key_iv
|
13
14
|
t.string :encrypted_email_salt
|
14
15
|
t.string :encrypted_credentials_salt
|
15
16
|
t.string :encrypted_email_iv
|
@@ -23,10 +24,12 @@ def create_tables
|
|
23
24
|
create_table :users do |t|
|
24
25
|
t.string :login
|
25
26
|
t.string :encrypted_password
|
27
|
+
t.string :encrypted_password_iv
|
26
28
|
t.boolean :is_admin
|
27
29
|
end
|
28
30
|
create_table :prime_ministers do |t|
|
29
31
|
t.string :encrypted_name
|
32
|
+
t.string :encrypted_name_iv
|
30
33
|
end
|
31
34
|
create_table :addresses do |t|
|
32
35
|
t.binary :encrypted_street
|
@@ -55,16 +58,17 @@ end
|
|
55
58
|
|
56
59
|
class Person < ActiveRecord::Base
|
57
60
|
self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
|
58
|
-
attr_encrypted :email, :
|
59
|
-
attr_encrypted :credentials, :
|
61
|
+
attr_encrypted :email, key: SECRET_KEY
|
62
|
+
attr_encrypted :credentials, key: Proc.new { |user| Encryptor.encrypt(value: user.salt, key: SECRET_KEY, iv: user.key_iv) }, marshal: true
|
60
63
|
|
61
64
|
after_initialize :initialize_salt_and_credentials
|
62
65
|
|
63
66
|
protected
|
64
67
|
|
65
68
|
def initialize_salt_and_credentials
|
69
|
+
self.key_iv ||= SecureRandom.random_bytes(12)
|
66
70
|
self.salt ||= Digest::SHA256.hexdigest((Time.now.to_i * rand(1000)).to_s)[0..15]
|
67
|
-
self.credentials ||= { :
|
71
|
+
self.credentials ||= { username: 'example', password: 'test' }
|
68
72
|
end
|
69
73
|
end
|
70
74
|
|
@@ -73,34 +77,34 @@ class PersonWithValidation < Person
|
|
73
77
|
end
|
74
78
|
|
75
79
|
class PersonWithProcMode < Person
|
76
|
-
attr_encrypted :email, :
|
77
|
-
attr_encrypted :credentials, :
|
80
|
+
attr_encrypted :email, key: SECRET_KEY, mode: Proc.new { :per_attribute_iv_and_salt }
|
81
|
+
attr_encrypted :credentials, key: SECRET_KEY, mode: Proc.new { :single_iv_and_salt }, insecure_mode: true
|
78
82
|
end
|
79
83
|
|
80
84
|
class Account < ActiveRecord::Base
|
81
85
|
attr_accessor :key
|
82
|
-
attr_encrypted :password, :
|
86
|
+
attr_encrypted :password, key: Proc.new {|account| account.key}
|
83
87
|
end
|
84
88
|
|
85
89
|
class PersonWithSerialization < ActiveRecord::Base
|
86
90
|
self.table_name = 'people'
|
87
|
-
attr_encrypted :email, :
|
91
|
+
attr_encrypted :email, key: SECRET_KEY
|
88
92
|
serialize :password
|
89
93
|
end
|
90
94
|
|
91
95
|
class UserWithProtectedAttribute < ActiveRecord::Base
|
92
96
|
self.table_name = 'users'
|
93
|
-
attr_encrypted :password, :
|
97
|
+
attr_encrypted :password, key: SECRET_KEY
|
94
98
|
attr_protected :is_admin if ::ActiveRecord::VERSION::STRING < "4.0"
|
95
99
|
end
|
96
100
|
|
97
101
|
class PersonUsingAlias < ActiveRecord::Base
|
98
102
|
self.table_name = 'people'
|
99
|
-
attr_encryptor :email, :
|
103
|
+
attr_encryptor :email, key: SECRET_KEY
|
100
104
|
end
|
101
105
|
|
102
106
|
class PrimeMinister < ActiveRecord::Base
|
103
|
-
attr_encrypted :name, :
|
107
|
+
attr_encrypted :name, marshal: true, key: SECRET_KEY
|
104
108
|
end
|
105
109
|
|
106
110
|
class Address < ActiveRecord::Base
|
@@ -115,11 +119,11 @@ class ActiveRecordTest < Minitest::Test
|
|
115
119
|
def setup
|
116
120
|
ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
|
117
121
|
create_tables
|
118
|
-
Account.create!(:
|
122
|
+
Account.create!(key: SECRET_KEY, password: "password")
|
119
123
|
end
|
120
124
|
|
121
125
|
def test_should_encrypt_email
|
122
|
-
@person = Person.create
|
126
|
+
@person = Person.create(email: 'test@example.com')
|
123
127
|
refute_nil @person.encrypted_email
|
124
128
|
refute_equal @person.email, @person.encrypted_email
|
125
129
|
assert_equal @person.email, Person.first.email
|
@@ -143,93 +147,97 @@ class ActiveRecordTest < Minitest::Test
|
|
143
147
|
end
|
144
148
|
|
145
149
|
def test_should_encrypt_decrypt_with_iv
|
146
|
-
@person = Person.create
|
150
|
+
@person = Person.create(email: 'test@example.com')
|
147
151
|
@person2 = Person.find(@person.id)
|
148
152
|
refute_nil @person2.encrypted_email_iv
|
149
153
|
assert_equal 'test@example.com', @person2.email
|
150
154
|
end
|
151
155
|
|
152
156
|
def test_should_ensure_attributes_can_be_deserialized
|
153
|
-
@person = PersonWithSerialization.new
|
157
|
+
@person = PersonWithSerialization.new(email: 'test@example.com', password: %w(an array of strings))
|
154
158
|
@person.save
|
155
159
|
assert_equal @person.password, %w(an array of strings)
|
156
160
|
end
|
157
161
|
|
158
162
|
def test_should_create_an_account_regardless_of_arguments_order
|
159
|
-
Account.create!(:
|
160
|
-
Account.create!(:
|
163
|
+
Account.create!(key: SECRET_KEY, password: "password")
|
164
|
+
Account.create!(password: "password" , key: SECRET_KEY)
|
161
165
|
end
|
162
166
|
|
163
167
|
def test_should_set_attributes_regardless_of_arguments_order
|
164
168
|
# minitest does not implement `assert_nothing_raised` https://github.com/seattlerb/minitest/issues/112
|
165
|
-
Account.new.attributes = { :
|
169
|
+
Account.new.attributes = { password: "password", key: SECRET_KEY }
|
166
170
|
end
|
167
171
|
|
168
172
|
def test_should_preserve_hash_key_type
|
169
|
-
hash = { :
|
170
|
-
account = Account.create!(:
|
173
|
+
hash = { foo: 'bar' }
|
174
|
+
account = Account.create!(key: hash)
|
171
175
|
assert_equal account.key, hash
|
172
176
|
end
|
173
177
|
|
174
178
|
def test_should_create_changed_predicate
|
175
|
-
person = Person.create!(:
|
176
|
-
|
179
|
+
person = Person.create!(email: 'test@example.com')
|
180
|
+
refute person.email_changed?
|
181
|
+
person.email = 'test@example.com'
|
182
|
+
refute person.email_changed?
|
183
|
+
person.email = nil
|
184
|
+
assert person.email_changed?
|
177
185
|
person.email = 'test2@example.com'
|
178
186
|
assert person.email_changed?
|
179
187
|
end
|
180
188
|
|
181
189
|
def test_should_create_was_predicate
|
182
190
|
original_email = 'test@example.com'
|
183
|
-
person = Person.create!(:
|
184
|
-
|
191
|
+
person = Person.create!(email: original_email)
|
192
|
+
assert_equal original_email, person.email_was
|
185
193
|
person.email = 'test2@example.com'
|
186
|
-
assert_equal person.email_was
|
194
|
+
assert_equal original_email, person.email_was
|
187
195
|
end
|
188
196
|
|
189
197
|
if ::ActiveRecord::VERSION::STRING > "4.0"
|
190
198
|
def test_should_assign_attributes
|
191
|
-
@user = UserWithProtectedAttribute.new
|
192
|
-
@user.attributes = ActionController::Parameters.new(:
|
199
|
+
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
|
200
|
+
@user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
|
193
201
|
assert_equal 'modified', @user.login
|
194
202
|
end
|
195
203
|
|
196
204
|
def test_should_not_assign_protected_attributes
|
197
|
-
@user = UserWithProtectedAttribute.new
|
198
|
-
@user.attributes = ActionController::Parameters.new(:
|
205
|
+
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
|
206
|
+
@user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
|
199
207
|
assert !@user.is_admin?
|
200
208
|
end
|
201
209
|
|
202
210
|
def test_should_raise_exception_if_not_permitted
|
203
|
-
@user = UserWithProtectedAttribute.new
|
211
|
+
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
|
204
212
|
assert_raises ActiveModel::ForbiddenAttributesError do
|
205
|
-
@user.attributes = ActionController::Parameters.new(:
|
213
|
+
@user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true)
|
206
214
|
end
|
207
215
|
end
|
208
216
|
|
209
217
|
def test_should_raise_exception_on_init_if_not_permitted
|
210
218
|
assert_raises ActiveModel::ForbiddenAttributesError do
|
211
|
-
@user = UserWithProtectedAttribute.new ActionController::Parameters.new(:
|
219
|
+
@user = UserWithProtectedAttribute.new ActionController::Parameters.new(login: 'modified', is_admin: true)
|
212
220
|
end
|
213
221
|
end
|
214
222
|
else
|
215
223
|
def test_should_assign_attributes
|
216
|
-
@user = UserWithProtectedAttribute.new
|
217
|
-
@user.attributes = {:
|
224
|
+
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
|
225
|
+
@user.attributes = { login: 'modified', is_admin: true }
|
218
226
|
assert_equal 'modified', @user.login
|
219
227
|
end
|
220
228
|
|
221
229
|
def test_should_not_assign_protected_attributes
|
222
|
-
@user = UserWithProtectedAttribute.new
|
223
|
-
@user.attributes = {:
|
230
|
+
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
|
231
|
+
@user.attributes = { login: 'modified', is_admin: true }
|
224
232
|
assert !@user.is_admin?
|
225
233
|
end
|
226
234
|
|
227
235
|
def test_should_assign_protected_attributes
|
228
|
-
@user = UserWithProtectedAttribute.new
|
236
|
+
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
|
229
237
|
if ::ActiveRecord::VERSION::STRING > "3.1"
|
230
|
-
@user.send
|
238
|
+
@user.send(:assign_attributes, { login: 'modified', is_admin: true }, without_protection: true)
|
231
239
|
else
|
232
|
-
@user.send
|
240
|
+
@user.send(:attributes=, { login: 'modified', is_admin: true }, false)
|
233
241
|
end
|
234
242
|
assert @user.is_admin?
|
235
243
|
end
|
@@ -241,7 +249,7 @@ class ActiveRecordTest < Minitest::Test
|
|
241
249
|
end
|
242
250
|
|
243
251
|
def test_should_allow_proc_based_mode
|
244
|
-
@person = PersonWithProcMode.create
|
252
|
+
@person = PersonWithProcMode.create(email: 'test@example.com', credentials: 'password123')
|
245
253
|
|
246
254
|
# Email is :per_attribute_iv_and_salt
|
247
255
|
assert_equal @person.class.encrypted_attributes[:email][:mode].class, Proc
|
@@ -275,21 +283,21 @@ class ActiveRecordTest < Minitest::Test
|
|
275
283
|
|
276
284
|
# See https://github.com/attr-encrypted/attr_encrypted/issues/68
|
277
285
|
def test_should_invalidate_virtual_attributes_on_reload
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
pm.name
|
282
|
-
|
286
|
+
old_pm_name = 'Winston Churchill'
|
287
|
+
new_pm_name = 'Neville Chamberlain'
|
288
|
+
pm = PrimeMinister.create!(name: old_pm_name)
|
289
|
+
assert_equal old_pm_name, pm.name
|
290
|
+
pm.name = new_pm_name
|
291
|
+
assert_equal new_pm_name, pm.name
|
283
292
|
|
284
293
|
result = pm.reload
|
285
294
|
assert_equal pm, result
|
286
|
-
assert_equal
|
295
|
+
assert_equal old_pm_name, pm.name
|
287
296
|
end
|
288
297
|
|
289
298
|
def test_should_save_encrypted_data_as_binary
|
290
299
|
street = '123 Elm'
|
291
|
-
address = Address.
|
292
|
-
address.save!
|
300
|
+
address = Address.create!(street: street)
|
293
301
|
refute_equal address.encrypted_street, street
|
294
302
|
assert_equal Address.first.street, street
|
295
303
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attr_encrypted
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sean Huber
|
@@ -33,7 +33,7 @@ cert_chain:
|
|
33
33
|
ZjeLmnSDiwL6doiP5IiwALH/dcHU67ck3NGf6XyqNwQrrmtPY0mv1WVVL4Uh+vYE
|
34
34
|
kHoFzE2no0BfBg78Re8fY69P5yES5ncC
|
35
35
|
-----END CERTIFICATE-----
|
36
|
-
date: 2016-
|
36
|
+
date: 2016-03-29 00:00:00.000000000 Z
|
37
37
|
dependencies:
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
39
|
name: encryptor
|
@@ -41,14 +41,14 @@ dependencies:
|
|
41
41
|
requirements:
|
42
42
|
- - "~>"
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version:
|
44
|
+
version: 3.0.0
|
45
45
|
type: :runtime
|
46
46
|
prerelease: false
|
47
47
|
version_requirements: !ruby/object:Gem::Requirement
|
48
48
|
requirements:
|
49
49
|
- - "~>"
|
50
50
|
- !ruby/object:Gem::Version
|
51
|
-
version:
|
51
|
+
version: 3.0.0
|
52
52
|
- !ruby/object:Gem::Dependency
|
53
53
|
name: activerecord
|
54
54
|
requirement: !ruby/object:Gem::Requirement
|
@@ -246,7 +246,13 @@ post_install_message: |2+
|
|
246
246
|
|
247
247
|
|
248
248
|
|
249
|
-
WARNING: Several insecure default options and features
|
249
|
+
WARNING: Several insecure default options and features were deprecated in attr_encrypted v2.0.0.
|
250
|
+
|
251
|
+
Additionally, there was a bug in Encryptor v2.0.0 that insecurely encrypted data when using an AES-*-GCM algorithm.
|
252
|
+
|
253
|
+
This bug was fixed but introduced breaking changes between v2.x and v3.x.
|
254
|
+
|
255
|
+
Please see the README for more information regarding upgrading to attr_encrypted v3.0.0.
|
250
256
|
|
251
257
|
|
252
258
|
rdoc_options:
|
metadata.gz.sig
CHANGED
Binary file
|