attr_encrypted 1.4.0 → 3.0.3

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.
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
- require File.expand_path('../test_helper', __FILE__)
2
+ require_relative 'test_helper'
3
3
 
4
4
  class SillyEncryptor
5
5
  def self.silly_encrypt(options)
@@ -12,6 +12,7 @@ class SillyEncryptor
12
12
  end
13
13
 
14
14
  class User
15
+ extend AttrEncrypted
15
16
  self.attr_encrypted_options[:key] = Proc.new { |user| SECRET_KEY } # default key
16
17
  self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
17
18
 
@@ -33,7 +34,8 @@ class User
33
34
  attr_accessor :salt
34
35
  attr_accessor :should_encrypt
35
36
 
36
- def initialize
37
+ def initialize(email: nil)
38
+ self.email = email
37
39
  self.salt = Time.now.to_i.to_s
38
40
  self.should_encrypt = true
39
41
  end
@@ -48,19 +50,40 @@ class Admin < User
48
50
  end
49
51
 
50
52
  class SomeOtherClass
53
+ extend AttrEncrypted
51
54
  def self.call(object)
52
55
  object.class
53
56
  end
54
57
  end
55
58
 
59
+ class YetAnotherClass
60
+ extend AttrEncrypted
61
+ self.attr_encrypted_options[:encode_iv] = false
62
+
63
+ attr_encrypted :email, :key => SECRET_KEY
64
+ attr_encrypted :phone_number, :key => SECRET_KEY, mode: Proc.new { |thing| thing.mode }, encode_iv: Proc.new { |thing| thing.encode_iv }, encode_salt: Proc.new { |thing| thing.encode_salt }
65
+
66
+ def initialize(email: nil, encode_iv: 'm', encode_salt: 'm', mode: :per_attribute_iv_and_salt)
67
+ self.email = email
68
+ @encode_iv = encode_iv
69
+ @encode_salt = encode_salt
70
+ @mode = mode
71
+ end
72
+
73
+ attr_reader :encode_iv, :encode_salt, :mode
74
+ end
75
+
56
76
  class AttrEncryptedTest < Minitest::Test
77
+ def setup
78
+ @iv = SecureRandom.random_bytes(12)
79
+ end
57
80
 
58
81
  def test_should_store_email_in_encrypted_attributes
59
82
  assert User.encrypted_attributes.include?(:email)
60
83
  end
61
84
 
62
85
  def test_should_not_store_salt_in_encrypted_attributes
63
- assert !User.encrypted_attributes.include?(:salt)
86
+ refute User.encrypted_attributes.include?(:salt)
64
87
  end
65
88
 
66
89
  def test_attr_encrypted_should_return_true_for_email
@@ -88,16 +111,16 @@ class AttrEncryptedTest < Minitest::Test
88
111
  end
89
112
 
90
113
  def test_should_not_encrypt_nil_value
91
- assert_nil User.encrypt_email(nil)
114
+ assert_nil User.encrypt_email(nil, iv: @iv)
92
115
  end
93
116
 
94
117
  def test_should_not_encrypt_empty_string
95
- assert_equal '', User.encrypt_email('')
118
+ assert_equal '', User.encrypt_email('', iv: @iv)
96
119
  end
97
120
 
98
121
  def test_should_encrypt_email
99
- refute_nil User.encrypt_email('test@example.com')
100
- refute_equal 'test@example.com', User.encrypt_email('test@example.com')
122
+ refute_nil User.encrypt_email('test@example.com', iv: @iv)
123
+ refute_equal 'test@example.com', User.encrypt_email('test@example.com', iv: @iv)
101
124
  end
102
125
 
103
126
  def test_should_encrypt_email_when_modifying_the_attr_writer
@@ -105,48 +128,52 @@ class AttrEncryptedTest < Minitest::Test
105
128
  assert_nil @user.encrypted_email
106
129
  @user.email = 'test@example.com'
107
130
  refute_nil @user.encrypted_email
108
- assert_equal User.encrypt_email('test@example.com'), @user.encrypted_email
131
+ iv = @user.encrypted_email_iv.unpack('m').first
132
+ salt = @user.encrypted_email_salt[1..-1].unpack('m').first
133
+ assert_equal User.encrypt_email('test@example.com', iv: iv, salt: salt), @user.encrypted_email
109
134
  end
110
135
 
111
136
  def test_should_not_decrypt_nil_value
112
- assert_nil User.decrypt_email(nil)
137
+ assert_nil User.decrypt_email(nil, iv: @iv)
113
138
  end
114
139
 
115
140
  def test_should_not_decrypt_empty_string
116
- assert_equal '', User.decrypt_email('')
141
+ assert_equal '', User.decrypt_email('', iv: @iv)
117
142
  end
118
143
 
119
144
  def test_should_decrypt_email
120
- encrypted_email = User.encrypt_email('test@example.com')
145
+ encrypted_email = User.encrypt_email('test@example.com', iv: @iv)
121
146
  refute_equal 'test@test.com', encrypted_email
122
- assert_equal 'test@example.com', User.decrypt_email(encrypted_email)
147
+ assert_equal 'test@example.com', User.decrypt_email(encrypted_email, iv: @iv)
123
148
  end
124
149
 
125
150
  def test_should_decrypt_email_when_reading
126
151
  @user = User.new
127
152
  assert_nil @user.email
128
- @user.encrypted_email = User.encrypt_email('test@example.com')
153
+ iv = @user.encrypted_email_iv.unpack('m').first
154
+ salt = @user.encrypted_email_salt[1..-1].unpack('m').first
155
+ @user.encrypted_email = User.encrypt_email('test@example.com', iv: iv, salt: salt)
129
156
  assert_equal 'test@example.com', @user.email
130
157
  end
131
158
 
132
159
  def test_should_encrypt_with_encoding
133
- assert_equal User.encrypt_with_encoding('test'), [User.encrypt_without_encoding('test')].pack('m')
160
+ assert_equal User.encrypt_with_encoding('test', iv: @iv), [User.encrypt_without_encoding('test', iv: @iv)].pack('m')
134
161
  end
135
162
 
136
163
  def test_should_decrypt_with_encoding
137
- encrypted = User.encrypt_with_encoding('test')
138
- assert_equal 'test', User.decrypt_with_encoding(encrypted)
139
- assert_equal User.decrypt_with_encoding(encrypted), User.decrypt_without_encoding(encrypted.unpack('m').first)
164
+ encrypted = User.encrypt_with_encoding('test', iv: @iv)
165
+ assert_equal 'test', User.decrypt_with_encoding(encrypted, iv: @iv)
166
+ assert_equal User.decrypt_with_encoding(encrypted, iv: @iv), User.decrypt_without_encoding(encrypted.unpack('m').first, iv: @iv)
140
167
  end
141
168
 
142
169
  def test_should_encrypt_with_custom_encoding
143
- assert_equal User.encrypt_with_encoding('test'), [User.encrypt_without_encoding('test')].pack('m')
170
+ assert_equal User.encrypt_with_encoding('test', iv: @iv), [User.encrypt_without_encoding('test', iv: @iv)].pack('m')
144
171
  end
145
172
 
146
173
  def test_should_decrypt_with_custom_encoding
147
- encrypted = User.encrypt_with_encoding('test')
148
- assert_equal 'test', User.decrypt_with_encoding(encrypted)
149
- assert_equal User.decrypt_with_encoding(encrypted), User.decrypt_without_encoding(encrypted.unpack('m').first)
174
+ encrypted = User.encrypt_with_encoding('test', iv: @iv)
175
+ assert_equal 'test', User.decrypt_with_encoding(encrypted, iv: @iv)
176
+ assert_equal User.decrypt_with_encoding(encrypted, iv: @iv), User.decrypt_without_encoding(encrypted.unpack('m').first, iv: @iv)
150
177
  end
151
178
 
152
179
  def test_should_encrypt_with_marshaling
@@ -164,7 +191,7 @@ class AttrEncryptedTest < Minitest::Test
164
191
  assert_nil @user.ssn_encrypted
165
192
  @user.ssn = 'testing'
166
193
  refute_nil @user.ssn_encrypted
167
- encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.ssn_encrypted_iv.unpack("m").first, :salt => @user.ssn_encrypted_salt )
194
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.ssn_encrypted_iv.unpack("m").first, :salt => @user.ssn_encrypted_salt.unpack("m").first )
168
195
  assert_equal encrypted, @user.ssn_encrypted
169
196
  end
170
197
 
@@ -173,7 +200,7 @@ class AttrEncryptedTest < Minitest::Test
173
200
  assert_nil @user.crypted_password_test
174
201
  @user.password = 'testing'
175
202
  refute_nil @user.crypted_password_test
