blind_index 0.3.0 → 0.3.2

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: 651caa81ae68cdce70f5f0f83d3f2b1d0d2365c2c34765414d3ae0e523e5cdab
4
- data.tar.gz: 4a7d274aec56ba615a9569ab19c222b24d4a052166e8acdc0bfd2a5c65b4855b
3
+ metadata.gz: fe8410b6e972d6fe7aa37648396462b1e2a70358813e97db153d62ed5ac3fbad
4
+ data.tar.gz: 37d9baa7fb293ee2aa6e0a9fb5d253f8d0c7a83807dade72a8ac532825dc0220
5
5
  SHA512:
6
- metadata.gz: e169875cc33b23da106311fbbc41a2647bbd6b3abfd5e904f9ad7315ea71117d2dd69cc829ff16b222640397ba5576d12094fe2a62000e9c6962409dc6ccd478
7
- data.tar.gz: a7ee41ba497568c4580d98508c204f956aff7ed1ee04bb4452b78fe2897e98015ec3e9718bc6ef174b432912bfb7cf55bd94db79c45e14041ad057f04a49055f
6
+ metadata.gz: c647598d872e02b829377d5436442f0d929575722ee3330396c773d4dea556aabf74083e4868923fb597478df5648487fbfa26361eb6a341b1709dea3bb2e137
7
+ data.tar.gz: 1a9c501115e25cecf73e59ccb7ee5b23c96ccb01c81e4a62e48c1858546cf67a9c83f4f482cbf212ca2f38de559bbb668c39bf90a131ede9732eb4e390f45d3b
@@ -1,3 +1,13 @@
1
+ ## 0.3.2
2
+
3
+ - Added support for dynamic finders
4
+ - Added support for inherited models
5
+
6
+ ## 0.3.1
7
+
8
+ - Added scrypt and Argon2 algorithms
9
+ - Added `cost` option
10
+
1
11
  ## 0.3.0
2
12
 
3
13
  - Enforce secure key generation
@@ -1,4 +1,4 @@
1
- Copyright (c) 2017 Andrew Kane
1
+ Copyright (c) 2017-2018 Andrew Kane
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -42,7 +42,7 @@ class User < ApplicationRecord
42
42
  end
43
43
  ```
44
44
 
45
- We use environment variables to store the keys ([dotenv](https://github.com/bkeepers/dotenv) is great for this). *Do not commit them to source control.* Generate one key for encryption and one key for hashing. You can generate keys in the Rails console with:
45
+ We use environment variables to store the keys as hex-encoded strings ([dotenv](https://github.com/bkeepers/dotenv) is great for this). *Do not commit them to source control.* Generate one key for encryption and one key for hashing. You can generate keys in the Rails console with:
46
46
 
47
47
  ```ruby
48
48
  SecureRandom.hex(32)
@@ -143,11 +143,8 @@ end
143
143
 
144
144
  The default is `10000`. Changing this value requires you to recompute the blind index.
145
145
 
146
-
147
146
  ### scrypt
148
147
 
149
- :warning: *Not production ready yet*
150
-
151
148
  Add [scrypt](https://github.com/pbhogan/scrypt) to your Gemfile and use:
152
149
 
153
150
  ```ruby
@@ -156,9 +153,15 @@ class User < ApplicationRecord
156
153
  end
157
154
  ```
158
155
 
159
- ### Argon2
156
+ Set the cost parameters with:
160
157
 
161
- :warning: *Not production ready yet*
158
+ ```ruby
159
+ class User < ApplicationRecord
160
+ blind_index :email, algorithm: :scrypt, cost: {n: 4096, r: 8, p: 1}, ...
161
+ end
162
+ ```
163
+
164
+ ### Argon2
162
165
 
163
166
  Add [argon2](https://github.com/technion/ruby-argon2) to your Gemfile and use:
164
167
 
@@ -168,6 +171,14 @@ class User < ApplicationRecord
168
171
  end
169
172
  ```
170
173
 
174
+ Set the cost parameters with:
175
+
176
+ ```ruby
177
+ class User < ApplicationRecord
178
+ blind_index :email, algorithm: :argon2, cost: {t: 3, m: 12}, ...
179
+ end
180
+ ```
181
+
171
182
  ## Reference
172
183
 
173
184
  By default, blind indexes are encoded in Base64. Set a different encoding with:
@@ -194,7 +205,15 @@ We recommend rotating your key if it doesn’t meet this criteria. You can gener
194
205
  SecureRandom.hex(32)
195
206
  ```
196
207
 
197
- Set the new key and recompute the blind index.
208
+ Update your model to convert the hex key to binary.
209
+
210
+ ```ruby
211
+ class User < ApplicationRecord
212
+ blind_index :email, key: [ENV["EMAIL_BLIND_INDEX_KEY"]].pack("H*")
213
+ end
214
+ ```
215
+
216
+ And recompute the blind index.
198
217
 
199
218
  ```ruby
200
219
  User.find_each do |user|
data/Rakefile CHANGED
@@ -10,19 +10,47 @@ end
10
10
 
11
11
  task default: :test
12
12
 
13
- task :benchmark do
14
- require "securerandom"
15
- require "benchmark/ips"
16
- require "blind_index"
17
- require "scrypt"
18
- require "argon2"
19
-
20
- key = SecureRandom.random_bytes(32)
21
- value = "secret"
22
-
23
- Benchmark.ips do |x|
24
- x.report("pbkdf2_hmac") { BlindIndex.generate_bidx(value, key: key, algorithm: :pbkdf2_hmac) }
25
- x.report("scrypt") { BlindIndex.generate_bidx(value, key: key, algorithm: :scrypt) }
26
- x.report("argon2") { BlindIndex.generate_bidx(value, key: key, algorithm: :argon2) }
13
+ namespace :benchmark do
14
+ task :algorithms do
15
+ require "securerandom"
16
+ require "benchmark/ips"
17
+ require "blind_index"
18
+ require "scrypt"
19
+ require "argon2"
20
+
21
+ key = SecureRandom.random_bytes(32)
22
+ value = "secret"
23
+
24
+ Benchmark.ips do |x|
25
+ x.report("pbkdf2_hmac") { BlindIndex.generate_bidx(value, key: key, algorithm: :pbkdf2_hmac) }
26
+ x.report("scrypt") { BlindIndex.generate_bidx(value, key: key, algorithm: :scrypt) }
27
+ x.report("argon2") { BlindIndex.generate_bidx(value, key: key, algorithm: :argon2) }
28
+ end
29
+ end
30
+
31
+ task :queries do
32
+ require "benchmark/ips"
33
+ require "active_record"
34
+ require "blind_index"
35
+
36
+ ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
37
+
38
+ ActiveRecord::Migration.create_table :users do
39
+ end
40
+
41
+ ActiveRecord::Migration.create_table :cities do
42
+ end
43
+
44
+ class User < ActiveRecord::Base
45
+ blind_index :email
46
+ end
47
+
48
+ class City < ActiveRecord::Base
49
+ end
50
+
51
+ Benchmark.ips do |x|
52
+ x.report("no index") { City.where(id: 1).first }
53
+ x.report("index") { User.where(id: 1).first }
54
+ end
27
55
  end
28
56
  end
@@ -15,7 +15,8 @@ module BlindIndex
15
15
  iterations: 10000,
16
16
  algorithm: :pbkdf2_hmac,
17
17
  insecure_key: false,
18
- encode: true
18
+ encode: true,
19
+ cost: {}
19
20
  }
20
21
 
21
22
  def self.generate_bidx(value, key:, **options)
@@ -39,16 +40,22 @@ module BlindIndex
39
40
 
40
41
  # gist to compare algorithm results
41
42
  # https://gist.github.com/ankane/fe3ac63fbf1c4550ee12554c664d2b8c
43
+ cost_options = options[:cost]
44
+
42
45
  value =
43
46
  case algorithm
44
47
  when :scrypt
45
- # n, p (keep r at 8)
46
- SCrypt::Engine.scrypt(value.to_s, key, 4096, 8, 1, 32)
48
+ n = cost_options[:n] || 4096
49
+ r = cost_options[:r] || 8
50
+ cp = cost_options[:p] || 1
51
+ SCrypt::Engine.scrypt(value.to_s, key, n, r, cp, 32)
47
52
  when :argon2
48
- # t_cost, m_cost
49
- [Argon2::Engine.hash_argon2i(value.to_s, key, 2, 12)].pack("H*")
53
+ t = cost_options[:t] || 3
54
+ m = cost_options[:m] || 12
55
+ [Argon2::Engine.hash_argon2i(value.to_s, key, t, m)].pack("H*")
50
56
  when :pbkdf2_hmac
51
- OpenSSL::PKCS5.pbkdf2_hmac(value.to_s, key, options[:iterations], 32, "sha256")
57
+ iterations = cost_options[:iterations] || options[:iterations]
58
+ OpenSSL::PKCS5.pbkdf2_hmac(value.to_s, key, iterations, 32, "sha256")
52
59
  else
53
60
  raise BlindIndex::Error, "Unknown algorithm"
54
61
  end
@@ -77,6 +84,8 @@ ActiveSupport.on_load(:active_record) do
77
84
  ActiveRecord::PredicateBuilder.singleton_class.prepend(BlindIndex::Extensions::PredicateBuilder)
78
85
  end
79
86
 
87
+ ActiveRecord::DynamicMatchers::Method.prepend(BlindIndex::Extensions::DynamicMatchers)
88
+
80
89
  unless ActiveRecord::VERSION::STRING.start_with?("5.1.")
81
90
  ActiveRecord::Validations::UniquenessValidator.prepend(BlindIndex::Extensions::UniquenessValidator)
82
91
  end
@@ -67,5 +67,15 @@ module BlindIndex
67
67
  end
68
68
  end
69
69
  end
70
+
71
+ module DynamicMatchers
72
+ def valid?
73
+ attribute_names.all? { |name| model.columns_hash[name] || model.reflect_on_aggregation(name.to_sym) || blind_index?(name.to_sym) }
74
+ end
75
+
76
+ def blind_index?(name)
77
+ model.respond_to?(:blind_indexes) && model.blind_indexes[name]
78
+ end
79
+ end
70
80
  end
71
81
  end
@@ -1,6 +1,6 @@
1
1
  module BlindIndex
2
2
  module Model
3
- def blind_index(name, key: nil, iterations: nil, attribute: nil, expression: nil, bidx_attribute: nil, callback: true, algorithm: nil, insecure_key: nil, encode: nil)
3
+ def blind_index(name, key: nil, iterations: nil, attribute: nil, expression: nil, bidx_attribute: nil, callback: true, algorithm: nil, insecure_key: nil, encode: nil, cost: nil)
4
4
  iterations ||= 10000
5
5
  attribute ||= name
6
6
  bidx_attribute ||= :"encrypted_#{name}_bidx"
@@ -10,15 +10,24 @@ module BlindIndex
10
10
  method_name = :"compute_#{name}_bidx"
11
11
 
12
12
  class_eval do
13
- class << self
14
- def blind_indexes
15
- @blind_indexes ||= {}
16
- end unless method_defined?(:blind_indexes)
13
+ @blind_indexes ||= {}
14
+
15
+ unless respond_to?(:blind_indexes)
16
+ def self.blind_indexes
17
+ parent_indexes =
18
+ if superclass.respond_to?(:blind_indexes)
19
+ superclass.blind_indexes
20
+ else
21
+ {}
22
+ end
23
+
24
+ parent_indexes.merge(@blind_indexes || {})
25
+ end
17
26
  end
18
27
 
19
28
  raise BlindIndex::Error, "Duplicate blind index: #{name}" if blind_indexes[name]
20
29
 
21
- blind_indexes[name] = {
30
+ @blind_indexes[name] = {
22
31
  key: key,
23
32
  iterations: iterations,
24
33
  attribute: attribute,
@@ -26,9 +35,11 @@ module BlindIndex
26
35
  bidx_attribute: bidx_attribute,
27
36
  algorithm: algorithm,
28
37
  insecure_key: insecure_key,
29
- encode: encode
38
+ encode: encode,
39
+ cost: cost
30
40
  }.reject { |_, v| v.nil? }
31
41
 
42
+ # should have been named generate_#{name}_bidx
32
43
  define_singleton_method method_name do |value|
33
44
  BlindIndex.generate_bidx(value, blind_indexes[name])
34
45
  end
@@ -1,3 +1,3 @@
1
1
  module BlindIndex
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blind_index
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-03 00:00:00.000000000 Z
11
+ date: 2018-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport