crypt_keeper 2.0.0.rc2 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d2c48e454fad3b2d938bbcabb028983954c991479524a7240acb772b46e37b1
4
- data.tar.gz: 907dd02f441238eaa0a3a77c8be9dd5f936a615630bc96c6759930f74da99f06
3
+ metadata.gz: a090653644f2d7aba77cd684309d1a720f3a956a8568d5c03f06985ca8b608ff
4
+ data.tar.gz: a61221ebb211944e2f2695f223da199c905e6ae70ce681aa3d4c909e61801e6c
5
5
  SHA512:
6
- metadata.gz: d9a292f9d37a60cf43a9f27c4981e6bfbfd7f603e5f53cbc08932103d9fd61c3c83c141ba56d67b26b7925a7f6d46b87885a9d595ce0b7eaa37ca7e846ee24ca
7
- data.tar.gz: 61def2dfc5d5deadb6b9f667d2b8490cc357e4956059abf45fedc7adae856a95d5f90fe2364da402dbcd0d00b791205e1a9222ce53c190b42b6fa92d0c65bb91
6
+ metadata.gz: 2eb493363aad423a7ea2131056b48e0c5be36ee4c61f46e1bc3dda20dba6cd70ac72e2f2a1741ed004a5e35c6b2526faaeaab5b777fee9f768a9ddd5e4a97db2
7
+ data.tar.gz: dd4f889755d15483c9777199a3e332d0d66b8845355179d9fbd4b0dc26e8524ad54cbe4df6a88882d7669d0f27c9bb37fc2473379ed2ada777a897ff41f5ca57
data/.travis.yml CHANGED
@@ -1,20 +1,60 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 2.2.7
5
- - 2.3.4
6
- - 2.4.1
4
+ - 2.2.10
5
+ - 2.3.8
6
+ - 2.4.5
7
+ - 2.5.3
8
+ - 2.6.4
9
+ - 2.7.2
7
10
 
8
11
  gemfile:
9
12
  - gemfiles/activerecord_4_2.gemfile
10
13
  - gemfiles/activerecord_5_0.gemfile
11
14
  - gemfiles/activerecord_5_1.gemfile
12
15
  - gemfiles/activerecord_5_2.gemfile
16
+ - gemfiles/activerecord_6_0.gemfile
17
+ - gemfiles/activerecord_6_1.gemfile
18
+
13
19
 
14
- addons:
15
- postgresql: 9.3
20
+ matrix:
21
+ exclude:
22
+ - rvm: 2.2.10
23
+ gemfile: gemfiles/activerecord_5_0.gemfile
24
+ - rvm: 2.2.10
25
+ gemfile: gemfiles/activerecord_5_1.gemfile
26
+ - rvm: 2.2.10
27
+ gemfile: gemfiles/activerecord_6_0.gemfile
28
+ - rvm: 2.2.10
29
+ gemfile: gemfiles/activerecord_6_1.gemfile
30
+ - rvm: 2.3.8
31
+ gemfile: gemfiles/activerecord_5_0.gemfile
32
+ - rvm: 2.3.8
33
+ gemfile: gemfiles/activerecord_5_1.gemfile
34
+ - rvm: 2.3.8
35
+ gemfile: gemfiles/activerecord_6_0.gemfile
36
+ - rvm: 2.3.8
37
+ gemfile: gemfiles/activerecord_6_1.gemfile
38
+ - rvm: 2.4.5
39
+ gemfile: gemfiles/activerecord_5_0.gemfile
40
+ - rvm: 2.4.5
41
+ gemfile: gemfiles/activerecord_5_1.gemfile
42
+ - rvm: 2.4.5
43
+ gemfile: gemfiles/activerecord_6_0.gemfile
44
+ - rvm: 2.4.5
45
+ gemfile: gemfiles/activerecord_6_1.gemfile
46
+ - rvm: 2.5.3
47
+ gemfile: gemfiles/activerecord_5_0.gemfile
48
+ - rvm: 2.5.3
49
+ gemfile: gemfiles/activerecord_5_1.gemfile
50
+ - rvm: 2.6.4
51
+ gemfile: gemfiles/activerecord_5_0.gemfile
52
+ - rvm: 2.6.4
53
+ gemfile: gemfiles/activerecord_5_1.gemfile
16
54
 