176
- encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => @user.crypted_password_test_salt)
203
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => @user.crypted_password_test_salt.unpack("m").first)
177
204
  assert_equal encrypted, @user.crypted_password_test
178
205
  end
179
206
 
@@ -182,7 +209,7 @@ class AttrEncryptedTest < Minitest::Test
182
209
  assert_nil @user.crypted_password_test
183
210
  @user.password = 'testing'
184
211
  refute_nil @user.crypted_password_test
185
- encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => @user.crypted_password_test_salt)
212
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => @user.crypted_password_test_salt.unpack("m").first)
186
213
  assert_equal encrypted, @user.crypted_password_test
187
214
  end
188
215
 
@@ -201,23 +228,24 @@ class AttrEncryptedTest < Minitest::Test
201
228
  end
202
229
 
203
230
  def test_should_evaluate_a_symbol_option
204
- assert_equal Object, Object.new.send(:evaluate_attr_encrypted_option, :class)
231
+ assert_equal SomeOtherClass, SomeOtherClass.new.send(:evaluate_attr_encrypted_option, :class)
205
232
  end
206
233
 
207
234
  def test_should_evaluate_a_proc_option
208
- assert_equal Object, Object.new.send(:evaluate_attr_encrypted_option, proc { |object| object.class })
235
+ assert_equal SomeOtherClass, SomeOtherClass.new.send(:evaluate_attr_encrypted_option, proc { |object| object.class })
209
236
  end
210
237
 
211
238
  def test_should_evaluate_a_lambda_option
212
- assert_equal Object, Object.new.send(:evaluate_attr_encrypted_option, lambda { |object| object.class })
239
+ assert_equal SomeOtherClass, SomeOtherClass.new.send(:evaluate_attr_encrypted_option, lambda { |object| object.class })
213
240
  end
214
241
 
215
242
  def test_should_evaluate_a_method_option
216
- assert_equal Object, Object.new.send(:evaluate_attr_encrypted_option, SomeOtherClass.method(:call))
243
+ assert_equal SomeOtherClass, SomeOtherClass.new.send(:evaluate_attr_encrypted_option, SomeOtherClass.method(:call))
217
244
  end
218
245
 
219
246
  def test_should_return_a_string_option
220
- assert_equal 'Object', Object.new.send(:evaluate_attr_encrypted_option, 'Object')
247
+ class_string = 'SomeOtherClass'
248
+ assert_equal class_string, SomeOtherClass.new.send(:evaluate_attr_encrypted_option, class_string)
221
249
  end
222
250
 
223
251
  def test_should_encrypt_with_true_if
@@ -225,7 +253,7 @@ class AttrEncryptedTest < Minitest::Test
225
253
  assert_nil @user.encrypted_with_true_if
226
254
  @user.with_true_if = 'testing'
227
255
  refute_nil @user.encrypted_with_true_if
228
- encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.encrypted_with_true_if_iv.unpack("m").first, :salt => @user.encrypted_with_true_if_salt)
256
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.encrypted_with_true_if_iv.unpack("m").first, :salt => @user.encrypted_with_true_if_salt.unpack("m").first)
229
257
  assert_equal encrypted, @user.encrypted_with_true_if
230
258
  end
231
259
 
@@ -242,7 +270,7 @@ class AttrEncryptedTest < Minitest::Test
242
270
  assert_nil @user.encrypted_with_false_unless
243
271
  @user.with_false_unless = 'testing'
244
272
  refute_nil @user.encrypted_with_false_unless
245
- encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.encrypted_with_false_unless_iv.unpack("m").first, :salt => @user.encrypted_with_false_unless_salt)
273
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.encrypted_with_false_unless_iv.unpack("m").first, :salt => @user.encrypted_with_false_unless_salt.unpack("m").first)
246
274
  assert_equal encrypted, @user.encrypted_with_false_unless
247
275
  end
248
276
 
@@ -261,11 +289,6 @@ class AttrEncryptedTest < Minitest::Test
261
289
  def test_should_always_reset_options
262
290
  @user = User.new
263
291
  @user.with_if_changed = "encrypt_stuff"
264
- @user.stubs(:instance_variable_get).returns(nil)
265
- @user.stubs(:instance_variable_set).raises("BadStuff")
266
- assert_raises RuntimeError do
267
- @user.with_if_changed
268
- end
269
292
 
270
293
  @user = User.new
271
294
  @user.should_encrypt = false
