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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3a0be3a350e84025ea0cb74994429572c39a46e6
4
- data.tar.gz: 9b0fe0406c35007117ed1c0cabca0157410dcc41
3
+ metadata.gz: 4f35a7b7559ac43fbc20bf110b06c48457195c35
4
+ data.tar.gz: a99c8beb7a082c64d21f123aeb5c342dffbb80c2
5
5
  SHA512:
6
- metadata.gz: 7a6cce9239ecf6143d2280c2a2f2e43b37b0a7c99341934984e80eaedc100b0d0d317b9b87be073d1bfd953e3fb997010f9eb16520d1880f2b3ea161c952829e
7
- data.tar.gz: a4aa866eb7607d56b5de2ef238163310ac6fd34e0b3595dd99b6e7a18734d7e4c9addd562fbbcc134d38fab255408fd68d7f0a5bc6f8525e241d68e8bcb35edd
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, "~> 2.0.0"
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 v2.x
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, "~> 2.0.0"
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
@@ -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', ['~> 2.0.0'])
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 have been deprecated in attr_encrypted v2.0.0. Please see the README for more details.\n\n\n"
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
- def reload_with_attr_encrypted(*args, &block)
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
- alias_method_chain :method_missing, :attr_encrypted
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
- def assign_attributes_with_attr_encrypted(*args)
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
- def attributes_with_attr_encrypted=(*args)
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
- send(attr) != decrypt(attr, send("#{options[:attribute]}_was"))
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
- decrypt(attr, send("#{options[:attribute]}_was")) if send("#{attr}_changed?")
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 = 2
4
+ MAJOR = 3
5
5
  MINOR = 0
6
- PATCH = 0
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
  #
@@ -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
- self.class.encrypted_attributes[attribute.to_sym].map do |option, value|
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
@@ -1,39 +1,40 @@
1
1
  require_relative 'test_helper'
2
2
 
3
- ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
3
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
4
4
 
5
5
  def create_tables
6
- silence_stream(STDOUT) do
7
- ActiveRecord::Schema.define(:version => 1) do
8
- create_table :people do |t|
9
- t.string :encrypted_email
10
- t.string :password
11
- t.string :encrypted_credentials
12
- t.binary :salt
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.boolean :is_admin
27
- end
28
- create_table :prime_ministers do |t|
29
- t.string :encrypted_name
30
- end
31
- create_table :addresses do |t|
32
- t.binary :encrypted_street
33
- t.binary :encrypted_street_iv
34
- t.binary :encrypted_zipcode
35
- t.string :mode
36
- end
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, :key => SECRET_KEY
59
- attr_encrypted :credentials, :key => Proc.new { |user| Encryptor.encrypt(:value => user.salt, :key => SECRET_KEY, iv: SecureRandom.random_bytes(12)) }, :marshal => true
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 ||= { :username => 'example', :password => 'test' }
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, :key => SECRET_KEY, :mode => Proc.new { :per_attribute_iv_and_salt }
77
- attr_encrypted :credentials, :key => SECRET_KEY, :mode => Proc.new { :single_iv_and_salt }, insecure_mode: true
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, :key => Proc.new {|account| account.key}
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, :key => SECRET_KEY
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, :key => SECRET_KEY
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, :key => SECRET_KEY
101
+ attr_encryptor :email, key: SECRET_KEY
100
102
  end
101
103
 
102
104
  class PrimeMinister < ActiveRecord::Base
103
- attr_encrypted :name, :marshal => true, :key => SECRET_KEY
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!(:key => SECRET_KEY, :password => "password")
120
+ Account.create!(key: SECRET_KEY, password: "password")
119
121
  end
120
122
 
121
123
  def test_should_encrypt_email