17
- sudo: false
55
+ services:
56
+ - postgresql
57
+ - mysql
18
58
 
19
59
  before_script:
20
60
  - cp spec/default.database.yml spec/database.yml
@@ -22,7 +62,8 @@ before_script:
22
62
  - psql crypt_keeper_providers -c 'CREATE EXTENSION IF NOT EXISTS pgcrypto;' -U postgres
23
63
  - mysql -e 'CREATE DATABASE crypt_keeper_providers'
24
64
 
25
- branches: master
65
+ branches:
66
+ - master
26
67
 
27
68
  notifications:
28
69
  email:
data/Appraisals CHANGED
@@ -1,11 +1,17 @@
1
1
  appraise "activerecord_4_2" do
2
2
  gem "activerecord", "~> 4.2.0"
3
3
  gem "activesupport", "~> 4.2.0"
4
+ gem "sqlite3", "~> 1.3.0"
5
+
6
+ # otherwise you get "undefined method `new' for BigDecimal:Class" in Ruby 2.7
7
+ gem "bigdecimal", "1.3.5"
4
8
  end
5
9
 
6
10
  appraise "activerecord_5_0" do
7
11
  gem "activerecord", "~> 5.0.0"
8
12
  gem "activesupport", "~> 5.0.0"
13
+
14
+ gem "sqlite3", "~> 1.3.6"
9
15
  end
10
16
 
11
17
  appraise "activerecord_5_1" do
@@ -17,3 +23,20 @@ appraise "activerecord_5_2" do
17
23
  gem "activerecord", "~> 5.2.0"
18
24
  gem "activesupport", "~> 5.2.0"
19
25
  end
26
+
27
+ appraise "activerecord_6_0" do
28
+ gem "activerecord", "~> 6.0.0"
29
+ gem "activesupport", "~> 6.0.0"
30
+ end
31
+
32
+ appraise "activerecord_6_1" do
33
+ gem "activerecord", "~> 6.1.0"
34
+ gem "activesupport", "~> 6.1.0"
35
+ gem "pg", "~> 1.1"
36
+ end
37
+
38
+ appraise "activerecord_7_0" do
39
+ gem "activerecord", "~> 7.0"
40
+ gem "activesupport", "~> 7.0"
41
+ gem "pg", "~> 1.1"
42
+ end
data/README.md CHANGED
@@ -151,10 +151,10 @@ Searching ciphertext is a complex problem that varies depending on the encryptio
151
151
  * ActiveSupport's MessageEncryptor uses a random initialization vector when generating keys. The same plaintext encrypted multiple times will have different output each time for the ciphertext. Since this is the case, it is not possible to search leveraging the database. Database rows will need to be filtered in memory. It is suggested that you use a scope or ActiveRecord batches to narrow the results before seaching them.
152
152
 
153
153
  * Mysql AES
154
- * Surprisingly, MySQL's implementation of AES does not use a random initialization vector. The column containing the ciphertext can be indexed and searched quickly.
154
+ * Surprisingly, MySQL's implementation of AES does not use a random initialization vector. The column containing the ciphertext can be indexed and searched quickly.
155
155
 
156
156
  * PostgresSQL PGP
157
- * PGP also uses a random initialization vector which means it generates unique output each time you encrypt plaintext. Although the database can be searched by performing row level decryption and comparing the plaintext, it will not be able to use an index. A scope or batch is suggested when searching.
157
+ * PGP also uses a random initialization vector which means it generates unique output each time you encrypt plaintext. Although the database can be searched by performing row level decryption and comparing the plaintext, it will not be able to use an index. A scope or batch is suggested when searching.
158
158
 
159
159
  ## How the search interface is used
160
160
 
data/crypt_keeper.gemspec CHANGED
@@ -18,13 +18,13 @@ Gem::Specification.new do |gem|
18
18
 
19
19
  gem.post_install_message = "WARNING: CryptKeeper 2.0 contains breaking changes and may require you to reencrypt your data! Please view the README at https://github.com/jmazzi/crypt_keeper for more information."
20
20
 
21
- gem.add_runtime_dependency 'activerecord', '>= 4.2', '< 5.3'
22
- gem.add_runtime_dependency 'activesupport', '>= 4.2', '< 5.3'
21
+ gem.add_runtime_dependency 'activerecord', '>= 4.2', '<= 7'
22
+ gem.add_runtime_dependency 'activesupport', '>= 4.2', '<= 7'
23
23
 