@@ -275,9 +298,9 @@ class AttrEncryptedTest < Minitest::Test
275
298
  end
276
299
 
277
300
  def test_should_cast_values_as_strings_before_encrypting
278
- string_encrypted_email = User.encrypt_email('3')
279
- assert_equal string_encrypted_email, User.encrypt_email(3)
280
- assert_equal '3', User.decrypt_email(string_encrypted_email)
301
+ string_encrypted_email = User.encrypt_email('3', iv: @iv)
302
+ assert_equal string_encrypted_email, User.encrypt_email(3, iv: @iv)
303
+ assert_equal '3', User.decrypt_email(string_encrypted_email, iv: @iv)
281
304
  end
282
305
 
283
306
  def test_should_create_query_accessor
@@ -296,12 +319,18 @@ class AttrEncryptedTest < Minitest::Test
296
319
  refute_equal @user.encrypted_email_iv, @user.crypted_password_test_iv
297
320
  end
298
321
 
322
+ def test_should_generate_iv_per_attribute_by_default
323
+ thing = YetAnotherClass.new(email: 'thing@thing.com')
324
+ refute_nil thing.encrypted_email_iv
325
+ end
326
+
299
327
  def test_should_vary_iv_per_instance
300
328
  @user1 = User.new
301
329
  @user1.email = 'email@example.com'
302
330
  @user2 = User.new
303
331
  @user2.email = 'email@example.com'
304
332
  refute_equal @user1.encrypted_email_iv, @user2.encrypted_email_iv
333
+ refute_equal @user1.encrypted_email, @user2.encrypted_email
305
334
  end
306
335
 
307
336
  def test_should_vary_salt_per_attribute
@@ -319,6 +348,11 @@ class AttrEncryptedTest < Minitest::Test
319
348
  refute_equal @user1.encrypted_email_salt, @user2.encrypted_email_salt
320
349
  end
321
350
 
351
+ def test_should_not_generate_salt_per_attribute_by_default
352
+ thing = YetAnotherClass.new(email: 'thing@thing.com')
353
+ assert_nil thing.encrypted_email_salt
354
+ end
355
+
322
356
  def test_should_decrypt_second_record
323
357
  @user1 = User.new
324
358
  @user1.email = 'test@example.com'
@@ -328,4 +362,32 @@ class AttrEncryptedTest < Minitest::Test
328
362
 
329
363
  assert_equal 'test@example.com', @user1.decrypt(:email, @user1.encrypted_email)
330
364
  end
365
+
366
+ def test_should_specify_the_default_algorithm
367
+ assert YetAnotherClass.encrypted_attributes[:email][:algorithm]
368
+ assert_equal YetAnotherClass.encrypted_attributes[:email][:algorithm], 'aes-256-gcm'
369
+ end
370
+
371
+ def test_should_not_encode_iv_when_encode_iv_is_false
372
+ email = 'thing@thing.com'
373
+ thing = YetAnotherClass.new(email: email)
374
+ refute thing.encrypted_email_iv =~ base64_encoding_regex
375
+ assert_equal thing.email, email
376
+ end
377
+
378
+ def test_should_base64_encode_iv_by_default
379
+ phone_number = '555-555-5555'
380
+ thing = YetAnotherClass.new
381
+ thing.phone_number = phone_number
382
+ assert thing.encrypted_phone_number_iv =~ base64_encoding_regex
383
+ assert_equal thing.phone_number, phone_number
384
+ end
385
+
386
+ def test_should_generate_unique_iv_for_every_encrypt_operation
387
+ user = User.new
388
+ user.email = 'initial_value@test.com'
389
+ original_iv = user.encrypted_email_iv
390
+ user.email = 'revised_value@test.com'
391
+ refute_equal original_iv, user.encrypted_email_iv
392
+ end
331
393
  end
@@ -1,5 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../test_helper', __FILE__)
2
+ require_relative 'test_helper'
3
3
 
4
4
  # Test to ensure that existing representations in database do not break on
5
5
  # migrating to new versions of this gem. This ensures that future versions of
@@ -13,11 +13,13 @@ class CompatibilityTest < Minitest::Test
13
13
  PET_BIRTHDATE_KEY = 'my-really-really-secret-pet-birthdate-key'
14
14
 
15
15
  self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
16
+ self.attr_encrypted_options[:algorithm] = 'aes-256-cbc'
17
+ self.attr_encrypted_options[:insecure_mode] = true
16
18
 
