attr_encrypted 2.0.0 → 3.0.2
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/.travis.yml +8 -1
- data/CHANGELOG.md +13 -0
- data/README.md +32 -8
- data/attr_encrypted.gemspec +5 -2
- data/checksum/attr_encrypted-3.0.0.gem.sha256 +1 -0
- data/checksum/attr_encrypted-3.0.0.gem.sha512 +1 -0
- data/checksum/attr_encrypted-3.0.1.gem.sha256 +1 -0
- data/checksum/attr_encrypted-3.0.1.gem.sha512 +1 -0
- data/lib/attr_encrypted/adapters/active_record.rb +18 -9
- data/lib/attr_encrypted/version.rb +2 -2
- data/lib/attr_encrypted.rb +3 -3
- data/test/active_record_test.rb +91 -79
- data/test/compatibility_test.rb +18 -20
- data/test/legacy_active_record_test.rb +6 -8
- data/test/legacy_compatibility_test.rb +12 -14
- data.tar.gz.sig +0 -0
- metadata +15 -5
- metadata.gz.sig +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f35a7b7559ac43fbc20bf110b06c48457195c35
|
4
|
+
data.tar.gz: a99c8beb7a082c64d21f123aeb5c342dffbb80c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25d196cdd13c8c8f0b677583e734cd85e5eea7cf148c33c9317d9bc966481dd549a5513d1f89ac598e53086a4913ba2873184830d57dbc5b740413464397e89e
|
7
|
+
data.tar.gz: 344729a1eb162560e4519b851e0a736f81dddaad4c652338b1af568549d7ba5036c1a7f935b01a7805a1da4972aeb054ffa7b3980e571213ca10a08b75227e8b
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.travis.yml
CHANGED
@@ -4,7 +4,7 @@ cache: bundler
|
|
4
4
|
rvm:
|
5
5
|
- 2.0
|
6
6
|
- 2.1
|
7
|
-
- 2.2
|
7
|
+
- 2.2.2
|
8
8
|
- 2.3.0
|
9
9
|
- rbx
|
10
10
|
env:
|
@@ -14,8 +14,15 @@ env:
|
|
14
14
|
- ACTIVERECORD=4.0.0
|
15
15
|
- ACTIVERECORD=4.1.0
|
16
16
|
- ACTIVERECORD=4.2.0
|
17
|
+
- ACTIVERECORD=5.0.0
|
17
18
|
matrix:
|
18
19
|
exclude:
|
20
|
+
- rvm: 2.0
|
21
|
+
env: ACTIVERECORD=5.0.0
|
22
|
+
- rvm: 2.1
|
23
|
+
env: ACTIVERECORD=5.0.0
|
24
|
+
- rvm: rbx
|
25
|
+
env: ACTIVERECORD=5.0.0
|
19
26
|
allow_failures:
|
20
27
|
- rvm: rbx
|
21
28
|
fast_finish: true
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# attr_encrypted #
|
2
2
|
|
3
|
+
## 3.0.2 ##
|
4
|
+
* Changed: Removed alias_method_chain for compatibility with Rails v5.x (@grosser)
|
5
|
+
* Changed: Updated Travis build matrix to include Rails 5. (@saghaulor) (@connorshea)
|
6
|
+
* Changed: Removed `.silence_stream` from tests as it has been removed from Rails 5. (@sblackstone)
|
7
|
+
|
8
|
+
## 3.0.1 ##
|
9
|
+
* Fixed: attr_was method no longer calls undefined methods. (@saghaulor)
|
10
|
+
|
11
|
+
## 3.0.0 ##
|
12
|
+
* Changed: Updated gemspec to use Encryptor v3.0.0. (@saghaulor)
|
13
|
+
* Changed: Updated README with instructions related to moving from v2.0.0 to v3.0.0. (@saghaulor)
|
14
|
+
* Fixed: ActiveModel::Dirty methods in the ActiveRecord adapter. (@saghaulor)
|
15
|
+
|
3
16
|
## 2.0.0 ##
|
4
17
|
* Added: Now using Encryptor v2.0.0 (@saghaulor)
|
5
18
|
* 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_attributes[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
|
@@ -0,0 +1 @@
|
|
1
|
+
845fc3cb09a19c3ac76192aba443788f92c880744617bca99b16fd31ce843e07
|
@@ -0,0 +1 @@
|
|
1
|
+
81a065442258cc3702aab62c7b2307a48ed3e0deb803600d11a7480cce0db7c43fd9929acd2755081042f8989236553fd694b6cb62776bbfc53f9165a22cbca1
|
@@ -0,0 +1 @@
|
|
1
|
+
33140af4b223177db7a19efb2fa38472a299a745b29ca1c5ba9d3fa947390b77
|
@@ -0,0 +1 @@
|
|
1
|
+
0c467cab98b9b2eb331f9818323a90ae01392d6cb03cf1f32faccc954d0fc54be65f0fc7bf751b0fce57925eef1c9e2af90181bc40d81ad93e21d15a001c53c6
|
@@ -6,19 +6,20 @@ if defined?(ActiveRecord::Base)
|
|
6
6
|
base.class_eval do
|
7
7
|
|
8
8
|
# https://github.com/attr-encrypted/attr_encrypted/issues/68
|
9
|
-
|
9
|
+
alias_method :reload_without_attr_encrypted, :reload
|
10
|
+
def reload(*args, &block)
|
10
11
|
result = reload_without_attr_encrypted(*args, &block)
|
11
12
|
self.class.encrypted_attributes.keys.each do |attribute_name|
|
12
13
|
instance_variable_set("@#{attribute_name}", nil)
|
13
14
|
end
|
14
15
|
result
|
15
16
|
end
|
16
|
-
alias_method_chain :reload, :attr_encrypted
|
17
17
|
|
18
18
|
attr_encrypted_options[:encode] = true
|
19
19
|
|
20
20
|
class << self
|
21
|
-
|
21
|
+
alias_method :method_missing_without_attr_encrypted, :method_missing
|
22
|
+
alias_method :method_missing, :method_missing_with_attr_encrypted
|
22
23
|
end
|
23
24
|
|
24
25
|
def perform_attribute_assignment(method, new_attributes, *args)
|
@@ -30,16 +31,16 @@ if defined?(ActiveRecord::Base)
|
|
30
31
|
private :perform_attribute_assignment
|
31
32
|
|
32
33
|
if ::ActiveRecord::VERSION::STRING > "3.1"
|
33
|
-
|
34
|
+
alias_method :assign_attributes_without_attr_encrypted, :assign_attributes
|
35
|
+
def assign_attributes(*args)
|
34
36
|
perform_attribute_assignment :assign_attributes_without_attr_encrypted, *args
|
35
37
|
end
|
36
|
-
alias_method_chain :assign_attributes, :attr_encrypted
|
37
38
|
end
|
38
39
|
|
39
|
-
|
40
|
+
alias_method :attributes_without_attr_encrypted=, :attributes=
|
41
|
+
def attributes=(*args)
|
40
42
|
perform_attribute_assignment :attributes_without_attr_encrypted=, *args
|
41
43
|
end
|
42
|
-
alias_method_chain :attributes=, :attr_encrypted
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
@@ -53,11 +54,19 @@ if defined?(ActiveRecord::Base)
|
|
53
54
|
options.merge! encrypted_attributes[attr]
|
54
55
|
|
55
56
|
define_method("#{attr}_changed?") do
|
56
|
-
|
57
|
+
if send("#{options[:attribute]}_changed?")
|
58
|
+
send(attr) != send("#{attr}_was")
|
59
|
+
end
|
57
60
|
end
|
58
61
|
|
59
62
|
define_method("#{attr}_was") do
|
60
|
-
|
63
|
+
attr_was_options = { operation: :decrypting }
|
64
|
+
attr_was_options[:iv]= send("#{options[:attribute]}_iv_was") if respond_to?("#{options[:attribute]}_iv_was")
|
65
|
+
attr_was_options[:salt]= send("#{options[:attribute]}_salt_was") if respond_to?("#{options[:attribute]}_salt_was")
|
66
|
+
encrypted_attributes[attr].merge!(attr_was_options)
|
67
|
+
evaluated_options = evaluated_attr_encrypted_options_for(attr)
|
68
|
+
[:iv, :salt, :operation].each { |key| encrypted_attributes[attr].delete(key) }
|
69
|
+
self.class.decrypt(attr, send("#{options[:attribute]}_was"), evaluated_options)
|
61
70
|
end
|
62
71
|
|
63
72
|
alias_method "#{attr}_before_type_cast", attr
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module AttrEncrypted
|
2
2
|
# Contains information about this gem's version
|
3
3
|
module Version
|
4
|
-
MAJOR =
|
4
|
+
MAJOR = 3
|
5
5
|
MINOR = 0
|
6
|
-
PATCH =
|
6
|
+
PATCH = 2
|
7
7
|
|
8
8
|
# Returns a version string by joining <tt>MAJOR</tt>, <tt>MINOR</tt>, and <tt>PATCH</tt> with <tt>'.'</tt>
|
9
9
|
#
|
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
|
data/test/active_record_test.rb
CHANGED
@@ -1,39 +1,40 @@
|
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
6
|
+
ActiveRecord::Schema.define(version: 1) do
|
7
|
+
create_table :people do |t|
|
8
|
+
t.string :encrypted_email
|
9
|
+
t.string :password
|
10
|
+
t.string :encrypted_credentials
|
11
|
+
t.binary :salt
|
12
|
+
t.binary :key_iv
|
13
|
+
t.string :encrypted_email_salt
|
14
|
+
t.string :encrypted_credentials_salt
|
15
|
+
t.string :encrypted_email_iv
|
16
|
+
t.string :encrypted_credentials_iv
|
17
|
+
end
|
18
|
+
create_table :accounts do |t|
|
19
|
+
t.string :encrypted_password
|
20
|
+
t.string :encrypted_password_iv
|
21
|
+
t.string :encrypted_password_salt
|
22
|
+
end
|
23
|
+
create_table :users do |t|
|
24
|
+
t.string :login
|
25
|
+
t.string :encrypted_password
|
26
|
+
t.string :encrypted_password_iv
|
27
|
+
t.boolean :is_admin
|
28
|
+
end
|
29
|
+
create_table :prime_ministers do |t|
|
30
|
+
t.string :encrypted_name
|
31
|
+
t.string :encrypted_name_iv
|
32
|
+
end
|
33
|
+
create_table :addresses do |t|
|
34
|
+
t.binary :encrypted_street
|
35
|
+
t.binary :encrypted_street_iv
|
36
|
+
t.binary :encrypted_zipcode
|
37
|
+
t.string :mode
|
37
38
|
end
|
38
39
|
end
|
39
40
|
end
|
@@ -55,16 +56,17 @@ end
|
|
55
56
|
|
56
57
|
class Person < ActiveRecord::Base
|
57
58
|
self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
|
58
|
-
attr_encrypted :email, :
|
59
|
-
attr_encrypted :credentials, :
|
59
|
+
attr_encrypted :email, key: SECRET_KEY
|
60
|
+
attr_encrypted :credentials, key: Proc.new { |user| Encryptor.encrypt(value: user.salt, key: SECRET_KEY, iv: user.key_iv) }, marshal: true
|
60
61
|
|
61
62
|
after_initialize :initialize_salt_and_credentials
|
62
63
|
|
63
64
|
protected
|
64
65
|
|
65
66
|
def initialize_salt_and_credentials
|
67
|
+
self.key_iv ||= SecureRandom.random_bytes(12)
|
66
68
|
self.salt ||= Digest::SHA256.hexdigest((Time.now.to_i * rand(1000)).to_s)[0..15]
|
67
|
-
self.credentials ||= { :
|
69
|
+
self.credentials ||= { username: 'example', password: 'test' }
|
68
70
|
end
|
69
71
|
end
|
70
72
|
|
@@ -73,34 +75,34 @@ class PersonWithValidation < Person
|
|
73
75
|
end
|
74
76
|
|
75
77
|
class PersonWithProcMode < Person
|
76
|
-
attr_encrypted :email, :
|
77
|
-
attr_encrypted :credentials, :
|
78
|
+
attr_encrypted :email, key: SECRET_KEY, mode: Proc.new { :per_attribute_iv_and_salt }
|
79
|
+
attr_encrypted :credentials, key: SECRET_KEY, mode: Proc.new { :single_iv_and_salt }, insecure_mode: true
|
78
80
|
end
|
79
81
|
|
80
82
|
class Account < ActiveRecord::Base
|
81
83
|
attr_accessor :key
|
82
|
-
attr_encrypted :password, :
|
84
|
+
attr_encrypted :password, key: Proc.new {|account| account.key}
|
83
85
|
end
|
84
86
|
|
85
87
|
class PersonWithSerialization < ActiveRecord::Base
|
86
88
|
self.table_name = 'people'
|
87
|
-
attr_encrypted :email, :
|
89
|
+
attr_encrypted :email, key: SECRET_KEY
|
88
90
|
serialize :password
|
89
91
|
end
|
90
92
|
|
91
93
|
class UserWithProtectedAttribute < ActiveRecord::Base
|
92
94
|
self.table_name = 'users'
|
93
|
-
attr_encrypted :password, :
|
95
|
+
attr_encrypted :password, key: SECRET_KEY
|
94
96
|
attr_protected :is_admin if ::ActiveRecord::VERSION::STRING < "4.0"
|
95
97
|
end
|
96
98
|
|
97
99
|
class PersonUsingAlias < ActiveRecord::Base
|
98
100
|
self.table_name = 'people'
|
99
|
-
attr_encryptor :email, :
|
101
|
+
attr_encryptor :email, key: SECRET_KEY
|
100
102
|
end
|
101
103
|
|
102
104
|
class PrimeMinister < ActiveRecord::Base
|
103
|
-
attr_encrypted :name, :
|
105
|
+
attr_encrypted :name, marshal: true, key: SECRET_KEY
|
104
106
|
end
|
105
107
|
|
106
108
|
class Address < ActiveRecord::Base
|
@@ -115,11 +117,11 @@ class ActiveRecordTest < Minitest::Test
|
|
115
117
|
def setup
|
116
118
|
ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
|
117
119
|
create_tables
|
118
|
-
Account.create!(:
|
120
|
+
Account.create!(key: SECRET_KEY, password: "password")
|
119
121
|
end
|
120
122
|
|
121
123
|
def test_should_encrypt_email
|
122
|
-
@person = Person.create
|
124
|
+
@person = Person.create(email: 'test@example.com')
|
123
125
|
refute_nil @person.encrypted_email
|
124
126
|
refute_equal @person.email, @person.encrypted_email
|
125
127
|
assert_equal @person.email, Person.first.email
|
@@ -143,93 +145,103 @@ class ActiveRecordTest < Minitest::Test
|
|
143
145
|
end
|
144
146
|
|
145
147
|
def test_should_encrypt_decrypt_with_iv
|
146
|
-
@person = Person.create
|
148
|
+
@person = Person.create(email: 'test@example.com')
|
147
149
|
@person2 = Person.find(@person.id)
|
148
150
|
refute_nil @person2.encrypted_email_iv
|
149
151
|
assert_equal 'test@example.com', @person2.email
|
150
152
|
end
|
151
153
|
|
152
154
|
def test_should_ensure_attributes_can_be_deserialized
|
153
|
-
@person = PersonWithSerialization.new
|
155
|
+
@person = PersonWithSerialization.new(email: 'test@example.com', password: %w(an array of strings))
|
154
156
|
@person.save
|
155
157
|
assert_equal @person.password, %w(an array of strings)
|
156
158
|
end
|
157
159
|
|
158
160
|
def test_should_create_an_account_regardless_of_arguments_order
|
159
|
-
Account.create!(:
|
160
|
-
Account.create!(:
|
161
|
+
Account.create!(key: SECRET_KEY, password: "password")
|
162
|
+
Account.create!(password: "password" , key: SECRET_KEY)
|
161
163
|
end
|
162
164
|
|
163
165
|
def test_should_set_attributes_regardless_of_arguments_order
|
164
166
|
# minitest does not implement `assert_nothing_raised` https://github.com/seattlerb/minitest/issues/112
|
165
|
-
Account.new.attributes = { :
|
167
|
+
Account.new.attributes = { password: "password", key: SECRET_KEY }
|
166
168
|
end
|
167
169
|
|
168
170
|
def test_should_preserve_hash_key_type
|
169
|
-
hash = { :
|
170
|
-
account = Account.create!(:
|
171
|
+
hash = { foo: 'bar' }
|
172
|
+
account = Account.create!(key: hash)
|
171
173
|
assert_equal account.key, hash
|
172
174
|
end
|
173
175
|
|
174
176
|
def test_should_create_changed_predicate
|
175
|
-
person = Person.create!(:
|
176
|
-
|
177
|
+
person = Person.create!(email: 'test@example.com')
|
178
|
+
refute person.email_changed?
|
179
|
+
person.email = 'test@example.com'
|
180
|
+
refute person.email_changed?
|
181
|
+
person.email = nil
|
182
|
+
assert person.email_changed?
|
177
183
|
person.email = 'test2@example.com'
|
178
184
|
assert person.email_changed?
|
179
185
|
end
|
180
186
|
|
181
187
|
def test_should_create_was_predicate
|
182
188
|
original_email = 'test@example.com'
|
183
|
-
person = Person.create!(:
|
184
|
-
|
189
|
+
person = Person.create!(email: original_email)
|
190
|
+
assert_equal original_email, person.email_was
|
185
191
|
person.email = 'test2@example.com'
|
186
|
-
assert_equal person.email_was
|
192
|
+
assert_equal original_email, person.email_was
|
193
|
+
old_pm_name = "Winston Churchill"
|
194
|
+
pm = PrimeMinister.create!(name: old_pm_name)
|
195
|
+
assert_equal old_pm_name, pm.name_was
|
196
|
+
old_zipcode = "90210"
|
197
|
+
address = Address.create!(zipcode: old_zipcode, mode: "single_iv_and_salt")
|
198
|
+
assert_equal old_zipcode, address.zipcode_was
|
187
199
|
end
|
188
200
|
|
189
201
|
if ::ActiveRecord::VERSION::STRING > "4.0"
|
190
202
|
def test_should_assign_attributes
|
191
|
-
@user = UserWithProtectedAttribute.new
|
192
|
-
@user.attributes = ActionController::Parameters.new(:
|
203
|
+
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
|
204
|
+
@user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
|
193
205
|
assert_equal 'modified', @user.login
|
194
206
|
end
|
195
207
|
|
196
208
|
def test_should_not_assign_protected_attributes
|
197
|
-
@user = UserWithProtectedAttribute.new
|
198
|
-
@user.attributes = ActionController::Parameters.new(:
|
209
|
+
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
|
210
|
+
@user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
|
199
211
|
assert !@user.is_admin?
|
200
212
|
end
|
201
213
|
|
202
214
|
def test_should_raise_exception_if_not_permitted
|
203
|
-
@user = UserWithProtectedAttribute.new
|
215
|
+
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
|
204
216
|
assert_raises ActiveModel::ForbiddenAttributesError do
|
205
|
-
@user.attributes = ActionController::Parameters.new(:
|
217
|
+
@user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true)
|
206
218
|
end
|
207
219
|
end
|
208
220
|
|
209
221
|
def test_should_raise_exception_on_init_if_not_permitted
|
210
222
|
assert_raises ActiveModel::ForbiddenAttributesError do
|
211
|
-
@user = UserWithProtectedAttribute.new ActionController::Parameters.new(:
|
223
|
+
@user = UserWithProtectedAttribute.new ActionController::Parameters.new(login: 'modified', is_admin: true)
|
212
224
|
end
|
213
225
|
end
|
214
226
|
else
|
215
227
|
def test_should_assign_attributes
|
216
|
-
@user = UserWithProtectedAttribute.new
|
217
|
-
@user.attributes = {:
|
228
|
+
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
|
229
|
+
@user.attributes = { login: 'modified', is_admin: true }
|
218
230
|
assert_equal 'modified', @user.login
|
219
231
|
end
|
220
232
|
|
221
233
|
def test_should_not_assign_protected_attributes
|
222
|
-
@user = UserWithProtectedAttribute.new
|
223
|
-
@user.attributes = {:
|
234
|
+
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
|
235
|
+
@user.attributes = { login: 'modified', is_admin: true }
|
224
236
|
assert !@user.is_admin?
|
225
237
|
end
|
226
238
|
|
227
239
|
def test_should_assign_protected_attributes
|
228
|
-
@user = UserWithProtectedAttribute.new
|
240
|
+
@user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
|
229
241
|
if ::ActiveRecord::VERSION::STRING > "3.1"
|
230
|
-
@user.send
|
242
|
+
@user.send(:assign_attributes, { login: 'modified', is_admin: true }, without_protection: true)
|
231
243
|
else
|
232
|
-
@user.send
|
244
|
+
@user.send(:attributes=, { login: 'modified', is_admin: true }, false)
|
233
245
|
end
|
234
246
|
assert @user.is_admin?
|
235
247
|
end
|
@@ -241,7 +253,7 @@ class ActiveRecordTest < Minitest::Test
|
|
241
253
|
end
|
242
254
|
|
243
255
|
def test_should_allow_proc_based_mode
|
244
|
-
@person = PersonWithProcMode.create
|
256
|
+
@person = PersonWithProcMode.create(email: 'test@example.com', credentials: 'password123')
|
245
257
|
|
246
258
|
# Email is :per_attribute_iv_and_salt
|
247
259
|
assert_equal @person.class.encrypted_attributes[:email][:mode].class, Proc
|
@@ -275,21 +287,21 @@ class ActiveRecordTest < Minitest::Test
|
|
275
287
|
|
276
288
|
# See https://github.com/attr-encrypted/attr_encrypted/issues/68
|
277
289
|
def test_should_invalidate_virtual_attributes_on_reload
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
pm.name
|
282
|
-
|
290
|
+
old_pm_name = 'Winston Churchill'
|
291
|
+
new_pm_name = 'Neville Chamberlain'
|
292
|
+
pm = PrimeMinister.create!(name: old_pm_name)
|
293
|
+
assert_equal old_pm_name, pm.name
|
294
|
+
pm.name = new_pm_name
|
295
|
+
assert_equal new_pm_name, pm.name
|
283
296
|
|
284
297
|
result = pm.reload
|
285
298
|
assert_equal pm, result
|
286
|
-
assert_equal
|
299
|
+
assert_equal old_pm_name, pm.name
|
287
300
|
end
|
288
301
|
|
289
302
|
def test_should_save_encrypted_data_as_binary
|
290
303
|
street = '123 Elm'
|
291
|
-
address = Address.
|
292
|
-
address.save!
|
304
|
+
address = Address.create!(street: street)
|
293
305
|
refute_equal address.encrypted_street, street
|
294
306
|
assert_equal Address.first.street, street
|
295
307
|
end
|
data/test/compatibility_test.rb
CHANGED
@@ -81,26 +81,24 @@ class CompatibilityTest < Minitest::Test
|
|
81
81
|
private
|
82
82
|
|
83
83
|
def create_tables
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
t.string :encrypted_birthdate_salt
|
103
|
-
end
|
84
|
+
ActiveRecord::Schema.define(:version => 1) do
|
85
|
+
create_table :nonmarshalling_pets do |t|
|
86
|
+
t.string :name
|
87
|
+
t.string :encrypted_nickname
|
88
|
+
t.string :encrypted_nickname_iv
|
89
|
+
t.string :encrypted_nickname_salt
|
90
|
+
t.string :encrypted_birthdate
|
91
|
+
t.string :encrypted_birthdate_iv
|
92
|
+
t.string :encrypted_birthdate_salt
|
93
|
+
end
|
94
|
+
create_table :marshalling_pets do |t|
|
95
|
+
t.string :name
|
96
|
+
t.string :encrypted_nickname
|
97
|
+
t.string :encrypted_nickname_iv
|
98
|
+
t.string :encrypted_nickname_salt
|
99
|
+
t.string :encrypted_birthdate
|
100
|
+
t.string :encrypted_birthdate_iv
|
101
|
+
t.string :encrypted_birthdate_salt
|
104
102
|
end
|
105
103
|
end
|
106
104
|
end
|
@@ -4,14 +4,12 @@ require_relative 'test_helper'
|
|
4
4
|
ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
|
5
5
|
|
6
6
|
def create_people_table
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
t.string :salt
|
14
|
-
end
|
7
|
+
ActiveRecord::Schema.define(:version => 1) do
|
8
|
+
create_table :legacy_people do |t|
|
9
|
+
t.string :encrypted_email
|
10
|
+
t.string :password
|
11
|
+
t.string :encrypted_credentials
|
12
|
+
t.string :salt
|
15
13
|
end
|
16
14
|
end
|
17
15
|
end
|
@@ -73,20 +73,18 @@ class LegacyCompatibilityTest < Minitest::Test
|
|
73
73
|
private
|
74
74
|
|
75
75
|
def create_tables
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
t.string :salt
|
89
|
-
end
|
76
|
+
ActiveRecord::Schema.define(:version => 1) do
|
77
|
+
create_table :legacy_nonmarshalling_pets do |t|
|
78
|
+
t.string :name
|
79
|
+
t.string :encrypted_nickname
|
80
|
+
t.string :encrypted_birthdate
|
81
|
+
t.string :salt
|
82
|
+
end
|
83
|
+
create_table :legacy_marshalling_pets do |t|
|
84
|
+
t.string :name
|
85
|
+
t.string :encrypted_nickname
|
86
|
+
t.string :encrypted_birthdate
|
87
|
+
t.string :salt
|
90
88
|
end
|
91
89
|
end
|
92
90
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
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.2
|
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-07-15 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
|
@@ -222,6 +222,10 @@ files:
|
|
222
222
|
- Rakefile
|
223
223
|
- attr_encrypted.gemspec
|
224
224
|
- certs/saghaulor.pem
|
225
|
+
- checksum/attr_encrypted-3.0.0.gem.sha256
|
226
|
+
- checksum/attr_encrypted-3.0.0.gem.sha512
|
227
|
+
- checksum/attr_encrypted-3.0.1.gem.sha256
|
228
|
+
- checksum/attr_encrypted-3.0.1.gem.sha512
|
225
229
|
- lib/attr_encrypted.rb
|
226
230
|
- lib/attr_encrypted/adapters/active_record.rb
|
227
231
|
- lib/attr_encrypted/adapters/data_mapper.rb
|
@@ -246,7 +250,13 @@ post_install_message: |2+
|
|
246
250
|
|
247
251
|
|
248
252
|
|
249
|
-
WARNING: Several insecure default options and features
|
253
|
+
WARNING: Several insecure default options and features were deprecated in attr_encrypted v2.0.0.
|
254
|
+
|
255
|
+
Additionally, there was a bug in Encryptor v2.0.0 that insecurely encrypted data when using an AES-*-GCM algorithm.
|
256
|
+
|
257
|
+
This bug was fixed but introduced breaking changes between v2.x and v3.x.
|
258
|
+
|
259
|
+
Please see the README for more information regarding upgrading to attr_encrypted v3.0.0.
|
250
260
|
|
251
261
|
|
252
262
|
rdoc_options:
|
metadata.gz.sig
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
�7
|
2
|
-
|
1
|
+
.��m�,~1�R��$�ޯ�z��,�\y���.�ή9��\˵XK_M�*)ÄLv��(�~%��s?�2!�:�v�%��f���ƌ!���#ѻ`�{Op���;�ɇq�f��e�7��Q�9H��ySs���W���k/e��[a��V���h/�6dz���>r3�GHnU��309�%=<J�
|
2
|
+
3�ai`�yQN�7�CKn���〞�7��B@Sg�yY\�@&�ݴ��e�
|