24
24
  gem.add_development_dependency 'rspec', '~> 3.5.0'
25
25
  gem.add_development_dependency 'guard', '~> 2.6.1'
26
26
  gem.add_development_dependency 'guard-rspec', '~> 4.2.9'
27
- gem.add_development_dependency 'rake', '~> 10.3.1'
27
+ gem.add_development_dependency 'rake'
28
28
  gem.add_development_dependency 'rb-fsevent', '~> 0.9.1'
29
29
  gem.add_development_dependency 'coveralls'
30
30
  gem.add_development_dependency 'appraisal', '~> 2.1.0'
@@ -35,7 +35,7 @@ Gem::Specification.new do |gem|
35
35
  gem.add_development_dependency 'activerecord-jdbcpostgresql-adapter'
36
36
  gem.add_development_dependency 'activerecord-jdbcmysql-adapter'
37
37
  else
38
- gem.add_development_dependency 'sqlite3'
38
+ gem.add_development_dependency 'sqlite3', '>= 1.3.3', '< 1.5'
39
39
  gem.add_development_dependency 'pg', '~> 0.18.0'
40
40
  gem.add_development_dependency 'mysql2', '>= 0.3.13', '< 0.6.0'
41
41
  end
@@ -4,6 +4,7 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "activerecord", "~> 4.2.0"
6
6
  gem "activesupport", "~> 4.2.0"
7
- gem "mysql2", ">= 0.3.13", "< 0.5"
7
+ gem "sqlite3", "~> 1.3.0"
8
+ gem "bigdecimal", "1.3.5"
8
9
 
9
10
  gemspec :path => "../"
@@ -4,6 +4,6 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "activerecord", "~> 5.0.0"
6
6
  gem "activesupport", "~> 5.0.0"
7
- gem "mysql2", ">= 0.3.18", "< 0.6.0"
7
+ gem "sqlite3", "~> 1.3.6"
8
8
 
9
9
  gemspec :path => "../"
@@ -4,6 +4,5 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "activerecord", "~> 5.1.0"
6
6
  gem "activesupport", "~> 5.1.0"
7
- gem "mysql2", ">= 0.3.18", "< 0.6.0"
8
7
 
9
8
  gemspec :path => "../"
@@ -4,6 +4,5 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "activerecord", "~> 5.2.0"
6
6
  gem "activesupport", "~> 5.2.0"
7
- gem "mysql2", ">= 0.4.4", "< 0.6.0"
8
7
 
9
8
  gemspec :path => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 6.0.0"
6
+ gem "activesupport", "~> 6.0.0"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 6.1.0"
6
+ gem "activesupport", "~> 6.1.0"
7
+ gem "pg", "~> 1.1"
8
+
9
+ gemspec :path => "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 7.0"
6
+ gem "activesupport", "~> 7.0"
7
+ gem "pg", "~> 1.1"
8
+
9
+ gemspec :path => "../"
@@ -12,6 +12,10 @@ module CryptKeeper
12
12
  def escape_and_execute_sql(query, new_transaction: false)
13
13
  query = ::ActiveRecord::Base.send :sanitize_sql_array, query
14
14
 
15
+ # force binary encoding to avoid "invalid byte sequence in UTF-8" errors
16
+ # when we send binary AES keys (f.ex) to the database
17
+ query = query.b if query.respond_to?(:b)
18
+
15
19
  if CryptKeeper.silence_logs?
16
20
  ::ActiveRecord::Base.logger.silence do
17
21
  execute_sql(query, new_transaction: new_transaction)
@@ -42,8 +42,14 @@ module CryptKeeper
42
42
  end
43
43
 
44
44
  def search(records, field, criteria)
45
- records.where("(pgp_sym_decrypt(cast(\"#{field}\" AS bytea), ?) = ?)",
46
- key, criteria)
45
+ if criteria.present?
46
+ records
47
+ .where.not("TRIM(BOTH FROM \"#{field}\") = ?", "")
48
+ .where("(pgp_sym_decrypt(cast(\"#{field}\" AS bytea), ?) = ?)",
49
+ key, criteria)
50
+ else
51
+ records.where(field => criteria)
52
+ end
47
53
  end
