attr_encrypted 1.3.5 → 3.0.0

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,15 +1,16 @@
1
- require File.expand_path('../test_helper', __FILE__)
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
6
  silence_stream(STDOUT) do
7
- ActiveRecord::Schema.define(:version => 1) do
7
+ ActiveRecord::Schema.define(version: 1) do
8
8
  create_table :people do |t|
9
9
  t.string :encrypted_email
10
10
  t.string :password
11
11
  t.string :encrypted_credentials
12
12
  t.binary :salt
13
+ t.binary :key_iv
13
14
  t.string :encrypted_email_salt
14
15
  t.string :encrypted_credentials_salt
15
16
  t.string :encrypted_email_iv
@@ -23,10 +24,18 @@ def create_tables
23
24
  create_table :users do |t|
24
25
  t.string :login
25
26
  t.string :encrypted_password
27
+ t.string :encrypted_password_iv
26
28
  t.boolean :is_admin
27
29
  end
28
30
  create_table :prime_ministers do |t|
29
31
  t.string :encrypted_name
32
+ t.string :encrypted_name_iv
33
+ end
34
+ create_table :addresses do |t|
35
+ t.binary :encrypted_street
36
+ t.binary :encrypted_street_iv
37
+ t.binary :encrypted_zipcode
38
+ t.string :mode
30
39
  end
31
40
  end
32
41
  end
@@ -36,7 +45,6 @@ end
36
45
  create_tables
37
46
 
38
47
  ActiveRecord::MissingAttributeError = ActiveModel::MissingAttributeError unless defined?(ActiveRecord::MissingAttributeError)
39
- ActiveRecord::Base.logger = Logger.new(nil) if ::ActiveRecord::VERSION::STRING < "3.0"
40
48
 
41
49
  if ::ActiveRecord::VERSION::STRING > "4.0"
42
50
  module Rack
@@ -50,22 +58,17 @@ end
50
58
 
51
59
  class Person < ActiveRecord::Base
52
60
  self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
53
- attr_encrypted :email, :key => SECRET_KEY
54
- attr_encrypted :credentials, :key => Proc.new { |user| Encryptor.encrypt(:value => user.salt, :key => SECRET_KEY) }, :marshal => true
61
+ attr_encrypted :email, key: SECRET_KEY
62
+ attr_encrypted :credentials, key: Proc.new { |user| Encryptor.encrypt(value: user.salt, key: SECRET_KEY, iv: user.key_iv) }, marshal: true
55
63
 
56
- if ActiveRecord::VERSION::STRING < "3"
57
- def after_initialize
58
- initialize_salt_and_credentials
59
- end
60
- else
61
- after_initialize :initialize_salt_and_credentials
62
- end
64
+ after_initialize :initialize_salt_and_credentials
63
65
 
64
66
  protected
65
67
 
66
68
  def initialize_salt_and_credentials
69
+ self.key_iv ||= SecureRandom.random_bytes(12)
67
70
  self.salt ||= Digest::SHA256.hexdigest((Time.now.to_i * rand(1000)).to_s)[0..15]
68
- self.credentials ||= { :username => 'example', :password => 'test' }
71
+ self.credentials ||= { username: 'example', password: 'test' }
69
72
  end
70
73
  end
71
74
 
@@ -74,34 +77,41 @@ class PersonWithValidation < Person
74
77
  end
75
78
 
76
79
  class PersonWithProcMode < Person
77
- attr_encrypted :email, :key => SECRET_KEY, :mode => Proc.new { :per_attribute_iv_and_salt }
78
- attr_encrypted :credentials, :key => SECRET_KEY, :mode => Proc.new { :single_iv_and_salt }
80
+ attr_encrypted :email, key: SECRET_KEY, mode: Proc.new { :per_attribute_iv_and_salt }
81
+ attr_encrypted :credentials, key: SECRET_KEY, mode: Proc.new { :single_iv_and_salt }, insecure_mode: true
79
82
  end
80
83
 
81
84
  class Account < ActiveRecord::Base
82
85
  attr_accessor :key
83
- attr_encrypted :password, :key => Proc.new {|account| account.key}
86
+ attr_encrypted :password, key: Proc.new {|account| account.key}
84
87
  end
85
88
 
86
89
  class PersonWithSerialization < ActiveRecord::Base
87
90
  self.table_name = 'people'
88
- attr_encrypted :email, :key => 'a secret key'
91
+ attr_encrypted :email, key: SECRET_KEY
89
92
  serialize :password
90
93
  end
91
94
 
92
95
  class UserWithProtectedAttribute < ActiveRecord::Base
93
96
  self.table_name = 'users'
94
- attr_encrypted :password, :key => 'a secret key'
97
+ attr_encrypted :password, key: SECRET_KEY
95
98
  attr_protected :is_admin if ::ActiveRecord::VERSION::STRING < "4.0"
96
99
  end
97
100
 
98
101
  class PersonUsingAlias < ActiveRecord::Base
99
102
  self.table_name = 'people'
100
- attr_encryptor :email, :key => 'a secret key'
103
+ attr_encryptor :email, key: SECRET_KEY
101
104
  end
102
105
 