17
19
  attr_encrypted :nickname,
18
- :key => proc { Encryptor.encrypt(:value => PET_NICKNAME_SALT, :key => PET_NICKNAME_KEY) }
20
+ :key => proc { Encryptor.encrypt(:value => PET_NICKNAME_SALT, :key => PET_NICKNAME_KEY, insecure_mode: true, algorithm: 'aes-256-cbc') }
19
21
  attr_encrypted :birthdate,
20
- :key => proc { Encryptor.encrypt(:value => PET_BIRTHDATE_SALT, :key => PET_BIRTHDATE_KEY) }
22
+ :key => proc { Encryptor.encrypt(:value => PET_BIRTHDATE_SALT, :key => PET_BIRTHDATE_KEY, insecure_mode: true, algorithm: 'aes-256-cbc') }
21
23
  end
22
24
 
23
25
  class MarshallingPet < ActiveRecord::Base
@@ -27,12 +29,14 @@ class CompatibilityTest < Minitest::Test
27
29
  PET_BIRTHDATE_KEY = 'my-really-really-secret-pet-birthdate-key'
28
30
 
29
31
  self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
32
+ self.attr_encrypted_options[:algorithm] = 'aes-256-cbc'
33
+ self.attr_encrypted_options[:insecure_mode] = true
30
34
 
31
35
  attr_encrypted :nickname,
32
- :key => proc { Encryptor.encrypt(:value => PET_NICKNAME_SALT, :key => PET_NICKNAME_KEY) },
36
+ :key => proc { Encryptor.encrypt(:value => PET_NICKNAME_SALT, :key => PET_NICKNAME_KEY, insecure_mode: true, algorithm: 'aes-256-cbc') },
33
37
  :marshal => true
34
38
  attr_encrypted :birthdate,
35
- :key => proc { Encryptor.encrypt(:value => PET_BIRTHDATE_SALT, :key => PET_BIRTHDATE_KEY) },
39
+ :key => proc { Encryptor.encrypt(:value => PET_BIRTHDATE_SALT, :key => PET_BIRTHDATE_KEY, insecure_mode: true, algorithm: 'aes-256-cbc') },
36
40
  :marshal => true
37
41
  end
38
42
 
@@ -58,69 +62,46 @@ class CompatibilityTest < Minitest::Test
58
62
  end
59
63
 
60
64
  def test_marshalling_backwards_compatibility
61
- # Marshalling formats changed significantly from Ruby 1.8.7 to 1.9.3.
62
- # Also, Date class did not correctly support marshalling pre-1.9.3, so here
63
- # we just marshal it as a string in the Ruby 1.8.7 case.
64
- if RUBY_VERSION < '1.9.3'
65
- pet = MarshallingPet.create!(
66
- :name => 'Fido',
67
- :encrypted_nickname => 'NhpLBIp3aKRzNZrUgUfVuceYi4x+8lE3wUsVCSI9BcU=',
68
- :encrypted_nickname_iv => 'wpQqrj3KN16fN6PsAerUTA==',
69
- :encrypted_nickname_salt => '8f1a62d274ca8a3a',
70
- :encrypted_birthdate => '4nbCEzcj6CjLd3B9liKm9Q==',
71
- :encrypted_birthdate_iv => 'Vt10PQZMrbamh/gmjSLdkQ==',
72
- :encrypted_birthdate_salt => 'cfb245a3df76404f'
73
- )
74
- else
75
- pet = MarshallingPet.create!(
76
- :name => 'Fido',
77
- :encrypted_nickname => 'EsQScJYkPw80vVGvKWkE37Px99HHpXPFjoEPTNa4rbs=',
78
- :encrypted_nickname_iv => 'fNq1OZcGvty4KfcvGTcFSw==',
79
- :encrypted_nickname_salt => '733b459b7d34c217',
80
- :encrypted_birthdate => '+VUlKQGfNWkOgCwI4hv+3qlGIwh9h6cJ/ranJlaxvU+xxQdL3H3cOzTcI2rkYkdR',
81
- :encrypted_birthdate_iv => 'Ka+zF/SwEYZKwVa24lvFfA==',
82
- :encrypted_birthdate_salt => 'd5e892d5bbd81566'
83
- )
84
- end
65
+ pet = MarshallingPet.create!(
66
+ :name => 'Fido',
67
+ :encrypted_nickname => 'EsQScJYkPw80vVGvKWkE37Px99HHpXPFjoEPTNa4rbs=',
68
+ :encrypted_nickname_iv => 'fNq1OZcGvty4KfcvGTcFSw==',
69
+ :encrypted_nickname_salt => '733b459b7d34c217',
70
+ :encrypted_birthdate => '+VUlKQGfNWkOgCwI4hv+3qlGIwh9h6cJ/ranJlaxvU+xxQdL3H3cOzTcI2rkYkdR',
71
+ :encrypted_birthdate_iv => 'Ka+zF/SwEYZKwVa24lvFfA==',
72
+ :encrypted_birthdate_salt => 'd5e892d5bbd81566'
73
+ )
85
74
 