48
54
 
49
55
  private
@@ -1,3 +1,3 @@
1
1
  module CryptKeeper
2
- VERSION = "2.0.0.rc2"
2
+ VERSION = "2.3.0"
3
3
  end
@@ -25,8 +25,7 @@ describe CryptKeeper::Model do
25
25
  end
26
26
 
27
27
  it "allows binary as a valid type" do
28
- subject.crypt_keeper :storage, encryptor: :fake_encryptor
29
- allow(subject.columns_hash['storage']).to receive(:type).and_return(:binary)
28
+ subject.crypt_keeper :storage_binary, encryptor: :fake_encryptor
30
29
  expect(subject.new.save).to be_truthy
31
30
  end
32
31
 
@@ -55,6 +54,7 @@ describe CryptKeeper::Model do
55
54
  end
56
55
  end
57
56
 
57
+
58
58
  context "Encryption and Decryption" do
59
59
  let(:plain_text) { 'plain_text' }
60
60
  let(:cipher_text) { 'tooltxet_nialp' }
@@ -105,6 +105,21 @@ describe CryptKeeper::Model do
105
105
  expect_any_instance_of(CryptKeeper::Provider::Encryptor).to_not receive(:decrypt)
106
106
  subject.find(record.id).storage
107
107
  end
108
+
109
+ context "with a binary database field" do
110
+ subject { create_encrypted_model :storage_binary, passphrase: 'tool', encryptor: :encryptor }
111
+
112
+ it "encrypts the data" do
113
+ expect_any_instance_of(CryptKeeper::Provider::Encryptor).to receive(:encrypt).with('testing')
114
+ subject.create!(storage_binary: 'testing')
115
+ end
116
+
117
+ it "decrypts the data" do
118
+ record = subject.create!(storage_binary: 'testing')
119
+ expect_any_instance_of(CryptKeeper::Provider::Encryptor).to receive(:decrypt).at_least(1).times.with('toolgnitset')
120
+ subject.find(record.id).storage_binary
121
+ end
122
+ end
108
123
  end
109
124
 
110
125
  context "Search" do
@@ -64,6 +64,42 @@ describe CryptKeeper::Provider::PostgresPgp do
64
64
  match = subject.create!(storage: 'blah')
65
65
  expect(subject.search_by_plaintext(:storage, 'blah').first).to eq(match)
66
66
  end
67
+
68
+ it "successfully accesses result when the data has empty strings and nil" do
69
+ subject.create!(storage: nil)
70
+ subject.create!(storage: '')
71
+ subject.create!(storage: ' ')
72
+ match = subject.create!(storage: 'blah')
73
+
74
+ results = subject.search_by_plaintext(:storage, 'blah')
75
+
76
+ expect(results).to match_array([match])
77
+ end
78
+
79
+ it "finds an empty string" do
80
+ subject.create!(storage: nil)
81
+ subject.create!(storage: 'blah')
82
+ match = subject.create!(storage: '')
83
+
84
+ expect(subject.search_by_plaintext(:storage, '')).to match_array([match])
85
+ end
86
+
87
+ it "finds the empty string with the right number of spaces" do
88
+ subject.create!(storage: '')
89
+ match = subject.create!(storage: ' ')
90
+
91
+ results = subject.search_by_plaintext(:storage, ' ')
92
+
93
+ expect(results).to match_array([match])
94
+ end
95
+
96
+ it "finds nil results" do
97
+ subject.create!(storage: '')
98
+ subject.create!(storage: 'blah')
99
+ match = subject.create!(storage: nil)
100
+
101
+ expect(subject.search_by_plaintext(:storage, nil)).to match_array([match])
102
+ end
67
103
  end
68
104
 
69
105
  describe "Custom pgcrypto options" do
data/spec/spec_helper.rb CHANGED
@@ -14,7 +14,11 @@ RSpec.configure do |config|
14
14
  config.filter_run :focus
15
15
 
16
16
  config.after :each do
17
- ActiveRecord::Base.descendants.each do |model|
17
+ descendants = ActiveRecord::Base.descendants.delete_if do |descendant|
18
+ descendant.to_s.include?("SchemaMigration")
19
+ end
20
+
21
+ descendants.each do |model|
18
22
  model.method(:delete_all).call