122
- @person = Person.create :email => 'test@example.com'
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 :email => 'test@example.com'
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 :email => 'test@example.com', :password => %w(an array of strings)
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!(:key => SECRET_KEY, :password => "password")
160
- Account.create!(:password => "password" , :key => SECRET_KEY)
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 = { :password => "password" , :key => SECRET_KEY }
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 = { :foo => 'bar' }
170
- account = Account.create!(:key => hash)
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!(:email => 'test@example.com')
176
- assert !person.email_changed?
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!(:email => original_email)
184
- assert !person.email_was
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, original_email
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 :login => 'login', :is_admin => false
192
- @user.attributes = ActionController::Parameters.new(:login => 'modified', :is_admin => true).permit(:login)
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 :login => 'login', :is_admin => false
198
- @user.attributes = ActionController::Parameters.new(:login => 'modified', :is_admin => true).permit(:login)
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 :login => 'login', :is_admin => false
215
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
204
216
  assert_raises ActiveModel::ForbiddenAttributesError do
205
- @user.attributes = ActionController::Parameters.new(:login => 'modified', :is_admin => true)
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(:login => 'modified', :is_admin => true)
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 :login => 'login', :is_admin => false
217
- @user.attributes = {:login => 'modified', :is_admin => true}
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 :login => 'login', :is_admin => false
223
- @user.attributes = {:login => 'modified', :is_admin => true}
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 :login => 'login', :is_admin => false
240
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
229
241
  if ::ActiveRecord::VERSION::STRING > "3.1"
230
- @user.send :assign_attributes, {:login => 'modified', :is_admin => true}, :without_protection => true
242
+ @user.send(:assign_attributes, { login: 'modified', is_admin: true }, without_protection: true)
231
243
  else
232
- @user.send :attributes=, {:login => 'modified', :is_admin => true}, false
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 :email => 'test@example.com', :credentials => 'password123'
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
- pm = PrimeMinister.new(:name => 'Winston Churchill')
279
- pm.save!
280
- assert_equal 'Winston Churchill', pm.name
281
- pm.name = 'Neville Chamberlain'
282
- assert_equal 'Neville Chamberlain', pm.name
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 'Winston Churchill', pm.name
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.new(street: street)
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
@@ -81,26 +81,24 @@ class CompatibilityTest < Minitest::Test
81
81
  private
82
82
 
83
83
  def create_tables
84
- silence_stream(STDOUT) do
85
- ActiveRecord::Schema.define(:version => 1) do
86
- create_table :nonmarshalling_pets do |t|
87
- t.string :name
88
- t.string :encrypted_nickname
89
- t.string :encrypted_nickname_iv
90
- t.string :encrypted_nickname_salt
91
- t.string :encrypted_birthdate
92
- t.string :encrypted_birthdate_iv
93
- t.string :encrypted_birthdate_salt
94
- end
95
- create_table :marshalling_pets do |t|
96
- t.string :name
97
- t.string :encrypted_nickname
98
- t.string :encrypted_nickname_iv
99
- t.string :encrypted_nickname_salt
100
- t.string :encrypted_birthdate
101
- t.string :encrypted_birthdate_iv
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
- silence_stream(STDOUT) do
8
- ActiveRecord::Schema.define(:version => 1) do
9
- create_table :legacy_people do |t|
10
- t.string :encrypted_email
11
- t.string :password
12
- t.string :encrypted_credentials
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
- silence_stream(STDOUT) do
77
- ActiveRecord::Schema.define(:version => 1) do
78
- create_table :legacy_nonmarshalling_pets do |t|
79
- t.string :name
80
- t.string :encrypted_nickname
81
- t.string :encrypted_birthdate
82
- t.string :salt
83
- end
84
- create_table :legacy_marshalling_pets do |t|
85
- t.string :name
86
- t.string :encrypted_nickname
87
- t.string :encrypted_birthdate
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: 2.0.0
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-02-23 00:00:00.000000000 Z
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: 2.0.0
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: 2.0.0
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 have been deprecated in attr_encrypted v2.0.0. Please see the README for more details.
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$ ��nK4��닊x��W���h�ꘑ���88��h�1a��FD.�X��$~b؛�
2
- 2/.J�ڐ\�H�;F]�� ���_����JkpQ
1
+ .��m�,~1R��$�ޯ�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���>r3GHnU��309�%=<J�
2
+ 3�ai`�yQN�7�CK n���〞�7��B@SgyY\�@&�ݴ��e