86
75
  assert_equal 'Fido', pet.name
87
76
  assert_equal 'Mummy\'s little helper', pet.nickname
88
77
 
89
- # See earlier comment.
90
- if RUBY_VERSION < '1.9.3'
91
- assert_equal '2011-07-09', pet.birthdate
92
- else
93
- assert_equal Date.new(2011, 7, 9), pet.birthdate
94
- end
78
+ assert_equal Date.new(2011, 7, 9), pet.birthdate
95
79
  end
96
80
 
97
81
  private
98
82
 
99
83
  def create_tables
100
- silence_stream(STDOUT) do
101
- ActiveRecord::Schema.define(:version => 1) do
102
- create_table :nonmarshalling_pets do |t|
103
- t.string :name
104
- t.string :encrypted_nickname
105
- t.string :encrypted_nickname_iv
106
- t.string :encrypted_nickname_salt
107
- t.string :encrypted_birthdate
108
- t.string :encrypted_birthdate_iv
109
- t.string :encrypted_birthdate_salt
110
- end
111
- create_table :marshalling_pets do |t|
112
- t.string :name
113
- t.string :encrypted_nickname
114
- t.string :encrypted_nickname_iv
115
- t.string :encrypted_nickname_salt
116
- t.string :encrypted_birthdate
117
- t.string :encrypted_birthdate_iv
118
- t.string :encrypted_birthdate_salt
119
- 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
120
102
  end
121
103
  end
122
104
  end
123
105
  end
124
106
 
125
107
  ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
126
-
@@ -1,4 +1,4 @@
1
- require File.expand_path('../test_helper', __FILE__)
1
+ require_relative 'test_helper'
2
2
 
3
3
  DataMapper.setup(:default, 'sqlite3::memory:')
4
4
 
@@ -1,17 +1,15 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../test_helper', __FILE__)
2
+ require_relative 'test_helper'
3
3
 
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
@@ -22,8 +20,12 @@ create_people_table
22
20
  ActiveRecord::MissingAttributeError = ActiveModel::MissingAttributeError unless defined?(ActiveRecord::MissingAttributeError)
23
21
 
24
22
  class LegacyPerson < ActiveRecord::Base
23
+ self.attr_encrypted_options[:insecure_mode] = true
24
+ self.attr_encrypted_options[:algorithm] = 'aes-256-cbc'
25
+ self.attr_encrypted_options[:mode] = :single_iv_and_salt
26
+
25
27
  attr_encrypted :email, :key => 'a secret key'
26
- attr_encrypted :credentials, :key => Proc.new { |user| Encryptor.encrypt(:value => user.salt, :key => 'some private key') }, :marshal => true
28
+ attr_encrypted :credentials, :key => Proc.new { |user| Encryptor.encrypt(:value => user.salt, :key => 'some private key', insecure_mode: true, algorithm: 'aes-256-cbc') }, :marshal => true
27
29
 
28
30
  ActiveSupport::Deprecation.silenced = true
29
31
  def after_initialize; end
@@ -55,7 +57,7 @@ class LegacyActiveRecordTest < Minitest::Test
55
57
  def test_should_decrypt_with_correct_encoding
56
58
  if defined?(Encoding)
57
59
  @person = LegacyPerson.create :email => 'test@example.com'
58
- assert_equal 'UTF-8', LegacyPerson.find(:first).email.encoding.name
60
+ assert_equal 'UTF-8', LegacyPerson.first.email.encoding.name
59
61
  end
60
62
  end
61
63
 
@@ -63,14 +65,14 @@ class LegacyActiveRecordTest < Minitest::Test
63
65
  @person = LegacyPerson.create :email => 'test@example.com'
64
66
  refute_nil @person.encrypted_email
65
67
  refute_equal @person.email, @person.encrypted_email
