crypt_keeper 0.22.0 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.travis.yml +5 -1
  4. data/Appraisals +6 -6
  5. data/README.md +8 -20
  6. data/Rakefile +7 -3
  7. data/crypt_keeper.gemspec +5 -5
  8. data/gemfiles/{activerecord_4_1.gemfile → activerecord_5_0.gemfile} +2 -2
  9. data/lib/crypt_keeper.rb +1 -2
  10. data/lib/crypt_keeper/helper.rb +0 -18
  11. data/lib/crypt_keeper/log_subscriber/mysql_aes.rb +7 -9
  12. data/lib/crypt_keeper/log_subscriber/postgres_pgp.rb +7 -9
  13. data/lib/crypt_keeper/model.rb +14 -20
  14. data/lib/crypt_keeper/provider/aes_new.rb +1 -1
  15. data/lib/crypt_keeper/provider/base.rb +21 -0
  16. data/lib/crypt_keeper/provider/mysql_aes_new.rb +1 -1
  17. data/lib/crypt_keeper/provider/postgres_pgp.rb +2 -2
  18. data/lib/crypt_keeper/provider/postgres_pgp_public_key.rb +1 -1
  19. data/lib/crypt_keeper/version.rb +1 -1
  20. data/spec/crypt_keeper/log_subscriber/mysql_aes_spec.rb +56 -0
  21. data/spec/crypt_keeper/log_subscriber/postgres_pgp_spec.rb +94 -0
  22. data/spec/crypt_keeper/model_spec.rb +172 -0
  23. data/spec/crypt_keeper/provider/aes_new_spec.rb +41 -0
  24. data/spec/crypt_keeper/provider/mysql_aes_new_spec.rb +50 -0
  25. data/spec/crypt_keeper/provider/postgres_pgp_public_key_spec.rb +66 -0
  26. data/spec/crypt_keeper/provider/postgres_pgp_spec.rb +66 -0
  27. data/spec/spec_helper.rb +0 -1
  28. data/spec/support/encryptors.rb +9 -3
  29. data/spec/support/logging.rb +92 -0
  30. metadata +37 -44
  31. data/gemfiles/activerecord_4_1.gemfile.lock +0 -120
  32. data/gemfiles/activerecord_4_2.gemfile.lock +0 -120
  33. data/lib/crypt_keeper/provider/aes.rb +0 -66
  34. data/lib/crypt_keeper/provider/mysql_aes.rb +0 -47
  35. data/spec/log_subscriber/mysql_aes_spec.rb +0 -73
  36. data/spec/log_subscriber/postgres_pgp_spec.rb +0 -123
  37. data/spec/model_spec.rb +0 -169
  38. data/spec/provider/aes_new_spec.rb +0 -45
  39. data/spec/provider/aes_spec.rb +0 -67
  40. data/spec/provider/mysql_aes_new_spec.rb +0 -54
  41. data/spec/provider/mysql_aes_spec.rb +0 -35
  42. data/spec/provider/postgres_pgp_public_key_spec.rb +0 -70
  43. data/spec/provider/postgres_pgp_spec.rb +0 -70
