attr_encrypted 1.4.0 → 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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