66
- assert_equal @person.email, LegacyPerson.find(:first).email
68
+ assert_equal @person.email, LegacyPerson.first.email
67
69
  end
68
70
 
69
71
  def test_should_marshal_and_encrypt_credentials
70
72
  @person = LegacyPerson.create
71
73
  refute_nil @person.encrypted_credentials
72
74
  refute_equal @person.credentials, @person.encrypted_credentials
73
- assert_equal @person.credentials, LegacyPerson.find(:first).credentials
75
+ assert_equal @person.credentials, LegacyPerson.first.credentials
74
76
  end
75
77
 
76
78
  def test_should_find_by_email
@@ -86,13 +88,13 @@ class LegacyActiveRecordTest < Minitest::Test
86
88
 
87
89
  def test_should_scope_by_email
88
90
  @person = LegacyPerson.create(:email => 'test@example.com')
89
- assert_equal @person, LegacyPerson.scoped_by_email('test@example.com').find(:first) rescue NoMethodError
91
+ assert_equal @person, LegacyPerson.scoped_by_email('test@example.com').first rescue NoMethodError
90
92
  end
91
93
 
92
94
  def test_should_scope_by_email_and_password
93
95
  LegacyPerson.create(:email => 'test@example.com', :password => 'invalid')
94
96
  @person = LegacyPerson.create(:email => 'test@example.com', :password => 'test')
95
- assert_equal @person, LegacyPerson.scoped_by_email_and_password('test@example.com', 'test').find(:first) rescue NoMethodError
97
+ assert_equal @person, LegacyPerson.scoped_by_email_and_password('test@example.com', 'test').first rescue NoMethodError
96
98
  end
97
99
 
98
100
  def test_should_encode_by_default
@@ -1,5 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../test_helper', __FILE__)
2
+ require_relative 'test_helper'
3
3
 
4
4
  class LegacySillyEncryptor
5
5
  def self.silly_encrypt(options)
@@ -12,7 +12,11 @@ class LegacySillyEncryptor
12
12
  end
13
13
 
14
14
  class LegacyUser
15
+ extend AttrEncrypted
15
16
  self.attr_encrypted_options[:key] = Proc.new { |user| user.class.to_s } # default key
17
+ self.attr_encrypted_options[:insecure_mode] = true
18
+ self.attr_encrypted_options[:algorithm] = 'aes-256-cbc'
19
+ self.attr_encrypted_options[:mode] = :single_iv_and_salt
16
20
 
17
21
  attr_encrypted :email, :without_encoding, :key => 'secret key'
18
22
  attr_encrypted :password, :prefix => 'crypted_', :suffix => '_test'
@@ -43,6 +47,7 @@ class LegacyAdmin < LegacyUser
43
47
  end
44
48
 
45
49
  class LegacySomeOtherClass
50
+ extend AttrEncrypted
46
51
  def self.call(object)
47
52
  object.class
48
53
  end
@@ -174,7 +179,7 @@ class LegacyAttrEncryptedTest < Minitest::Test
174
179
  assert_nil @user.ssn_encrypted
175
180
  @user.ssn = 'testing'
176
181
  refute_nil @user.ssn_encrypted
177
- assert_equal Encryptor.encrypt(:value => 'testing', :key => @user.salt), @user.ssn_encrypted
182
+ assert_equal Encryptor.encrypt(:value => 'testing', :key => @user.salt, insecure_mode: true, algorithm: 'aes-256-cbc'), @user.ssn_encrypted
178
183
  end
179
184
 
180
185
  def test_should_evaluate_a_key_passed_as_a_proc
@@ -182,7 +187,7 @@ class LegacyAttrEncryptedTest < Minitest::Test
182
187
  assert_nil @user.crypted_password_test
183
188
  @user.password = 'testing'
184
189
  refute_nil @user.crypted_password_test
185
- assert_equal Encryptor.encrypt(:value => 'testing', :key => 'LegacyUser'), @user.crypted_password_test
190
+ assert_equal Encryptor.encrypt(:value => 'testing', :key => 'LegacyUser', insecure_mode: true, algorithm: 'aes-256-cbc'), @user.crypted_password_test
186
191
  end
187
192
 
188
193
  def test_should_use_options_found_in_the_attr_encrypted_options_attribute
@@ -190,7 +195,7 @@ class LegacyAttrEncryptedTest < Minitest::Test
190
195
  assert_nil @user.crypted_password_test
191
196
  @user.password = 'testing'
192
197
  refute_nil @user.crypted_password_test
193
- assert_equal Encryptor.encrypt(:value => 'testing', :key => 'LegacyUser'), @user.crypted_password_test
198
+ assert_equal Encryptor.encrypt(:value => 'testing', :key => 'LegacyUser', insecure_mode: true, algorithm: 'aes-256-cbc'), @user.crypted_password_test
194
199
  end
195
200
 
196
201
  def test_should_inherit_encrypted_attributes
@@ -208,23 +213,24 @@ class LegacyAttrEncryptedTest < Minitest::Test
208
213
  end
209
214
 
210
215
  def test_should_evaluate_a_symbol_option
211
- assert_equal Object, Object.new.send(:evaluate_attr_encrypted_option, :class)
216
+ assert_equal LegacySomeOtherClass, LegacySomeOtherClass.new.send(:evaluate_attr_encrypted_option, :class)
212
217
  end
213
218
 
214
219
  def test_should_evaluate_a_proc_option
215
- assert_equal Object, Object.new.send(:evaluate_attr_encrypted_option, proc { |object| object.class })
220
+ assert_equal LegacySomeOtherClass, LegacySomeOtherClass.new.send(:evaluate_attr_encrypted_option, proc { |object| object.class })
216
221
  end
217
222
 
218
223
  def test_should_evaluate_a_lambda_option
219
- assert_equal Object, Object.new.send(:evaluate_attr_encrypted_option, lambda { |object| object.class })
224
+ assert_equal LegacySomeOtherClass, LegacySomeOtherClass.new.send(:evaluate_attr_encrypted_option, lambda { |object| object.class })
220
225
  end
221
226
 
222
227
  def test_should_evaluate_a_method_option
223
- assert_equal Object, Object.new.send(:evaluate_attr_encrypted_option, LegacySomeOtherClass.method(:call))
228
+ assert_equal LegacySomeOtherClass, LegacySomeOtherClass.new.send(:evaluate_attr_encrypted_option, LegacySomeOtherClass.method(:call))
224
229
  end
225
230
 
226
231
  def test_should_return_a_string_option
227
- assert_equal 'Object', Object.new.send(:evaluate_attr_encrypted_option, 'Object')
232
+ class_string = 'LegacySomeOtherClass'
233
+ assert_equal class_string, LegacySomeOtherClass.new.send(:evaluate_attr_encrypted_option, class_string)
228
234
  end
229
235
 
230
236
  def test_should_encrypt_with_true_if
@@ -232,7 +238,7 @@ class LegacyAttrEncryptedTest < Minitest::Test
232
238
  assert_nil @user.encrypted_with_true_if
233
239
  @user.with_true_if = 'testing'
234
240
  refute_nil @user.encrypted_with_true_if
235
- assert_equal Encryptor.encrypt(:value => 'testing', :key => 'secret key'), @user.encrypted_with_true_if
241
+ assert_equal Encryptor.encrypt(:value => 'testing', :key => 'secret key', insecure_mode: true, algorithm: 'aes-256-cbc'), @user.encrypted_with_true_if
236
242
  end
237
243
 
238
244
  def test_should_not_encrypt_with_false_if
@@ -248,7 +254,7 @@ class LegacyAttrEncryptedTest < Minitest::Test
248
254
  assert_nil @user.encrypted_with_false_unless
249
255
  @user.with_false_unless = 'testing'
250
256
  refute_nil @user.encrypted_with_false_unless
251
- assert_equal Encryptor.encrypt(:value => 'testing', :key => 'secret key'), @user.encrypted_with_false_unless
257
+ assert_equal Encryptor.encrypt(:value => 'testing', :key => 'secret key', insecure_mode: true, algorithm: 'aes-256-cbc'), @user.encrypted_with_false_unless
252
258
  end
253
259
 
254
260
  def test_should_not_encrypt_with_true_unless
@@ -266,11 +272,6 @@ class LegacyAttrEncryptedTest < Minitest::Test
266
272
  def test_should_always_reset_options
267
273
  @user = LegacyUser.new
268
274
  @user.with_if_changed = "encrypt_stuff"
269
- @user.stubs(:instance_variable_get).returns(nil)
270
- @user.stubs(:instance_variable_set).raises("BadStuff")
271
- assert_raises RuntimeError do
272
- @user.with_if_changed
273
- end
274
275
 
275
276
  @user = LegacyUser.new
276
277
  @user.should_encrypt = false