symmetric-encryption 3.4.0 → 3.6.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.
- checksums.yaml +4 -4
- data/README.md +102 -55
- data/Rakefile +13 -8
- data/lib/rails/generators/symmetric_encryption/config/config_generator.rb +1 -1
- data/lib/rails/generators/symmetric_encryption/heroku_config/templates/symmetric-encryption.yml +2 -2
- data/lib/rails/generators/symmetric_encryption/new_keys/new_keys_generator.rb +2 -2
- data/lib/symmetric_encryption.rb +7 -6
- data/lib/symmetric_encryption/cipher.rb +4 -4
- data/lib/symmetric_encryption/extensions/active_record/base.rb +6 -46
- data/lib/symmetric_encryption/extensions/mongo_mapper/plugins/encrypted_key.rb +129 -0
- data/lib/symmetric_encryption/{mongoid.rb → extensions/mongoid/encrypted.rb} +12 -46
- data/lib/symmetric_encryption/generator.rb +54 -0
- data/lib/symmetric_encryption/railtie.rb +3 -3
- data/lib/symmetric_encryption/railties/symmetric_encryption.rake +1 -1
- data/lib/symmetric_encryption/railties/symmetric_encryption_validator.rb +1 -1
- data/lib/symmetric_encryption/reader.rb +3 -3
- data/lib/symmetric_encryption/symmetric_encryption.rb +25 -15
- data/lib/symmetric_encryption/version.rb +1 -1
- data/lib/symmetric_encryption/writer.rb +4 -4
- data/test/active_record_test.rb +474 -0
- data/test/cipher_test.rb +15 -15
- data/test/config/mongo_mapper.yml +7 -0
- data/test/{field_encrypted_test.rb → mongo_mapper_test.rb} +68 -67
- data/test/mongoid_test.rb +535 -0
- data/test/reader_test.rb +10 -10
- data/test/symmetric_encryption_test.rb +27 -27
- data/test/test_db.sqlite3 +0 -0
- data/test/test_helper.rb +0 -1
- data/test/writer_test.rb +2 -2
- metadata +14 -8
- data/test/attr_encrypted_test.rb +0 -622
data/test/reader_test.rb
CHANGED
@@ -89,19 +89,19 @@ class ReaderTest < Test::Unit::TestCase
|
|
89
89
|
|
90
90
|
[
|
91
91
|
# No Header
|
92
|
-
{:
|
92
|
+
{header: false, random_key: false, random_iv: false},
|
93
93
|
# Default Header with random key and iv
|
94
94
|
{},
|
95
95
|
# Header with no compression ( default anyway )
|
96
|
-
{:
|
96
|
+
{compress: false},
|
97
97
|
# Compress and use Random key, iv
|
98
|
-
{:
|
98
|
+
{compress: true},
|
99
99
|
# Header but not random key or iv
|
100
|
-
{:
|
100
|
+
{random_key: false},
|
101
101
|
# Random iv only
|
102
|
-
{:
|
102
|
+
{random_key: false, random_iv: true},
|
103
103
|
# Random iv only with compression
|
104
|
-
{:
|
104
|
+
{random_iv: true, compress: true},
|
105
105
|
].each do |options|
|
106
106
|
|
107
107
|
[:data, :empty, :blank].each do |usecase|
|
@@ -245,7 +245,7 @@ class ReaderTest < Test::Unit::TestCase
|
|
245
245
|
setup do
|
246
246
|
@filename = '_test'
|
247
247
|
# Create encrypted file with old encryption key
|
248
|
-
SymmetricEncryption::Writer.open(@filename, :
|
248
|
+
SymmetricEncryption::Writer.open(@filename, version: 0) do |file|
|
249
249
|
@data.inject(0) {|sum,str| sum + file.write(str)}
|
250
250
|
end
|
251
251
|
end
|
@@ -283,7 +283,7 @@ class ReaderTest < Test::Unit::TestCase
|
|
283
283
|
setup do
|
284
284
|
@filename = '_test'
|
285
285
|
# Create encrypted file with old encryption key
|
286
|
-
SymmetricEncryption::Writer.open(@filename, :
|
286
|
+
SymmetricEncryption::Writer.open(@filename, version: 0, header: false, random_key: false) do |file|
|
287
287
|
@data.inject(0) {|sum,str| sum + file.write(str)}
|
288
288
|
end
|
289
289
|
end
|
@@ -297,14 +297,14 @@ class ReaderTest < Test::Unit::TestCase
|
|
297
297
|
end
|
298
298
|
|
299
299
|
should "decrypt from file in a single read" do
|
300
|
-
decrypted = SymmetricEncryption::Reader.open(@filename, :
|
300
|
+
decrypted = SymmetricEncryption::Reader.open(@filename, version: 0) {|file| file.read}
|
301
301
|
assert_equal @data_str, decrypted
|
302
302
|
end
|
303
303
|
|
304
304
|
should "decrypt from file in a single read with different version" do
|
305
305
|
# Should fail since file was encrypted using version 0 key
|
306
306
|
assert_raise OpenSSL::Cipher::CipherError do
|
307
|
-
SymmetricEncryption::Reader.open(@filename, :
|
307
|
+
SymmetricEncryption::Reader.open(@filename, version: 2) {|file| file.read}
|
308
308
|
end
|
309
309
|
end
|
310
310
|
end
|
@@ -108,41 +108,41 @@ class SymmetricEncryptionTest < Test::Unit::TestCase
|
|
108
108
|
assert_equal false, SymmetricEncryption.encrypted?(@social_security_number)
|
109
109
|
end
|
110
110
|
end
|
111
|
+
end
|
111
112
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
113
|
+
context "using select_cipher" do
|
114
|
+
setup do
|
115
|
+
@social_security_number = "987654321"
|
116
|
+
# Encrypt data without a header and encode with base64 which has a trailing '\n'
|
117
|
+
@encrypted_0_ssn = SymmetricEncryption.cipher(0).encode(SymmetricEncryption.cipher(0).binary_encrypt(@social_security_number,false,false,false))
|
117
118
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
end
|
119
|
+
SymmetricEncryption.select_cipher do |encoded_str, decoded_str|
|
120
|
+
# Use cipher version 0 if the encoded string ends with "\n" otherwise
|
121
|
+
# use the current default cipher
|
122
|
+
encoded_str.end_with?("\n") ? SymmetricEncryption.cipher(0) : SymmetricEncryption.cipher
|
123
123
|
end
|
124
|
+
end
|
124
125
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
126
|
+
teardown do
|
127
|
+
# Clear out select_cipher
|
128
|
+
SymmetricEncryption.select_cipher
|
129
|
+
end
|
129
130
|
|
130
|
-
|
131
|
-
|
132
|
-
end
|
131
|
+
should "decrypt string without a header using an old cipher" do
|
132
|
+
assert_equal @social_security_number, SymmetricEncryption.decrypt(@encrypted_0_ssn)
|
133
133
|
end
|
134
|
+
end
|
134
135
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
136
|
+
context "without select_cipher" do
|
137
|
+
setup do
|
138
|
+
@social_security_number = "987654321"
|
139
|
+
# Encrypt data without a header and encode with base64 which has a trailing '\n'
|
140
|
+
assert @encrypted_0_ssn = SymmetricEncryption.cipher(0).encode(SymmetricEncryption.cipher(0).binary_encrypt(@social_security_number,false,false,false))
|
141
|
+
end
|
141
142
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
end
|
143
|
+
should "decrypt string without a header using an old cipher" do
|
144
|
+
assert_raises OpenSSL::Cipher::CipherError do
|
145
|
+
SymmetricEncryption.decrypt(@encrypted_0_ssn)
|
146
146
|
end
|
147
147
|
end
|
148
148
|
end
|
data/test/test_db.sqlite3
CHANGED
Binary file
|
data/test/test_helper.rb
CHANGED
@@ -7,7 +7,6 @@ require 'erb'
|
|
7
7
|
require 'test/unit'
|
8
8
|
# Since we want both the AR and Mongoid extensions loaded we need to require them first
|
9
9
|
require 'active_record'
|
10
|
-
require 'mongoid'
|
11
10
|
require 'symmetric-encryption'
|
12
11
|
# Should redefines Proc#bind so must include after Rails
|
13
12
|
require 'shoulda'
|
data/test/writer_test.rb
CHANGED
@@ -27,7 +27,7 @@ class WriterTest < Test::Unit::TestCase
|
|
27
27
|
|
28
28
|
should "encrypt to string stream" do
|
29
29
|
stream = StringIO.new
|
30
|
-
file = SymmetricEncryption::Writer.new(stream, :
|
30
|
+
file = SymmetricEncryption::Writer.new(stream, header: false, random_key: false, random_iv: false)
|
31
31
|
written_len = @data.inject(0) {|sum,str| sum + file.write(str)}
|
32
32
|
assert_equal @data_len, file.size
|
33
33
|
file.close
|
@@ -50,7 +50,7 @@ class WriterTest < Test::Unit::TestCase
|
|
50
50
|
|
51
51
|
should "encrypt to file using .open" do
|
52
52
|
written_len = nil
|
53
|
-
SymmetricEncryption::Writer.open(@filename, :
|
53
|
+
SymmetricEncryption::Writer.open(@filename, header: false, random_key: false, random_iv: false) do |file|
|
54
54
|
written_len = @data.inject(0) {|sum,str| sum + file.write(str)}
|
55
55
|
assert_equal @data_len, file.size
|
56
56
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: symmetric-encryption
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Reid Morrison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-06-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: coercible
|
@@ -46,7 +46,9 @@ files:
|
|
46
46
|
- lib/symmetric_encryption.rb
|
47
47
|
- lib/symmetric_encryption/cipher.rb
|
48
48
|
- lib/symmetric_encryption/extensions/active_record/base.rb
|
49
|
-
- lib/symmetric_encryption/
|
49
|
+
- lib/symmetric_encryption/extensions/mongo_mapper/plugins/encrypted_key.rb
|
50
|
+
- lib/symmetric_encryption/extensions/mongoid/encrypted.rb
|
51
|
+
- lib/symmetric_encryption/generator.rb
|
50
52
|
- lib/symmetric_encryption/railtie.rb
|
51
53
|
- lib/symmetric_encryption/railties/symmetric_encryption.rake
|
52
54
|
- lib/symmetric_encryption/railties/symmetric_encryption_validator.rb
|
@@ -54,10 +56,11 @@ files:
|
|
54
56
|
- lib/symmetric_encryption/symmetric_encryption.rb
|
55
57
|
- lib/symmetric_encryption/version.rb
|
56
58
|
- lib/symmetric_encryption/writer.rb
|
57
|
-
- test/
|
59
|
+
- test/active_record_test.rb
|
58
60
|
- test/cipher_test.rb
|
59
61
|
- test/config/database.yml
|
60
62
|
- test/config/empty.csv
|
63
|
+
- test/config/mongo_mapper.yml
|
61
64
|
- test/config/mongoid_v2.yml
|
62
65
|
- test/config/mongoid_v3.yml
|
63
66
|
- test/config/symmetric-encryption.yml
|
@@ -65,7 +68,8 @@ files:
|
|
65
68
|
- test/config/test_new.key
|
66
69
|
- test/config/test_secondary_1.iv
|
67
70
|
- test/config/test_secondary_1.key
|
68
|
-
- test/
|
71
|
+
- test/mongo_mapper_test.rb
|
72
|
+
- test/mongoid_test.rb
|
69
73
|
- test/reader_test.rb
|
70
74
|
- test/symmetric_encryption_test.rb
|
71
75
|
- test/test_db.sqlite3
|
@@ -91,15 +95,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
95
|
version: '0'
|
92
96
|
requirements: []
|
93
97
|
rubyforge_project:
|
94
|
-
rubygems_version: 2.2.
|
98
|
+
rubygems_version: 2.2.2
|
95
99
|
signing_key:
|
96
100
|
specification_version: 4
|
97
101
|
summary: Symmetric Encryption for Ruby, and Ruby on Rails
|
98
102
|
test_files:
|
99
|
-
- test/
|
103
|
+
- test/active_record_test.rb
|
100
104
|
- test/cipher_test.rb
|
101
105
|
- test/config/database.yml
|
102
106
|
- test/config/empty.csv
|
107
|
+
- test/config/mongo_mapper.yml
|
103
108
|
- test/config/mongoid_v2.yml
|
104
109
|
- test/config/mongoid_v3.yml
|
105
110
|
- test/config/symmetric-encryption.yml
|
@@ -107,7 +112,8 @@ test_files:
|
|
107
112
|
- test/config/test_new.key
|
108
113
|
- test/config/test_secondary_1.iv
|
109
114
|
- test/config/test_secondary_1.key
|
110
|
-
- test/
|
115
|
+
- test/mongo_mapper_test.rb
|
116
|
+
- test/mongoid_test.rb
|
111
117
|
- test/reader_test.rb
|
112
118
|
- test/symmetric_encryption_test.rb
|
113
119
|
- test/test_db.sqlite3
|
data/test/attr_encrypted_test.rb
DELETED
@@ -1,622 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/test_helper'
|
2
|
-
|
3
|
-
ActiveRecord::Base.logger = SemanticLogger[ActiveRecord]
|
4
|
-
ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read('test/config/database.yml')).result)
|
5
|
-
ActiveRecord::Base.establish_connection('test')
|
6
|
-
|
7
|
-
ActiveRecord::Schema.define :version => 0 do
|
8
|
-
create_table :users, :force => true do |t|
|
9
|
-
t.string :encrypted_bank_account_number
|
10
|
-
t.string :encrypted_social_security_number
|
11
|
-
t.string :encrypted_string
|
12
|
-
t.text :encrypted_long_string
|
13
|
-
t.text :encrypted_data_yaml
|
14
|
-
t.text :encrypted_data_json
|
15
|
-
t.string :name
|
16
|
-
|
17
|
-
t.string :encrypted_integer_value
|
18
|
-
t.string :encrypted_float_value
|
19
|
-
t.string :encrypted_decimal_value
|
20
|
-
t.string :encrypted_datetime_value
|
21
|
-
t.string :encrypted_time_value
|
22
|
-
t.string :encrypted_date_value
|
23
|
-
t.string :encrypted_true_value
|
24
|
-
t.string :encrypted_false_value
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class User < ActiveRecord::Base
|
29
|
-
attr_encrypted :bank_account_number
|
30
|
-
attr_encrypted :social_security_number
|
31
|
-
attr_encrypted :string, :random_iv => true
|
32
|
-
attr_encrypted :long_string, :random_iv => true, :compress => true
|
33
|
-
attr_encrypted :data_yaml, :random_iv => true, :compress => true, :type => :yaml
|
34
|
-
attr_encrypted :data_json, :random_iv => true, :compress => true, :type => :json
|
35
|
-
|
36
|
-
attr_encrypted :integer_value, :type => :integer
|
37
|
-
attr_encrypted :float_value, :type => :float
|
38
|
-
attr_encrypted :decimal_value, :type => :decimal
|
39
|
-
attr_encrypted :datetime_value, :type => :datetime
|
40
|
-
attr_encrypted :time_value, :type => :time
|
41
|
-
attr_encrypted :date_value, :type => :date
|
42
|
-
attr_encrypted :true_value, :type => :boolean
|
43
|
-
attr_encrypted :false_value, :type => :boolean
|
44
|
-
|
45
|
-
validates :encrypted_bank_account_number, :symmetric_encryption => true
|
46
|
-
validates :encrypted_social_security_number, :symmetric_encryption => true
|
47
|
-
end
|
48
|
-
|
49
|
-
# Load Symmetric Encryption keys
|
50
|
-
SymmetricEncryption.load!(File.join(File.dirname(__FILE__), 'config', 'symmetric-encryption.yml'), 'test')
|
51
|
-
|
52
|
-
# Initialize the database connection
|
53
|
-
config_file = File.join(File.dirname(__FILE__), 'config', 'database.yml')
|
54
|
-
raise "database config not found. Create a config file at: test/config/database.yml" unless File.exists? config_file
|
55
|
-
|
56
|
-
cfg = YAML.load(ERB.new(File.new(config_file).read).result)['test']
|
57
|
-
raise("Environment 'test' not defined in test/config/database.yml") unless cfg
|
58
|
-
|
59
|
-
User.establish_connection(cfg)
|
60
|
-
|
61
|
-
#
|
62
|
-
# Unit Test for attr_encrypted and validation aspects of SymmetricEncryption
|
63
|
-
#
|
64
|
-
class AttrEncryptedTest < Test::Unit::TestCase
|
65
|
-
context 'the SymmetricEncryption Library' do
|
66
|
-
|
67
|
-
setup do
|
68
|
-
@bank_account_number = "1234567890"
|
69
|
-
@bank_account_number_encrypted = "QEVuQwIAL94ArJeFlJrZp6SYsvoOGA=="
|
70
|
-
|
71
|
-
@social_security_number = "987654321"
|
72
|
-
@social_security_number_encrypted = "QEVuQwIAS+8X1NRrqdfEIQyFHVPuVA=="
|
73
|
-
|
74
|
-
@string = "A string containing some data to be encrypted with a random initialization vector"
|
75
|
-
@long_string = "A string containing some data to be encrypted with a random initialization vector and compressed since it takes up so much space in plain text form"
|
76
|
-
|
77
|
-
@name = 'Joe Bloggs'
|
78
|
-
|
79
|
-
@integer_value = 12
|
80
|
-
@float_value = 88.12345
|
81
|
-
@decimal_value = BigDecimal.new("22.51")
|
82
|
-
@datetime_value = DateTime.new(2001, 11, 26, 20, 55, 54, "-5")
|
83
|
-
@time_value = Time.new(2013, 01, 01, 22, 30, 00, "-04:00")
|
84
|
-
@date_value = Date.new(1927, 04, 02)
|
85
|
-
@h = { :a => 'A', :b => 'B' }
|
86
|
-
|
87
|
-
@user = User.new(
|
88
|
-
# Encrypted Attribute
|
89
|
-
:bank_account_number => @bank_account_number,
|
90
|
-
# Encrypted Attribute
|
91
|
-
:social_security_number => @social_security_number,
|
92
|
-
:name => @name,
|
93
|
-
# data type specific fields
|
94
|
-
:integer_value => @integer_value,
|
95
|
-
:float_value => @float_value,
|
96
|
-
:decimal_value => @decimal_value,
|
97
|
-
:datetime_value => @datetime_value,
|
98
|
-
:time_value => @time_value,
|
99
|
-
:date_value => @date_value,
|
100
|
-
:true_value => true,
|
101
|
-
:false_value => false,
|
102
|
-
:data_yaml => @h.dup,
|
103
|
-
:data_json => @h.dup
|
104
|
-
)
|
105
|
-
end
|
106
|
-
|
107
|
-
should "have encrypted methods" do
|
108
|
-
assert_equal true, @user.respond_to?(:encrypted_bank_account_number)
|
109
|
-
assert_equal true, @user.respond_to?(:bank_account_number)
|
110
|
-
assert_equal true, @user.respond_to?(:encrypted_social_security_number)
|
111
|
-
assert_equal true, @user.respond_to?(:social_security_number)
|
112
|
-
assert_equal true, @user.respond_to?(:data_yaml)
|
113
|
-
assert_equal true, @user.respond_to?(:data_json)
|
114
|
-
assert_equal false, @user.respond_to?(:encrypted_name)
|
115
|
-
end
|
116
|
-
|
117
|
-
should "have unencrypted values" do
|
118
|
-
assert_equal @bank_account_number, @user.bank_account_number
|
119
|
-
assert_equal @social_security_number, @user.social_security_number
|
120
|
-
end
|
121
|
-
|
122
|
-
should "have encrypted values" do
|
123
|
-
assert_equal @bank_account_number_encrypted, @user.encrypted_bank_account_number
|
124
|
-
assert_equal @social_security_number_encrypted, @user.encrypted_social_security_number
|
125
|
-
end
|
126
|
-
|
127
|
-
should "support same iv" do
|
128
|
-
@user.social_security_number = @social_security_number
|
129
|
-
assert first_value = @user.social_security_number
|
130
|
-
# Assign the same value
|
131
|
-
@user.social_security_number = @social_security_number
|
132
|
-
assert_equal first_value, @user.social_security_number
|
133
|
-
end
|
134
|
-
|
135
|
-
should "support a random iv" do
|
136
|
-
@user.string = @string
|
137
|
-
assert first_value = @user.encrypted_string
|
138
|
-
# Assign the same value
|
139
|
-
@user.string = @string.dup
|
140
|
-
assert_equal true, first_value != @user.encrypted_string
|
141
|
-
end
|
142
|
-
|
143
|
-
should "support a random iv and compress" do
|
144
|
-
@user.string = @long_string
|
145
|
-
@user.long_string = @long_string
|
146
|
-
|
147
|
-
assert_equal true, (@user.encrypted_long_string.length.to_f / @user.encrypted_string.length) < 0.8
|
148
|
-
end
|
149
|
-
|
150
|
-
should "encrypt" do
|
151
|
-
user = User.new
|
152
|
-
user.bank_account_number = @bank_account_number
|
153
|
-
assert_equal @bank_account_number, user.bank_account_number
|
154
|
-
assert_equal @bank_account_number_encrypted, user.encrypted_bank_account_number
|
155
|
-
end
|
156
|
-
|
157
|
-
should "allow lookups using unencrypted or encrypted column name" do
|
158
|
-
@user.save!
|
159
|
-
|
160
|
-
inq = User.find_by_bank_account_number(@bank_account_number)
|
161
|
-
assert_equal @bank_account_number, inq.bank_account_number
|
162
|
-
assert_equal @bank_account_number_encrypted, inq.encrypted_bank_account_number
|
163
|
-
|
164
|
-
@user.delete
|
165
|
-
end
|
166
|
-
|
167
|
-
should "all paths should lead to the same result" do
|
168
|
-
assert_equal @bank_account_number_encrypted, (@user.encrypted_social_security_number = @bank_account_number_encrypted)
|
169
|
-
assert_equal @bank_account_number, @user.social_security_number
|
170
|
-
assert_equal @bank_account_number_encrypted, @user.encrypted_social_security_number
|
171
|
-
end
|
172
|
-
|
173
|
-
should "all paths should lead to the same result 2" do
|
174
|
-
assert_equal @bank_account_number, (@user.social_security_number = @bank_account_number)
|
175
|
-
assert_equal @bank_account_number_encrypted, @user.encrypted_social_security_number
|
176
|
-
assert_equal @bank_account_number, @user.social_security_number
|
177
|
-
end
|
178
|
-
|
179
|
-
should "all paths should lead to the same result, check uninitialized" do
|
180
|
-
user = User.new
|
181
|
-
assert_equal nil, user.social_security_number
|
182
|
-
assert_equal @bank_account_number, (user.social_security_number = @bank_account_number)
|
183
|
-
assert_equal @bank_account_number, user.social_security_number
|
184
|
-
assert_equal @bank_account_number_encrypted, user.encrypted_social_security_number
|
185
|
-
|
186
|
-
assert_equal nil, (user.social_security_number = nil)
|
187
|
-
assert_equal nil, user.social_security_number
|
188
|
-
assert_equal nil, user.encrypted_social_security_number
|
189
|
-
end
|
190
|
-
|
191
|
-
should "allow unencrypted values to be passed to the constructor" do
|
192
|
-
user = User.new(:bank_account_number => @bank_account_number, :social_security_number => @social_security_number)
|
193
|
-
assert_equal @bank_account_number, user.bank_account_number
|
194
|
-
assert_equal @social_security_number, user.social_security_number
|
195
|
-
assert_equal @bank_account_number_encrypted, user.encrypted_bank_account_number
|
196
|
-
assert_equal @social_security_number_encrypted, user.encrypted_social_security_number
|
197
|
-
end
|
198
|
-
|
199
|
-
should "return encrypted attributes for the class" do
|
200
|
-
expect = {:social_security_number=>:encrypted_social_security_number, :bank_account_number=>:encrypted_bank_account_number}
|
201
|
-
result = User.encrypted_attributes
|
202
|
-
expect.each_pair {|k,v| assert_equal expect[k], result[k]}
|
203
|
-
end
|
204
|
-
|
205
|
-
should "return encrypted keys for the class" do
|
206
|
-
expect = [:social_security_number, :bank_account_number]
|
207
|
-
result = User.encrypted_keys
|
208
|
-
expect.each {|val| assert_equal true, result.include?(val)}
|
209
|
-
|
210
|
-
# Also check encrypted_attribute?
|
211
|
-
expect.each {|val| assert_equal true, User.encrypted_attribute?(val)}
|
212
|
-
end
|
213
|
-
|
214
|
-
should "return encrypted columns for the class" do
|
215
|
-
expect = [:encrypted_social_security_number, :encrypted_bank_account_number]
|
216
|
-
result = User.encrypted_columns
|
217
|
-
expect.each {|val| assert_equal true, result.include?(val)}
|
218
|
-
|
219
|
-
# Also check encrypted_column?
|
220
|
-
expect.each {|val| assert_equal true, User.encrypted_column?(val)}
|
221
|
-
end
|
222
|
-
|
223
|
-
should "validate encrypted data" do
|
224
|
-
assert_equal true, @user.valid?
|
225
|
-
@user.encrypted_bank_account_number = '123'
|
226
|
-
assert_equal false, @user.valid?
|
227
|
-
assert_equal ["must be a value encrypted using SymmetricEncryption.encrypt"], @user.errors[:encrypted_bank_account_number]
|
228
|
-
@user.encrypted_bank_account_number = SymmetricEncryption.encrypt('123')
|
229
|
-
assert_equal true, @user.valid?
|
230
|
-
@user.bank_account_number = '123'
|
231
|
-
assert_equal true, @user.valid?
|
232
|
-
end
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
context "with saved user" do
|
237
|
-
setup do
|
238
|
-
@user.save!
|
239
|
-
end
|
240
|
-
|
241
|
-
teardown do
|
242
|
-
@user.destroy
|
243
|
-
end
|
244
|
-
|
245
|
-
should "return correct data type before save" do
|
246
|
-
u = User.new(:integer_value => "5")
|
247
|
-
assert_equal 5, u.integer_value
|
248
|
-
assert u.integer_value.kind_of?(Integer)
|
249
|
-
end
|
250
|
-
|
251
|
-
should "handle gsub! for non-encrypted_field" do
|
252
|
-
@user.name.gsub!('a', 'v')
|
253
|
-
new_name = @name.gsub('a', 'v')
|
254
|
-
assert_equal new_name, @user.name
|
255
|
-
@user.reload
|
256
|
-
assert_equal new_name, @user.name
|
257
|
-
end
|
258
|
-
|
259
|
-
should "prevent gsub! on non-encrypted value of encrypted_field" do
|
260
|
-
# can't modify frozen String
|
261
|
-
assert_raises RuntimeError do
|
262
|
-
@user.bank_account_number.gsub!('5', '4')
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
should "revert changes on reload" do
|
267
|
-
new_bank_account_number = '444444444'
|
268
|
-
@user.bank_account_number = new_bank_account_number
|
269
|
-
assert_equal new_bank_account_number, @user.bank_account_number
|
270
|
-
|
271
|
-
# Reload User model from the database
|
272
|
-
@user.reload
|
273
|
-
assert_equal @bank_account_number_encrypted, @user.encrypted_bank_account_number
|
274
|
-
assert_equal @bank_account_number, @user.bank_account_number
|
275
|
-
end
|
276
|
-
|
277
|
-
should "revert changes to encrypted field on reload" do
|
278
|
-
new_bank_account_number = '111111111'
|
279
|
-
new_encrypted_bank_account_number = SymmetricEncryption.encrypt(new_bank_account_number)
|
280
|
-
@user.encrypted_bank_account_number = new_encrypted_bank_account_number
|
281
|
-
assert_equal new_encrypted_bank_account_number, @user.encrypted_bank_account_number
|
282
|
-
assert_equal new_bank_account_number, @user.bank_account_number
|
283
|
-
|
284
|
-
# Reload User model from the database
|
285
|
-
@user.reload
|
286
|
-
assert_equal @bank_account_number_encrypted, @user.encrypted_bank_account_number
|
287
|
-
assert_equal @bank_account_number, @user.bank_account_number
|
288
|
-
end
|
289
|
-
|
290
|
-
context "data types" do
|
291
|
-
setup do
|
292
|
-
@user_clone = User.find(@user.id)
|
293
|
-
end
|
294
|
-
|
295
|
-
context "integer values" do
|
296
|
-
should "return correct data type" do
|
297
|
-
assert_equal @integer_value, @user_clone.integer_value
|
298
|
-
assert @user.clone.integer_value.kind_of?(Integer)
|
299
|
-
end
|
300
|
-
|
301
|
-
should "coerce data type before save" do
|
302
|
-
u = User.new(:integer_value => "5")
|
303
|
-
assert_equal 5, u.integer_value
|
304
|
-
assert u.integer_value.kind_of?(Integer)
|
305
|
-
end
|
306
|
-
|
307
|
-
should "permit replacing value with nil" do
|
308
|
-
@user_clone.integer_value = nil
|
309
|
-
@user_clone.save!
|
310
|
-
|
311
|
-
@user.reload
|
312
|
-
assert_nil @user.integer_value
|
313
|
-
assert_nil @user.encrypted_integer_value
|
314
|
-
end
|
315
|
-
|
316
|
-
should "permit replacing value" do
|
317
|
-
new_integer_value = 98
|
318
|
-
@user_clone.integer_value = new_integer_value
|
319
|
-
@user_clone.save!
|
320
|
-
|
321
|
-
@user.reload
|
322
|
-
assert_equal new_integer_value, @user.integer_value
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
context "float values" do
|
327
|
-
should "return correct data type" do
|
328
|
-
assert_equal @float_value, @user_clone.float_value
|
329
|
-
assert @user.clone.float_value.kind_of?(Float)
|
330
|
-
end
|
331
|
-
|
332
|
-
should "coerce data type before save" do
|
333
|
-
u = User.new(:float_value => "5.6")
|
334
|
-
assert_equal 5.6, u.float_value
|
335
|
-
assert u.float_value.kind_of?(Float)
|
336
|
-
end
|
337
|
-
|
338
|
-
should "permit replacing value with nil" do
|
339
|
-
@user_clone.float_value = nil
|
340
|
-
@user_clone.save!
|
341
|
-
|
342
|
-
@user.reload
|
343
|
-
assert_nil @user.float_value
|
344
|
-
assert_nil @user.encrypted_float_value
|
345
|
-
end
|
346
|
-
|
347
|
-
should "permit replacing value" do
|
348
|
-
new_float_value = 45.4321
|
349
|
-
@user_clone.float_value = new_float_value
|
350
|
-
@user_clone.save!
|
351
|
-
|
352
|
-
@user.reload
|
353
|
-
assert_equal new_float_value, @user.float_value
|
354
|
-
end
|
355
|
-
end
|
356
|
-
|
357
|
-
context "decimal values" do
|
358
|
-
should "return correct data type" do
|
359
|
-
assert_equal @decimal_value, @user_clone.decimal_value
|
360
|
-
assert @user.clone.decimal_value.kind_of?(BigDecimal)
|
361
|
-
end
|
362
|
-
|
363
|
-
should "coerce data type before save" do
|
364
|
-
u = User.new(:decimal_value => "99.95")
|
365
|
-
assert_equal BigDecimal.new("99.95"), u.decimal_value
|
366
|
-
assert u.decimal_value.kind_of?(BigDecimal)
|
367
|
-
end
|
368
|
-
|
369
|
-
should "permit replacing value with nil" do
|
370
|
-
@user_clone.decimal_value = nil
|
371
|
-
@user_clone.save!
|
372
|
-
|
373
|
-
@user.reload
|
374
|
-
assert_nil @user.decimal_value
|
375
|
-
assert_nil @user.encrypted_decimal_value
|
376
|
-
end
|
377
|
-
|
378
|
-
should "permit replacing value" do
|
379
|
-
new_decimal_value = BigDecimal.new("99.95")
|
380
|
-
@user_clone.decimal_value = new_decimal_value
|
381
|
-
@user_clone.save!
|
382
|
-
|
383
|
-
@user.reload
|
384
|
-
assert_equal new_decimal_value, @user.decimal_value
|
385
|
-
end
|
386
|
-
end
|
387
|
-
|
388
|
-
context "datetime values" do
|
389
|
-
should "return correct data type" do
|
390
|
-
assert_equal @datetime_value, @user_clone.datetime_value
|
391
|
-
assert @user.clone.datetime_value.kind_of?(DateTime)
|
392
|
-
end
|
393
|
-
|
394
|
-
should "coerce data type before save" do
|
395
|
-
now = Time.now
|
396
|
-
u = User.new(:datetime_value => now)
|
397
|
-
assert_equal now, u.datetime_value
|
398
|
-
assert u.datetime_value.kind_of?(DateTime)
|
399
|
-
end
|
400
|
-
|
401
|
-
should "permit replacing value with nil" do
|
402
|
-
@user_clone.datetime_value = nil
|
403
|
-
@user_clone.save!
|
404
|
-
|
405
|
-
@user.reload
|
406
|
-
assert_nil @user.datetime_value
|
407
|
-
assert_nil @user.encrypted_datetime_value
|
408
|
-
end
|
409
|
-
|
410
|
-
should "permit replacing value" do
|
411
|
-
new_datetime_value = DateTime.new(1998, 10, 21, 8, 33, 28, "+5")
|
412
|
-
@user_clone.datetime_value = new_datetime_value
|
413
|
-
@user_clone.save!
|
414
|
-
|
415
|
-
@user.reload
|
416
|
-
assert_equal new_datetime_value, @user.datetime_value
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
|
-
context "time values" do
|
421
|
-
should "return correct data type" do
|
422
|
-
assert_equal @time_value, @user_clone.time_value
|
423
|
-
assert @user.clone.time_value.kind_of?(Time)
|
424
|
-
end
|
425
|
-
|
426
|
-
should "coerce data type before save" do
|
427
|
-
now = Time.now
|
428
|
-
u = User.new(:time_value => now)
|
429
|
-
assert_equal now, u.time_value
|
430
|
-
assert u.time_value.kind_of?(Time)
|
431
|
-
end
|
432
|
-
|
433
|
-
should "permit replacing value with nil" do
|
434
|
-
@user_clone.time_value = nil
|
435
|
-
@user_clone.save!
|
436
|
-
|
437
|
-
@user.reload
|
438
|
-
assert_nil @user.time_value
|
439
|
-
assert_nil @user.encrypted_time_value
|
440
|
-
end
|
441
|
-
|
442
|
-
should "permit replacing value" do
|
443
|
-
new_time_value = Time.new(1998, 10, 21, 8, 33, 28, "+04:00")
|
444
|
-
@user_clone.time_value = new_time_value
|
445
|
-
@user_clone.save!
|
446
|
-
|
447
|
-
@user.reload
|
448
|
-
assert_equal new_time_value, @user.time_value
|
449
|
-
end
|
450
|
-
end
|
451
|
-
|
452
|
-
context "date values" do
|
453
|
-
should "return correct data type" do
|
454
|
-
assert_equal @date_value, @user_clone.date_value
|
455
|
-
assert @user.clone.date_value.kind_of?(Date)
|
456
|
-
end
|
457
|
-
|
458
|
-
should "coerce data type before save" do
|
459
|
-
now = Time.now
|
460
|
-
u = User.new(:date_value => now)
|
461
|
-
assert_equal now.to_date, u.date_value
|
462
|
-
assert u.date_value.kind_of?(Date)
|
463
|
-
end
|
464
|
-
|
465
|
-
should "permit replacing value with nil" do
|
466
|
-
@user_clone.date_value = nil
|
467
|
-
@user_clone.save!
|
468
|
-
|
469
|
-
@user.reload
|
470
|
-
assert_nil @user.date_value
|
471
|
-
assert_nil @user.encrypted_date_value
|
472
|
-
end
|
473
|
-
|
474
|
-
should "permit replacing value" do
|
475
|
-
new_date_value = Date.new(1998, 10, 21)
|
476
|
-
@user_clone.date_value = new_date_value
|
477
|
-
@user_clone.save!
|
478
|
-
|
479
|
-
@user.reload
|
480
|
-
assert_equal new_date_value, @user.date_value
|
481
|
-
end
|
482
|
-
end
|
483
|
-
|
484
|
-
context "true values" do
|
485
|
-
should "return correct data type" do
|
486
|
-
assert_equal true, @user_clone.true_value
|
487
|
-
assert @user.clone.true_value.kind_of?(TrueClass)
|
488
|
-
end
|
489
|
-
|
490
|
-
should "coerce data type before save" do
|
491
|
-
u = User.new(:true_value => "1")
|
492
|
-
assert_equal true, u.true_value
|
493
|
-
assert u.true_value.kind_of?(TrueClass)
|
494
|
-
end
|
495
|
-
|
496
|
-
should "permit replacing value with nil" do
|
497
|
-
@user_clone.true_value = nil
|
498
|
-
@user_clone.save!
|
499
|
-
|
500
|
-
@user.reload
|
501
|
-
assert_nil @user.true_value
|
502
|
-
assert_nil @user.encrypted_true_value
|
503
|
-
end
|
504
|
-
|
505
|
-
should "permit replacing value" do
|
506
|
-
new_value = false
|
507
|
-
@user_clone.true_value = new_value
|
508
|
-
@user_clone.save!
|
509
|
-
|
510
|
-
@user.reload
|
511
|
-
assert_equal new_value, @user.true_value
|
512
|
-
end
|
513
|
-
end
|
514
|
-
|
515
|
-
context "false values" do
|
516
|
-
should "return correct data type" do
|
517
|
-
assert_equal false, @user_clone.false_value
|
518
|
-
assert @user.clone.false_value.kind_of?(FalseClass)
|
519
|
-
end
|
520
|
-
|
521
|
-
should "coerce data type before save" do
|
522
|
-
u = User.new(:false_value => "0")
|
523
|
-
assert_equal false, u.false_value
|
524
|
-
assert u.false_value.kind_of?(FalseClass)
|
525
|
-
end
|
526
|
-
|
527
|
-
should "permit replacing value with nil" do
|
528
|
-
@user_clone.false_value = nil
|
529
|
-
@user_clone.save!
|
530
|
-
|
531
|
-
@user.reload
|
532
|
-
assert_nil @user.false_value
|
533
|
-
assert_nil @user.encrypted_false_value
|
534
|
-
end
|
535
|
-
|
536
|
-
should "permit replacing value" do
|
537
|
-
new_value = true
|
538
|
-
@user_clone.false_value = new_value
|
539
|
-
@user_clone.save!
|
540
|
-
|
541
|
-
@user.reload
|
542
|
-
assert_equal new_value, @user.false_value
|
543
|
-
end
|
544
|
-
end
|
545
|
-
|
546
|
-
context "JSON Serialization" do
|
547
|
-
setup do
|
548
|
-
# JSON Does not support symbols, so they will come back as strings
|
549
|
-
# Convert symbols to string in the test
|
550
|
-
@h.keys.each do |k|
|
551
|
-
@h[k.to_s] = @h[k]
|
552
|
-
@h.delete(k)
|
553
|
-
end
|
554
|
-
end
|
555
|
-
|
556
|
-
should "return correct data type" do
|
557
|
-
assert_equal @h, @user_clone.data_json
|
558
|
-
assert @user.clone.data_json.kind_of?(Hash)
|
559
|
-
end
|
560
|
-
|
561
|
-
should "not coerce data type (leaves as hash) before save" do
|
562
|
-
u = User.new(:data_json => @h)
|
563
|
-
assert_equal @h, u.data_json
|
564
|
-
assert u.data_json.kind_of?(Hash)
|
565
|
-
end
|
566
|
-
|
567
|
-
should "permit replacing value with nil" do
|
568
|
-
@user_clone.data_json = nil
|
569
|
-
@user_clone.save!
|
570
|
-
|
571
|
-
@user.reload
|
572
|
-
assert_nil @user.data_json
|
573
|
-
assert_nil @user.encrypted_data_json
|
574
|
-
end
|
575
|
-
|
576
|
-
should "permit replacing value" do
|
577
|
-
new_value = @h.clone
|
578
|
-
new_value['c'] = 'C'
|
579
|
-
@user_clone.data_json = new_value
|
580
|
-
@user_clone.save!
|
581
|
-
|
582
|
-
@user.reload
|
583
|
-
assert_equal new_value, @user.data_json
|
584
|
-
end
|
585
|
-
end
|
586
|
-
|
587
|
-
context "YAML Serialization" do
|
588
|
-
should "return correct data type" do
|
589
|
-
assert_equal @h, @user_clone.data_yaml
|
590
|
-
assert @user.clone.data_yaml.kind_of?(Hash)
|
591
|
-
end
|
592
|
-
|
593
|
-
should "not coerce data type (leaves as hash) before save" do
|
594
|
-
u = User.new(:data_yaml => @h)
|
595
|
-
assert_equal @h, u.data_yaml
|
596
|
-
assert u.data_yaml.kind_of?(Hash)
|
597
|
-
end
|
598
|
-
|
599
|
-
should "permit replacing value with nil" do
|
600
|
-
@user_clone.data_yaml = nil
|
601
|
-
@user_clone.save!
|
602
|
-
|
603
|
-
@user.reload
|
604
|
-
assert_nil @user.data_yaml
|
605
|
-
assert_nil @user.encrypted_data_yaml
|
606
|
-
end
|
607
|
-
|
608
|
-
should "permit replacing value" do
|
609
|
-
new_value = @h.clone
|
610
|
-
new_value[:c] = 'C'
|
611
|
-
@user_clone.data_yaml = new_value
|
612
|
-
@user_clone.save!
|
613
|
-
|
614
|
-
@user.reload
|
615
|
-
assert_equal new_value, @user.data_yaml
|
616
|
-
end
|
617
|
-
end
|
618
|
-
|
619
|
-
end
|
620
|
-
end
|
621
|
-
end
|
622
|
-
end
|