blind_index 2.3.0 → 2.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: 89f2640c25eea46ce76f32e3f8c725744f356c1037bc719c7cf2e1ab2728a1ee
4
- data.tar.gz: 984cf9b1d682d5662129e0ce9dee0047c3c57fbbc6d2922913bc59c0024334dc
3
+ metadata.gz: 5a8f12336176bc78927ea8f645fa707e872db1a4523ee00ea5e43e5b6663db19
4
+ data.tar.gz: fb0eab6db99944ab6e249f26e2f5f01846127732d23443944a11e2d3bcd05b59
5
5
  SHA512:
6
- metadata.gz: 99d6f55c8664ba560ac4f7171a402eb6a18347d7be1bfb70425b8f506ba829c808a1e18fc26fda5d8eb7bb88ec7cdcce989e0aadd7e94c22cbfefc915f01150d
7
- data.tar.gz: b9df49cf70f1e62e2bc753c0dc065c5fb236b38962cc3bdd7d15d6a7068521aaacd051ac996a9fc05018c48a32b4ca84494f268abee9900b447d3fb107416063
6
+ metadata.gz: 170b3ce8ee37f46f930c9bc7a16d828bf86c2653d215b05b1d34c93d0f60f1cb6f246f201095be33cff78e2f1c8de440987177e55462f1f5c662fd9b4616ffc7
7
+ data.tar.gz: 35690b9711146af73d4dfc4d8b92d7f1562619d2a98212ce9c2d4f6edafc4a785ae2458c5455c12c2fb312d986b1fb0f4df34883987ec1a4840fa49436e3ff26
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 2.3.2 (2023-04-26)
2
+
3
+ - Added `key_table` and `key_attribute` options
4
+
5
+ ## 2.3.1 (2022-09-06)
6
+
7
+ - Fixed error with `backfill` when `bidx_attribute` is a symbol
8
+
1
9
  ## 2.3.0 (2022-01-16)
2
10
 
3
11
  - Added blind indexes to `filter_attributes`
data/README.md CHANGED
@@ -23,12 +23,12 @@ Here’s a [great article](https://blog.cryptographyengineering.com/2019/02/11/a
23
23
  Add this line to your application’s Gemfile:
24
24
 
25
25
  ```ruby
26
- gem 'blind_index'
26
+ gem "blind_index"
27
27
  ```
28
28
 
29
29
  ## Prep
30
30
 
31
- Your model should already be set up with Lockbox or attr_encrypted. The examples are for a `User` model with `encrypts :email` or `attr_encrypted :email`. See the full examples for [Lockbox](https://ankane.org/securing-user-emails-lockbox) and [attr_encrypted](https://ankane.org/securing-user-emails-in-rails) if needed.
31
+ Your model should already be set up with Lockbox or attr_encrypted. The examples are for a `User` model with `has_encrypted :email` or `attr_encrypted :email`. See the full examples for [Lockbox](https://ankane.org/securing-user-emails-lockbox) and [attr_encrypted](https://ankane.org/securing-user-emails-in-rails) if needed.
32
32
 
33
33
  Also, if you use attr_encrypted, [generate a key](#key-generation).
34
34
 
@@ -224,17 +224,27 @@ Finally, drop the old column.
224
224
 
225
225
  ## Key Separation
226
226
 
227
- The master key is used to generate unique keys for each blind index. This technique comes from [CipherSweet](https://ciphersweet.paragonie.com/internals/key-hierarchy). The table name and blind index column name are both used in this process. If you need to rename a table with blind indexes, or a blind index column itself, get the key:
227
+ The master key is used to generate unique keys for each blind index. This technique comes from [CipherSweet](https://ciphersweet.paragonie.com/internals/key-hierarchy). The table name and blind index column name are both used in this process.
228
+
229
+ You can get an individual key with:
228
230
 
229
231
  ```ruby
230
232
  BlindIndex.index_key(table: "users", bidx_attribute: "email_bidx")
231
233
  ```
232
234
 
233
- And set it directly before renaming:
235
+ To rename a table with blind indexes, use:
234
236
 
235
237
  ```ruby
236
238
  class User < ApplicationRecord
237
- blind_index :email, key: ENV["USER_EMAIL_BLIND_INDEX_KEY"]
239
+ blind_index :email, key_table: "original_table"
240
+ end
241
+ ```
242
+
243
+ To rename a blind index column, use:
244
+
245
+ ```ruby
246
+ class User < ApplicationRecord
247
+ blind_index :email, key_attribute: "original_column"
238
248
  end
239
249
  ```
240
250
 
@@ -346,6 +356,28 @@ class User < ApplicationRecord
346
356
  end
347
357
  ```
348
358
 
359
+ ## Compatibility
360
+
361
+ You can generate blind indexes from other languages as well. For Python, you can use [argon2-cffi](https://github.com/hynek/argon2-cffi).
362
+
363
+ ```python
364
+ from argon2.low_level import Type, hash_secret_raw
365
+ from base64 import b64encode
366
+
367
+ key = '289737bab72fa97b1f4b081cef00d7b7d75034bcf3183c363feaf3e6441777bc'
368
+ value = 'test@example.org'
369
+
370
+ bidx = b64encode(hash_secret_raw(
371
+ secret=value.encode(),
372
+ salt=bytes.fromhex(key),
373
+ time_cost=3,
374
+ memory_cost=2**12,
375
+ parallelism=1,
376
+ hash_len=32,
377
+ type=Type.ID
378
+ ))
379
+ ```
380
+
349
381
  ## Alternatives
350
382
 
351
383
  One alternative to blind indexing is to use a deterministic encryption scheme, like [AES-SIV](https://github.com/miscreant/miscreant). In this approach, the encrypted data will be the same for matches. We recommend blind indexing over deterministic encryption because:
@@ -363,105 +395,6 @@ One alternative to blind indexing is to use a deterministic encryption scheme, l
363
395
  - Better Lockbox integration - no need to generate a separate key
364
396
  - There’s a new gem for Argon2 that has no dependencies and (officially) supports Windows
365
397
 
366
- ### 1.0.0
367
-
368
- 1.0.0 brings a number of improvements. Here are a few to be aware of:
369
-
370
- - Argon2id is the default algorithm for stronger security
371
- - You can use a master key instead of individual keys for each column
372
- - Columns no longer have an `encrypted_` prefix
373
-
374
- For existing fields, add:
375
-
376
- ```ruby
377
- class User < ApplicationRecord
378
- blind_index :email, legacy: true
379
- end
380
- ```
381
-
382
- #### Optional
383
-
384
- To rotate to new fields that use Argon2id and a master key, generate a master key:
385
-
386
- ```ruby
387
- BlindIndex.generate_key
388
- ```
389
-
390
- And set `ENV["BLIND_INDEX_MASTER_KEY"]` or `BlindIndex.master_key`.
391
-
392
- Add a new column without the `encrypted_` prefix:
393
-
394
- ```ruby
395
- add_column :users, :email_bidx, :string
396
- add_index :users, :email_bidx # unique: true if needed
397
- ```
398
-
399
- And add to your model
400
-
401
- ```ruby
402
- class User < ApplicationRecord
403
- blind_index :email, key: ENV["USER_EMAIL_BLIND_INDEX_KEY"], legacy: true, rotate: {}
404
- end
405
- ```
406
-
407
- > For more sensitive fields, use `rotate: {slow: true}`
408
-
409
- This will keep the new column synced going forward. Next, backfill the data:
410
-
411
- ```ruby
412
- User.unscoped.where(email_bidx: nil).find_each do |user|
413
- user.compute_rotated_email_bidx
414
- user.save(validate: false)
415
- end
416
- ```
417
-
418
- Then update your model
419
-
420
- ```ruby
421
- class User < ApplicationRecord
422
- blind_index :email
423
- end
424
- ```
425
-
426
- > For more sensitive fields, add `slow: true`
427
-
428
- Finally, drop the old column.
429
-
430
- ### 0.3.0
431
-
432
- This version introduces a breaking change to enforce secure key generation. An error is thrown if your blind index key isn’t both binary and 32 bytes.
433
-
434
- We recommend rotating your key if it doesn’t meet this criteria. You can generate a new key in the Rails console with:
435
-
436
- ```ruby
437
- SecureRandom.hex(32)
438
- ```
439
-
440
- Update your model to convert the hex key to binary.
441
-
442
- ```ruby
443
- class User < ApplicationRecord
444
- blind_index :email, key: [ENV["USER_EMAIL_BLIND_INDEX_KEY"]].pack("H*")
445
- end
446
- ```
447
-
448
- And recompute the blind index.
449
-
450
- ```ruby
451
- User.unscoped.find_each do |user|
452
- user.compute_email_bidx
453
- user.save(validate: false)
454
- end
455
- ```
456
-
457
- To continue without rotating, set:
458
-
459
- ```ruby
460
- class User < ApplicationRecord
461
- blind_index :email, insecure_key: true
462
- end
463
- ```
464
-
465
398
  ## History
466
399
 
467
400
  View the [changelog](https://github.com/ankane/blind_index/blob/master/CHANGELOG.md)
@@ -21,8 +21,8 @@ module BlindIndex
21
21
  # modify in-place
22
22
  def filter_columns!(columns)
23
23
  columns = Array(columns).map(&:to_s)
24
- blind_indexes.select! { |_, v| columns.include?(v[:bidx_attribute]) }
25
- bad_columns = columns - blind_indexes.map { |_, v| v[:bidx_attribute] }
24
+ blind_indexes.select! { |_, v| columns.include?(v[:bidx_attribute].to_s) }
25
+ bad_columns = columns - blind_indexes.map { |_, v| v[:bidx_attribute].to_s }
26
26
  raise ArgumentError, "Bad column: #{bad_columns.first}" if bad_columns.any?
27
27
  end
28
28
 
@@ -10,7 +10,7 @@ module BlindIndex
10
10
  # check here so we validate rotate options as well
11
11
  unknown_keywords = options.keys - [:algorithm, :attribute, :bidx_attribute,
12
12
  :callback, :cost, :encode, :expression, :insecure_key, :iterations, :key,
13
- :legacy, :master_key, :size, :slow, :version]
13
+ :key_attribute, :key_table, :legacy, :master_key, :size, :slow, :version]
14
14
  raise ArgumentError, "unknown keywords: #{unknown_keywords.join(", ")}" if unknown_keywords.any?
15
15
 
16
16
  attribute = options[:attribute] || name
@@ -33,7 +33,7 @@ module BlindIndex
33
33
  class_method_name = :"generate_#{name}_bidx"
34
34
 
35
35
  key = options[:key]
36
- key ||= -> { BlindIndex.index_key(table: try(:table_name) || collection_name.to_s, bidx_attribute: bidx_attribute, master_key: options[:master_key], encode: false) }
36
+ key ||= -> { BlindIndex.index_key(table: options[:key_table] || try(:table_name) || collection_name.to_s, bidx_attribute: options[:key_attribute] || bidx_attribute, master_key: options[:master_key], encode: false) }
37
37
 
38
38
  class_eval do
39
39
  activerecord = defined?(ActiveRecord) && self < ActiveRecord::Base
@@ -1,3 +1,3 @@
1
1
  module BlindIndex
2
- VERSION = "2.3.0"
2
+ VERSION = "2.3.2"
3
3
  end
data/lib/blind_index.rb CHANGED
@@ -6,10 +6,10 @@ require "argon2/kdf"
6
6
  require "openssl"
7
7
 
8
8
  # modules
9
- require "blind_index/backfill"
10
- require "blind_index/key_generator"
11
- require "blind_index/model"
12
- require "blind_index/version"
9
+ require_relative "blind_index/backfill"
10
+ require_relative "blind_index/key_generator"
11
+ require_relative "blind_index/model"
12
+ require_relative "blind_index/version"
13
13
 
14
14
  module BlindIndex
15
15
  class Error < StandardError; end
@@ -137,7 +137,7 @@ module BlindIndex
137
137
  end
138
138
 
139
139
  ActiveSupport.on_load(:active_record) do
140
- require "blind_index/extensions"
140
+ require_relative "blind_index/extensions"
141
141
  extend BlindIndex::Model
142
142
 
143
143
  ActiveRecord::TableMetadata.prepend(BlindIndex::Extensions::TableMetadata)
@@ -147,7 +147,7 @@ ActiveSupport.on_load(:active_record) do
147
147
  end
148
148
 
149
149
  ActiveSupport.on_load(:mongoid) do
150
- require "blind_index/mongoid"
150
+ require_relative "blind_index/mongoid"
151
151
  Mongoid::Document::ClassMethods.include(BlindIndex::Model)
152
152
  Mongoid::Criteria.prepend(BlindIndex::Mongoid::Criteria)
153
153
  Mongoid::Validatable::UniquenessValidator.prepend(BlindIndex::Mongoid::UniquenessValidator)
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: 2.3.0
4
+ version: 2.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-16 00:00:00.000000000 Z
11
+ date: 2023-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -73,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
73
  - !ruby/object:Gem::Version
74
74
  version: '0'
75
75
  requirements: []
76
- rubygems_version: 3.3.3
76
+ rubygems_version: 3.4.10
77
77
  signing_key:
78
78
  specification_version: 4
79
79
  summary: Securely search encrypted database fields