103
106
  class PrimeMinister < ActiveRecord::Base
104
- attr_encrypted :name, :marshal => true, :key => 'SECRET_KEY'
107
+ attr_encrypted :name, marshal: true, key: SECRET_KEY
108
+ end
109
+
110
+ class Address < ActiveRecord::Base
111
+ self.attr_encrypted_options[:marshal] = false
112
+ self.attr_encrypted_options[:encode] = false
113
+ attr_encrypted :street, encode_iv: false, key: SECRET_KEY
114
+ attr_encrypted :zipcode, key: SECRET_KEY, mode: Proc.new { |address| address.mode.to_sym }, insecure_mode: true
105
115
  end
106
116
 
107
117
  class ActiveRecordTest < Minitest::Test
@@ -109,21 +119,21 @@ class ActiveRecordTest < Minitest::Test
109
119
  def setup
110
120
  ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
111
121
  create_tables
112
- Account.create!(:key => SECRET_KEY, :password => "password")
122
+ Account.create!(key: SECRET_KEY, password: "password")
113
123
  end
114
124
 
115
125
  def test_should_encrypt_email
116
- @person = Person.create :email => 'test@example.com'
126
+ @person = Person.create(email: 'test@example.com')
117
127
  refute_nil @person.encrypted_email
118
128
  refute_equal @person.email, @person.encrypted_email
119
- assert_equal @person.email, Person.find(:first).email
129
+ assert_equal @person.email, Person.first.email
120
130
  end
121
131
 
122
132
  def test_should_marshal_and_encrypt_credentials
123
133
  @person = Person.create
124
134
  refute_nil @person.encrypted_credentials
125
135
  refute_equal @person.credentials, @person.encrypted_credentials
126
- assert_equal @person.credentials, Person.find(:first).credentials
136
+ assert_equal @person.credentials, Person.first.credentials
127
137
  end
128
138
 
129
139
  def test_should_encode_by_default
@@ -137,77 +147,97 @@ class ActiveRecordTest < Minitest::Test
137
147
  end
138
148
 
139
149
  def test_should_encrypt_decrypt_with_iv
140
- @person = Person.create :email => 'test@example.com'
150
+ @person = Person.create(email: 'test@example.com')
141
151
  @person2 = Person.find(@person.id)
142
152
  refute_nil @person2.encrypted_email_iv
143
153
  assert_equal 'test@example.com', @person2.email
144
154
  end
145
155
 
146
156
  def test_should_ensure_attributes_can_be_deserialized
147
- @person = PersonWithSerialization.new :email => 'test@example.com', :password => %w(an array of strings)
157
+ @person = PersonWithSerialization.new(email: 'test@example.com', password: %w(an array of strings))
148
158
  @person.save
149
159
  assert_equal @person.password, %w(an array of strings)
150
160
  end
151
161
 
152
162
  def test_should_create_an_account_regardless_of_arguments_order
153
- Account.create!(:key => SECRET_KEY, :password => "password")
154
- Account.create!(:password => "password" , :key => SECRET_KEY)
163
+ Account.create!(key: SECRET_KEY, password: "password")
164
+ Account.create!(password: "password" , key: SECRET_KEY)
155
165
  end
156
166
 
157
167
  def test_should_set_attributes_regardless_of_arguments_order
158
- Account.new.attributes = { :password => "password" , :key => SECRET_KEY }
168
+ # minitest does not implement `assert_nothing_raised` https://github.com/seattlerb/minitest/issues/112
169
+ Account.new.attributes = { password: "password", key: SECRET_KEY }
159
170
  end
160
171
 
161
172
  def test_should_preserve_hash_key_type
162
- hash = { :foo => 'bar' }
163
- account = Account.create!(:key => hash)
173
+ hash = { foo: 'bar' }
174
+ account = Account.create!(key: hash)
164
175
  assert_equal account.key, hash
165
176
  end
166
177
 
178
+ def test_should_create_changed_predicate
179
+ person = Person.create!(email: 'test@example.com')
180
+ refute person.email_changed?
181
+ person.email = 'test@example.com'
182
+ refute person.email_changed?
183
+ person.email = nil
184
+ assert person.email_changed?
185
+ person.email = 'test2@example.com'
186
+ assert person.email_changed?
187
+ end
188
+
189
+ def test_should_create_was_predicate
190
+ original_email = 'test@example.com'
191
+ person = Person.create!(email: original_email)
192
+ assert_equal original_email, person.email_was
193
+ person.email = 'test2@example.com'
194
+ assert_equal original_email, person.email_was
195
+ end
196
+
167
197
  if ::ActiveRecord::VERSION::STRING > "4.0"
168
198
  def test_should_assign_attributes
169
- @user = UserWithProtectedAttribute.new :login => 'login', :is_admin => false
170
- @user.attributes = ActionController::Parameters.new(:login => 'modified', :is_admin => true).permit(:login)
199
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
200
+ @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
171
201
  assert_equal 'modified', @user.login
172
202
  end
173
203
 
174
204
  def test_should_not_assign_protected_attributes
