crypt_keeper 0.22.0 → 1.0.0.beta1

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.
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