@@ -1,120 +0,0 @@
1
- PATH
2
- remote: ../
3
- specs:
4
- crypt_keeper (0.21.0)
5
- activerecord (>= 3.1, < 4.3)
6
- activesupport (>= 3.1, < 4.3)
7
- aes (~> 0.5.0)
8
- armor (~> 0.0.2)
9
-
10
- GEM
11
- remote: https://rubygems.org/
12
- specs:
13
- activemodel (4.2.6)
14
- activesupport (= 4.2.6)
15
- builder (~> 3.1)
16
- activerecord (4.2.6)
17
- activemodel (= 4.2.6)
18
- activesupport (= 4.2.6)
19
- arel (~> 6.0)
20
- activesupport (4.2.6)
21
- i18n (~> 0.7)
22
- json (~> 1.7, >= 1.7.7)
23
- minitest (~> 5.1)
24
- thread_safe (~> 0.3, >= 0.3.4)
25
- tzinfo (~> 1.1)
26
- aes (0.5.0)
27
- appraisal (1.0.3)
28
- bundler
29
- rake
30
- thor (>= 0.14.0)
31
- arel (6.0.3)
32
- armor (0.0.3)
33
- builder (3.2.2)
34
- celluloid (0.16.0)
35
- timers (~> 4.0.0)
36
- coderay (1.1.1)
37
- coveralls (0.8.13)
38
- json (~> 1.8)
39
- simplecov (~> 0.11.0)
40
- term-ansicolor (~> 1.3)
41
- thor (~> 0.19.1)
42
- tins (~> 1.6.0)
43
- diff-lcs (1.2.5)
44
- docile (1.1.5)
45
- ffi (1.9.10)
46
- formatador (0.2.5)
47
- guard (2.6.1)
48
- formatador (>= 0.2.4)
49
- listen (~> 2.7)
50
- lumberjack (~> 1.0)
51
- pry (>= 0.9.12)
52
- thor (>= 0.18.1)
53
- guard-rspec (4.2.10)
54
- guard (~> 2.1)
55
- rspec (>= 2.14, < 4.0)
56
- hitimes (1.2.4)
57
- i18n (0.7.0)
58
- json (1.8.3)
59
- listen (2.10.1)
60
- celluloid (~> 0.16.0)
61
- rb-fsevent (>= 0.9.3)
62
- rb-inotify (>= 0.9)
63
- lumberjack (1.0.10)
64
- method_source (0.8.2)
65
- minitest (5.9.0)
66
- mysql2 (0.3.21)
67
- pg (0.17.1)
68
- pry (0.10.3)
69
- coderay (~> 1.1.0)
70
- method_source (~> 0.8.1)
71
- slop (~> 3.4)
72
- rake (10.3.2)
73
- rb-fsevent (0.9.7)
74
- rb-inotify (0.9.7)
75
- ffi (>= 0.5.0)
76
- rspec (2.14.1)
77
- rspec-core (~> 2.14.0)
78
- rspec-expectations (~> 2.14.0)
79
- rspec-mocks (~> 2.14.0)
80
- rspec-core (2.14.8)
81
- rspec-expectations (2.14.5)
82
- diff-lcs (>= 1.1.3, < 2.0)
83
- rspec-mocks (2.14.6)
84
- simplecov (0.11.2)
85
- docile (~> 1.1.0)
86
- json (~> 1.8)
87
- simplecov-html (~> 0.10.0)
88
- simplecov-html (0.10.0)
89
- slop (3.6.0)
90
- sqlite3 (1.3.11)
91
- term-ansicolor (1.3.2)
92
- tins (~> 1.0)
93
- thor (0.19.1)
94
- thread_safe (0.3.5)
95
- timers (4.0.4)
96
- hitimes
97
- tins (1.6.0)
98
- tzinfo (1.2.2)
99
- thread_safe (~> 0.1)
100
-
101
- PLATFORMS
102
- ruby
103
-
104
- DEPENDENCIES
105
- activerecord (~> 4.2.0)
106
- activesupport (~> 4.2.0)
107
- appraisal (~> 1.0.0)
108
- coveralls
109
- crypt_keeper!
110
- guard (~> 2.6.1)
111
- guard-rspec (~> 4.2.9)
112
- mysql2 (~> 0.3.11)
113
- pg (~> 0.17.1)
114
- rake (~> 10.3.1)
115
- rb-fsevent (~> 0.9.1)
116
- rspec (~> 2.14.0)
117
- sqlite3
118
-
119
- BUNDLED WITH
120
- 1.12.5
@@ -1,66 +0,0 @@
1
- require 'digest/sha2'
2
- require 'openssl'
3
- require 'base64'
4
-
5
- module CryptKeeper
6
- module Provider
7
- class Aes
8
- SEPARATOR = ":crypt_keeper:"
9
-
10
- # Public: The encryption key
11
- attr_accessor :key
12
-
13
- # Public: An instance of OpenSSL::Cipher::Cipher
14
- attr_accessor :aes
15
-
16
- # Public: Initializes the class
17
- #
18
- # options - A hash of options. :key is required
19
- def initialize(options = {})
20
- legacy
21
- @aes = ::OpenSSL::Cipher::Cipher.new("AES-256-CBC")
22
- @aes.padding = 1
23
-
24
- key = options.fetch(:key) do
25
- raise ArgumentError, "Missing :key"
26
- end
27
-
28
- @key = Digest::SHA256.digest(key)
29
- end
30
-
31
- # Public: Encrypt a string
32
- #
33
- # Note: nil and empty strings are not encryptable with AES.
34
- # When they are encountered, the orignal value is returned.
35
- # Otherwise, returns the encrypted string
36
- def encrypt(value)
37
- return value if value == '' || value.nil?
38
- aes.encrypt
39
- aes.key = key
40
- Base64::encode64("#{aes.random_iv}#{SEPARATOR}#{aes.update(value.to_s) + aes.final}")
41
- end
42
-
43
- # Public: Decrypt a string
44
- #
45
- # Note: nil and empty strings are not encryptable with AES (and thus cannot be decrypted).
46
- # When they are encountered, the orignal value is returned.
47
- # Otherwise, returns the decrypted string
48
- def decrypt(value)
49
- return value if value == '' || value.nil?
50
- iv, value = Base64::decode64(value.to_s).split(SEPARATOR)
51
- aes.decrypt
52
- aes.key = key
53
- aes.iv = iv
54
- aes.update(value) + aes.final
55
- end
56
-
57
- private
58
-
59
- def legacy
60
- unless ENV['CRYPT_KEEPER_IGNORE_LEGACY_DEPRECATION']
61
- warn "[DEPRECATION] AES Legacy is now deprecated. Please see http://git.io/uYcp2A"
62
- end
63
- end
64
- end
65
- end
66
- end
@@ -1,47 +0,0 @@
1
- require 'crypt_keeper/log_subscriber/mysql_aes'
2
-
3
- module CryptKeeper
4
- module Provider
5
- class MysqlAes
6
- include CryptKeeper::Helper::SQL
7
-
8
- attr_accessor :key
9
-
10
- # Public: Initializes the encryptor
11
- #
12
- # options - A hash, :key is required
13
- def initialize(options = {})
14
- legacy
15
- ActiveSupport.run_load_hooks(:crypt_keeper_mysql_aes_log, self)
16
-
17
- @key = options.fetch(:key) do
18
- raise ArgumentError, "Missing :key"
19
- end
20
- end
21
-
22
- # Public: Encrypts a string
23
- #
24
- # Returns an encrypted string
25
- def encrypt(value)
26
- Base64.encode64 escape_and_execute_sql(
27
- ["SELECT AES_ENCRYPT(?, ?)", value, key]).first
28
- end
29
-
30
- # Public: Decrypts a string
31
- #
32
- # Returns a plaintext string
33
- def decrypt(value)
34
- escape_and_execute_sql(
35
- ["SELECT AES_DECRYPT(?, ?)", Base64.decode64(value), key]).first
36
- end
37
-
38
- private
39
-
40
- def legacy
41
- unless ENV['CRYPT_KEEPER_IGNORE_LEGACY_DEPRECATION']
42
- warn "[DEPRECATION] MySqlAes Legacy is now deprecated. Please see http://git.io/nXXOlg"
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,73 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module CryptKeeper::LogSubscriber
4
- describe MysqlAes do
5
- before do
6
- CryptKeeper.silence_logs = false
7
- end
8
-
9
- use_mysql
10
-
11
- context "AES encryption" do
12
- # Fire the ActiveSupport.on_load
13
- before do
14
- CryptKeeper::Provider::MysqlAesNew.new key: 'secret', salt: 'salt'
15
- end
16
-
17
- subject { ::ActiveRecord::LogSubscriber.new }
18
-
19
- let(:input_query) do
20
- "SELECT aes_encrypt('encrypt_value', 'encrypt_key'), aes_decrypt('decrypt_value', 'decrypt_key') FROM DUAL;"
21
- end
22
-
23
- let(:output_query) do
24
- "SELECT aes_encrypt([FILTERED]) FROM DUAL;"
25
- end
26
-
27
- let(:input_search_query) do
28
- "SELECT \"sensitive_data\".* FROM \"sensitive_data\" WHERE ((aes_decrypt('f'), 'tool') = 'blah')) AND secret = 'testing'"
29
- end
30
-
31
- let(:output_search_query) do
32
- "SELECT \"sensitive_data\".* FROM \"sensitive_data\" WHERE ((aes_decrypt([FILTERED]) AND secret = 'testing'"
33
- end
34
-
35
- it "filters aes functions" do
36
- subject.should_receive(:sql_without_mysql_aes) do |event|
37
- event.payload[:sql].should == output_query
38
- end
39
-
40
- subject.sql(ActiveSupport::Notifications::Event.new(:sql, 1, 1, 1, { sql: input_query }))
41
- end
42
-
43
- it "filters aes functions in lowercase" do
44
- subject.should_receive(:sql_without_mysql_aes) do |event|
45
- event.payload[:sql].should == output_query.downcase.gsub(/filtered/, 'FILTERED')
46
- end
47
-
48
- subject.sql(ActiveSupport::Notifications::Event.new(:sql, 1, 1, 1, { sql: input_query.downcase }))
49
- end
50
-
51
- it "filters aes functions when searching" do
52
- subject.should_receive(:sql_without_mysql_aes) do |event|
53
- event.payload[:sql].should == output_search_query
54
- end
55
-
56
- subject.sql(ActiveSupport::Notifications::Event.new(:sql, 1, 1, 1, { sql: input_search_query }))
57
- end
58
-
59
- it "forces string encodings" do
60
- string_encoding_query = "SELECT aes_encrypt('hi \255', 'test')"
61
- subject.sql(ActiveSupport::Notifications::Event.new(:sql, 1, 1, 1, { sql: string_encoding_query }))
62
- end
63
-
64
- it "skips logging if CryptKeeper.silence_logs is set" do
65
- CryptKeeper.silence_logs = true
66
-
67
- subject.should_not_receive(:sql_without_mysql_aes)
68
-
69
- subject.sql(ActiveSupport::Notifications::Event.new(:sql, 1, 1, 1, { sql: input_query }))
70
- end
71
- end
72
- end
73
- end
@@ -1,123 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module CryptKeeper::LogSubscriber
4
- describe PostgresPgp do
5
- before do
6
- CryptKeeper.silence_logs = false
7
- end
8
-
9
- use_postgres
10
-
11
- context "Symmetric encryption" do
12
- # Fire the ActiveSupport.on_load
13
- before do
14
- CryptKeeper::Provider::PostgresPgp.new key: 'secret'
15
- end
16
-
17
- subject { ::ActiveRecord::LogSubscriber.new }
18
-
19
- let(:input_query) do
20
- "SELECT pgp_sym_encrypt('encrypt_value', 'encrypt_key'), pgp_sym_decrypt('decrypt_value', 'decrypt_key') FROM DUAL;"
21
- end
22
-
23
- let(:output_query) do
24
- "SELECT encrypt([FILTERED]) FROM DUAL;"
25
- end
26
-
27
- let(:input_search_query) do
28
- "SELECT \"sensitive_data\".* FROM \"sensitive_data\" WHERE ((pgp_sym_decrypt('f'), 'tool') = 'blah')) AND secret = 'testing'"
29
- end
30
-
31
- let(:output_search_query) do
32
- "SELECT \"sensitive_data\".* FROM \"sensitive_data\" WHERE decrypt([FILTERED]) AND secret = 'testing'"
33
- end
34
-
35
- it "filters pgp functions" do
36
- subject.should_receive(:sql_without_postgres_pgp) do |event|
37
- event.payload[:sql].should == output_query
38
- end
39
-
40
- subject.sql(ActiveSupport::Notifications::Event.new(:sql, 1, 1, 1, { sql: input_query }))
41
- end
42
-
43
- it "filters pgp functions in lowercase" do
44
- subject.should_receive(:sql_without_postgres_pgp) do |event|
45
- event.payload[:sql].should == output_query.downcase.gsub(/filtered/, 'FILTERED')
46
- end
47
-
48
- subject.sql(ActiveSupport::Notifications::Event.new(:sql, 1, 1, 1, { sql: input_query.downcase }))
49
- end
50
-
51
- it "filters pgp functions when searching" do
52
- subject.should_receive(:sql_without_postgres_pgp) do |event|
53
- event.payload[:sql].should == output_search_query
54
- end
55
-
56
- subject.sql(ActiveSupport::Notifications::Event.new(:sql, 1, 1, 1, { sql: input_search_query }))
57
- end
58
-
59
- it "forces string encodings" do
60
- string_encoding_query = "SELECT pgp_sym_encrypt('hi \255', 'test')"
61
- subject.sql(ActiveSupport::Notifications::Event.new(:sql, 1, 1, 1, { sql: string_encoding_query }))
62
- end
63
-
64
- it "skips logging if CryptKeeper.silence_logs is set" do
65
- CryptKeeper.silence_logs = true
66
-
67
- subject.should_not_receive(:sql_without_postgres_pgp)
68
-
69
- subject.sql(ActiveSupport::Notifications::Event.new(:sql, 1, 1, 1, { sql: input_query }))
70
- end
71
- end
72
-
73
- context "Public key encryption" do
74
- let(:public_key) do
75
- IO.read(File.join(SPEC_ROOT, 'fixtures', 'public.asc'))
76
- end
77
-
78
- let(:private_key) do
79
- IO.read(File.join(SPEC_ROOT, 'fixtures', 'private.asc'))
80
- end
81
-
82
- # Fire the ActiveSupport.on_load
83
- before do
84
- CryptKeeper::Provider::PostgresPgpPublicKey.new key: 'secret', public_key: public_key, private_key: private_key
85
- end
86
-
87
- subject { ::ActiveRecord::LogSubscriber.new }
88
-
89
- let(:input_query) do
90
- "SELECT pgp_pub_encrypt('test', dearmor('#{public_key}
91
- '))"
92
- end
93
-
94
- let(:output_query) do
95
- "SELECT encrypt([FILTERED])"
96
- end
97
-
98
- it "filters pgp functions" do
99
- subject.should_receive(:sql_without_postgres_pgp) do |event|
100
- event.payload[:sql].should == output_query
101
- end
102
-
103
- subject.sql(ActiveSupport::Notifications::Event.new(:sql, 1, 1, 1, { sql: input_query }))
104
- end
105
-
106
- it "filters pgp functions in lowercase" do
107
- subject.should_receive(:sql_without_postgres_pgp) do |event|
108
- event.payload[:sql].should == output_query.downcase.gsub(/filtered/, 'FILTERED')
109
- end
110
-
111
- subject.sql(ActiveSupport::Notifications::Event.new(:sql, 1, 1, 1, { sql: input_query.downcase }))
112
- end
113
-
114
- it "skips logging if CryptKeeper.silence_logs is set" do
115
- CryptKeeper.silence_logs = true
116
-
117
- subject.should_not_receive(:sql_without_postgres_pgp)
118
-
119
- subject.sql(ActiveSupport::Notifications::Event.new(:sql, 1, 1, 1, { sql: input_query }))
120
- end
121
- end
122
- end
123
- end
@@ -1,169 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- module CryptKeeper
6
- describe Model do
7
- use_sqlite
8
-
9
- subject { create_model }
10
-
11
- after do
12
- CryptKeeper.stub_encryption = false
13
- end
14
-
15
- describe "#crypt_keeper" do
16
- context "Fields" do
17
- it "enables encryption for the given fields" do
18
- subject.crypt_keeper :storage, :secret, encryptor: :fake_encryptor
19
- subject.crypt_keeper_fields.should == [:storage, :secret]
20
- end
21
-
22
- it "raises an exception for missing field" do
23
- msg = "Column :none does not exist"
24
- subject.crypt_keeper :none, encryptor: :fake_encryptor
25
- expect { subject.new.save }.to raise_error(ArgumentError, msg)
26
- end
27
-
28
- it "raises an exception for non text fields" do
29
- msg = "Column :name must be of type 'text' to be used for encryption"
30
- subject.crypt_keeper :name, encryptor: :fake_encryptor
31
- expect { subject.new.save }.to raise_error(ArgumentError, msg)
32
- end
33
- end
34
-
35
- context "Options" do
36
- it "accepts the class name as a string" do
37
- subject.crypt_keeper :storage, :secret, key1: 1, key2: 2, encryptor: "FakeEncryptor"
38
- subject.send(:encryptor_klass).should == CryptKeeper::Provider::FakeEncryptor
39
- end
40
-
41
- it "raises an error on missing encryptor" do
42
- expect { subject.crypt_keeper :storage, :secret }.
43
- to raise_error(RuntimeError, /You must specify a valid encryptor/)
44
- end
45
- end
46
- end
47
-
48
- context "Encryption and Decryption" do
49
- let(:plain_text) { 'plain_text' }
50
- let(:cipher_text) { 'tooltxet_nialp' }
51
-
52
- subject { create_encrypted_model :storage, passphrase: 'tool', encryptor: :encryptor }
53
-
54
- it "encrypts the data" do
55
- CryptKeeper::Provider::Encryptor.any_instance.should_receive(:encrypt).with('testing')
56
- subject.create!(storage: 'testing')
57
- end
58
-
59
- it "decrypts the data" do
60
- record = subject.create!(storage: 'testing')
61
- CryptKeeper::Provider::Encryptor.any_instance.should_receive(:decrypt).at_least(1).times.with('toolgnitset')
62
- subject.find(record.id).storage
63
- end
64
-
65
- it "returns the plaintext on decrypt" do
66
- record = subject.create!(storage: 'testing')
67
- subject.find(record.id).storage.should == 'testing'
68
- end
69
-
70
- it "does not encrypt or decrypt nil" do
71
- data = subject.create!(storage: nil)
72
- data.storage.should be_nil
73
- end
74
-
75
- it "does not encrypt or decrypt empty strings" do
76
- data = subject.create!(storage: "")
77
- data.storage.should be_empty
78
- end
79
-
80
- it "converts numbers to strings" do
81
- data = subject.create!(storage: 1)
82
- data.reload.storage.should == "1"
83
- end
84
-
85
- it "does not decrypt when stubbing is enabled" do
86
- CryptKeeper.stub_encryption = true
87
- record = subject.create!(storage: "testing")
88
- CryptKeeper::Provider::Encryptor.any_instance.should_not_receive(:decrypt)
89
- subject.find(record.id).storage
90
- end
91
-
92
- it "does not decrypt when stubbing is enabled after model is created" do
93
- record = subject.create!(storage: "testing")
94
- CryptKeeper.stub_encryption = true
95
- CryptKeeper::Provider::Encryptor.any_instance.should_not_receive(:decrypt)
96
- subject.find(record.id).storage
97
- end
98
- end
99
-
100
- context "Search" do
101
- subject { create_encrypted_model :storage, passphrase: 'tool', encryptor: :search_encryptor }
102
-
103
- it "searches if supported" do
104
- expect { subject.search_by_plaintext(:storage, 'test1') }.to_not raise_error
105
- end
106
-
107
- it "complains about bad columns" do
108
- expect { subject.search_by_plaintext(:what, 'test1') }.to raise_error(/what is not a crypt_keeper field/)
109
- end
110
- end
111
-
112
- context "Encodings" do
113
- subject { create_encrypted_model :storage, key: 'tool', salt: 'salt', encryptor: :aes_new, encoding: 'utf-8' }
114
-
115
- it "forces the encoding on decrypt" do
116
- record = subject.create!(storage: 'Tromsø')
117
- record.reload
118
- expect(record.storage).to eql('Tromsø')
119
- end
120
-
121
- it "converts from other encodings" do
122
- plaintext = "\xC2\xA92011 AACR".force_encoding('ASCII-8BIT')
123
- record = subject.create!(storage: plaintext)
124
- record.reload
125
- expect(record.storage.encoding.name).to eql('UTF-8')
126
- end
127
- end
128
-
129
- context "Initial Table Encryption" do
130
- subject { create_encrypted_model :storage, key: 'tool', salt: 'salt', encryptor: :aes_new }
131
-
132
- before do
133
- subject.delete_all
134
- c = create_model
135
- 5.times { |i| c.create! storage: "testing#{i}" }
136
- end
137
-
138
- it "encrypts the table" do
139
- expect { subject.first(5).map(&:storage) }.to raise_error(OpenSSL::Cipher::CipherError)
140
- subject.encrypt_table!
141
- expect { subject.first(5).map(&:storage) }.not_to raise_error
142
- end
143
- end
144
-
145
- context "Table Decryption (Reverse of Initial Table Encryption)" do
146
- subject { create_encrypted_model :storage, key: 'tool', salt: 'salt', encryptor: :aes_new }
147
- let!(:storage_entries) { 5.times.map { |i| "testing#{i}" } }
148
-
149
- before do
150
- subject.delete_all
151
- storage_entries.each { |entry| subject.create! storage: entry}
152
- end
153
-
154
- it "decrypts the table" do
155
- subject.decrypt_table!
156
- expect( create_model.first(5).map(&:storage) ).to eq( storage_entries )
157
- end
158
- end
159
-
160
- context "Missing Attributes" do
161
- subject { create_encrypted_model :storage, key: 'tool', salt: 'salt', encryptor: :aes_new, encoding: 'utf-8' }
162
-
163
- it "doesn't attempt decryption of missing attributes" do
164
- subject.create!(storage: 'blah')
165
- expect { subject.select(:id).first }.to_not raise_error
166
- end
167
- end
168
- end
169
- end