175
- @user = UserWithProtectedAttribute.new :login => 'login', :is_admin => false
176
- @user.attributes = ActionController::Parameters.new(:login => 'modified', :is_admin => true).permit(:login)
205
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
206
+ @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true).permit(:login)
177
207
  assert !@user.is_admin?
178
208
  end
179
209
 
180
210
  def test_should_raise_exception_if_not_permitted
181
- @user = UserWithProtectedAttribute.new :login => 'login', :is_admin => false
211
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
182
212
  assert_raises ActiveModel::ForbiddenAttributesError do
183
- @user.attributes = ActionController::Parameters.new(:login => 'modified', :is_admin => true)
213
+ @user.attributes = ActionController::Parameters.new(login: 'modified', is_admin: true)
184
214
  end
185
215
  end
186
216
 
187
217
  def test_should_raise_exception_on_init_if_not_permitted
188
218
  assert_raises ActiveModel::ForbiddenAttributesError do
189
- @user = UserWithProtectedAttribute.new ActionController::Parameters.new(:login => 'modified', :is_admin => true)
219
+ @user = UserWithProtectedAttribute.new ActionController::Parameters.new(login: 'modified', is_admin: true)
190
220
  end
191
221
  end
192
222
  else
193
223
  def test_should_assign_attributes
194
- @user = UserWithProtectedAttribute.new :login => 'login', :is_admin => false
195
- @user.attributes = {:login => 'modified', :is_admin => true}
224
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
225
+ @user.attributes = { login: 'modified', is_admin: true }
196
226
  assert_equal 'modified', @user.login
197
227
  end
198
228
 
199
229
  def test_should_not_assign_protected_attributes
200
- @user = UserWithProtectedAttribute.new :login => 'login', :is_admin => false
201
- @user.attributes = {:login => 'modified', :is_admin => true}
230
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
231
+ @user.attributes = { login: 'modified', is_admin: true }
202
232
  assert !@user.is_admin?
203
233
  end
204
234
 
205
235
  def test_should_assign_protected_attributes
206
- @user = UserWithProtectedAttribute.new :login => 'login', :is_admin => false
236
+ @user = UserWithProtectedAttribute.new(login: 'login', is_admin: false)
207
237
  if ::ActiveRecord::VERSION::STRING > "3.1"
208
- @user.send :assign_attributes, {:login => 'modified', :is_admin => true}, :without_protection => true
238
+ @user.send(:assign_attributes, { login: 'modified', is_admin: true }, without_protection: true)
209
239
  else
210
- @user.send :attributes=, {:login => 'modified', :is_admin => true}, false
240
+ @user.send(:attributes=, { login: 'modified', is_admin: true }, false)
211
241
  end
212
242
  assert @user.is_admin?
213
243
  end
@@ -219,7 +249,7 @@ class ActiveRecordTest < Minitest::Test
219
249
  end
220
250
 
221
251
  def test_should_allow_proc_based_mode
222
- @person = PersonWithProcMode.create :email => 'test@example.com', :credentials => 'password123'
252
+ @person = PersonWithProcMode.create(email: 'test@example.com', credentials: 'password123')
223
253
 
224
254
  # Email is :per_attribute_iv_and_salt
225
255
  assert_equal @person.class.encrypted_attributes[:email][:mode].class, Proc
@@ -248,19 +278,34 @@ class ActiveRecordTest < Minitest::Test
248
278
 
249
279
  refute_nil user.encrypted_email
250
280
  refute_equal user.email, user.encrypted_email
251
- assert_equal user.email, PersonUsingAlias.find(:first).email
281
+ assert_equal user.email, PersonUsingAlias.first.email
252
282
  end
253
283
 
254
284
  # See https://github.com/attr-encrypted/attr_encrypted/issues/68
255
285
  def test_should_invalidate_virtual_attributes_on_reload
256
- pm = PrimeMinister.new(:name => 'Winston Churchill')
257
- pm.save!
258
- assert_equal 'Winston Churchill', pm.name
259
- pm.name = 'Neville Chamberlain'
260
- assert_equal 'Neville Chamberlain', pm.name
286
+ old_pm_name = 'Winston Churchill'
287
+ new_pm_name = 'Neville Chamberlain'
288
+ pm = PrimeMinister.create!(name: old_pm_name)
289
+ assert_equal old_pm_name, pm.name
290
+ pm.name = new_pm_name
291
+ assert_equal new_pm_name, pm.name
261
292
 
262
293
  result = pm.reload
263
294
  assert_equal pm, result
264
- assert_equal 'Winston Churchill', pm.name
295
+ assert_equal old_pm_name, pm.name
296
+ end
297
+
298
+ def test_should_save_encrypted_data_as_binary
299
+ street = '123 Elm'
300
+ address = Address.create!(street: street)
301
+ refute_equal address.encrypted_street, street
302
+ assert_equal Address.first.street, street
303
+ end
304
+
305
+ def test_should_evaluate_proc_based_mode
306
+ street = '123 Elm'
307
+ zipcode = '12345'
308
+ address = Address.new(street: street, zipcode: zipcode, mode: :single_iv_and_salt)
309
+ assert_nil address.encrypted_zipcode_iv
265
310
  end
266
311
  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
  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