19
23
  end
20
24
  end
@@ -18,6 +18,7 @@ module CryptKeeper
18
18
  create_table :sensitive_data, :force => true do |t|
19
19
  t.column :name, :string
20
20
  t.column :storage, :text
21
+ t.column :storage_binary, :binary
21
22
  t.column :secret, :text
22
23
  end
23
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crypt_keeper
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc2
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Mazzi
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-10 00:00:00.000000000 Z
11
+ date: 2021-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -17,9 +17,9 @@ dependencies:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '4.2'
20
- - - "<"
20
+ - - "<="
21
21
  - !ruby/object:Gem::Version
22
- version: '5.3'
22
+ version: '7'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -27,9 +27,9 @@ dependencies:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
29
  version: '4.2'
30
- - - "<"
30
+ - - "<="
31
31
  - !ruby/object:Gem::Version
32
- version: '5.3'
32
+ version: '7'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: activesupport
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -37,9 +37,9 @@ dependencies:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
39
  version: '4.2'
40
- - - "<"
40
+ - - "<="
41
41
  - !ruby/object:Gem::Version
42
- version: '5.3'
42
+ version: '7'
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
@@ -47,9 +47,9 @@ dependencies:
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
49
  version: '4.2'
50
- - - "<"
50
+ - - "<="
51
51
  - !ruby/object:Gem::Version
52
- version: '5.3'
52
+ version: '7'
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: rspec
55
55
  requirement: !ruby/object:Gem::Requirement
@@ -96,16 +96,16 @@ dependencies:
96
96
  name: rake
97
97
  requirement: !ruby/object:Gem::Requirement
98
98
  requirements:
99
- - - "~>"
99
+ - - ">="
100
100
  - !ruby/object:Gem::Version
101
- version: 10.3.1
101
+ version: '0'
102
102
  type: :development
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
105
105
  requirements:
106
- - - "~>"
106
+ - - ">="
107
107
  - !ruby/object:Gem::Version
108
- version: 10.3.1
108
+ version: '0'
109
109
  - !ruby/object:Gem::Dependency
110
110
  name: rb-fsevent
111
111
  requirement: !ruby/object:Gem::Requirement
@@ -154,14 +154,20 @@ dependencies:
154
154
  requirements:
155
155
  - - ">="
156
156
  - !ruby/object:Gem::Version
157
- version: '0'
157
+ version: 1.3.3
158
+ - - "<"
159
+ - !ruby/object:Gem::Version
160
+ version: '1.5'
158
161
  type: :development
159
162
  prerelease: false
160
163
  version_requirements: !ruby/object:Gem::Requirement
161
164
  requirements:
162
165
  - - ">="
163
166
  - !ruby/object:Gem::Version
164
- version: '0'
167
+ version: 1.3.3
168
+ - - "<"
169
+ - !ruby/object:Gem::Version
170
+ version: '1.5'
165
171
  - !ruby/object:Gem::Dependency
166
172
  name: pg
167
173
  requirement: !ruby/object:Gem::Requirement
@@ -217,6 +223,9 @@ files:
217
223
  - gemfiles/activerecord_5_0.gemfile
218
224
  - gemfiles/activerecord_5_1.gemfile
219
225
  - gemfiles/activerecord_5_2.gemfile
226
+ - gemfiles/activerecord_6_0.gemfile
227
+ - gemfiles/activerecord_6_1.gemfile
228
+ - gemfiles/activerecord_7_0.gemfile
220
229
  - lib/crypt_keeper.rb
221
230
  - lib/crypt_keeper/helper.rb
222
231
  - lib/crypt_keeper/log_subscriber/mysql_aes.rb
@@ -261,13 +270,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
261
270
  version: '0'
262
271
  required_rubygems_version: !ruby/object:Gem::Requirement
263
272
  requirements:
264
- - - ">"
273
+ - - ">="
265
274
  - !ruby/object:Gem::Version
266
- version: 1.3.1
275
+ version: '0'
267
276
  requirements: []
268
- rubyforge_project:
269
- rubygems_version: 2.7.6
270
- signing_key:
277
+ rubygems_version: 3.1.4
278
+ signing_key:
271
279
  specification_version: 4
272
280
  summary: Transparent ActiveRecord encryption
273
281
  test_files: