README.md in blind_index-2.3.1 vs README.md in blind_index-2.3.2
- old
+ new
@@ -222,24 +222,34 @@
Finally, drop the old column.
## Key Separation
-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:
+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.
+You can get an individual key with:
+
```ruby
BlindIndex.index_key(table: "users", bidx_attribute: "email_bidx")
```
-And set it directly before renaming:
+To rename a table with blind indexes, use:
```ruby
class User < ApplicationRecord
- blind_index :email, key: ENV["USER_EMAIL_BLIND_INDEX_KEY"]
+ blind_index :email, key_table: "original_table"
end
```
+To rename a blind index column, use:
+
+```ruby
+class User < ApplicationRecord
+ blind_index :email, key_attribute: "original_column"
+end
+```
+
## Algorithm
Argon2id is used for best security. The default cost parameters are 3 iterations and 4 MB of memory. For `slow: true`, the cost parameters are 4 iterations and 32 MB of memory.
A number of other algorithms are [also supported](docs/Other-Algorithms.md). Unless you have specific reasons to use them, go with Argon2id.
@@ -344,10 +354,32 @@
class User < ApplicationRecord
blind_index :email, key: ENV["USER_EMAIL_BLIND_INDEX_KEY"]
end
```
+## Compatibility
+
+You can generate blind indexes from other languages as well. For Python, you can use [argon2-cffi](https://github.com/hynek/argon2-cffi).
+
+```python
+from argon2.low_level import Type, hash_secret_raw
+from base64 import b64encode
+
+key = '289737bab72fa97b1f4b081cef00d7b7d75034bcf3183c363feaf3e6441777bc'
+value = 'test@example.org'
+
+bidx = b64encode(hash_secret_raw(
+ secret=value.encode(),
+ salt=bytes.fromhex(key),
+ time_cost=3,
+ memory_cost=2**12,
+ parallelism=1,
+ hash_len=32,
+ type=Type.ID
+))
+```
+
## Alternatives
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:
1. You can keep encryption consistent for all fields (both searchable and non-searchable)
@@ -360,108 +392,9 @@
2.0.0 brings a number of improvements.
- Blind indexes are updated immediately instead of in a `before_validation` callback
- Better Lockbox integration - no need to generate a separate key
- There’s a new gem for Argon2 that has no dependencies and (officially) supports Windows
-
-### 1.0.0
-
-1.0.0 brings a number of improvements. Here are a few to be aware of:
-
-- Argon2id is the default algorithm for stronger security
-- You can use a master key instead of individual keys for each column
-- Columns no longer have an `encrypted_` prefix
-
-For existing fields, add:
-
-```ruby
-class User < ApplicationRecord
- blind_index :email, legacy: true
-end
-```
-
-#### Optional
-
-To rotate to new fields that use Argon2id and a master key, generate a master key:
-
-```ruby
-BlindIndex.generate_key
-```
-
-And set `ENV["BLIND_INDEX_MASTER_KEY"]` or `BlindIndex.master_key`.
-
-Add a new column without the `encrypted_` prefix:
-
-```ruby
-add_column :users, :email_bidx, :string
-add_index :users, :email_bidx # unique: true if needed
-```
-
-And add to your model
-
-```ruby
-class User < ApplicationRecord
- blind_index :email, key: ENV["USER_EMAIL_BLIND_INDEX_KEY"], legacy: true, rotate: {}
-end
-```
-
-> For more sensitive fields, use `rotate: {slow: true}`
-
-This will keep the new column synced going forward. Next, backfill the data:
-
-```ruby
-User.unscoped.where(email_bidx: nil).find_each do |user|
- user.compute_rotated_email_bidx
- user.save(validate: false)
-end
-```
-
-Then update your model
-
-```ruby
-class User < ApplicationRecord
- blind_index :email
-end
-```
-
-> For more sensitive fields, add `slow: true`
-
-Finally, drop the old column.
-
-### 0.3.0
-
-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.
-
-We recommend rotating your key if it doesn’t meet this criteria. You can generate a new key in the Rails console with:
-
-```ruby
-SecureRandom.hex(32)
-```
-
-Update your model to convert the hex key to binary.
-
-```ruby
-class User < ApplicationRecord
- blind_index :email, key: [ENV["USER_EMAIL_BLIND_INDEX_KEY"]].pack("H*")
-end
-```
-
-And recompute the blind index.
-
-```ruby
-User.unscoped.find_each do |user|
- user.compute_email_bidx
- user.save(validate: false)
-end
-```
-
-To continue without rotating, set:
-
-```ruby
-class User < ApplicationRecord
- blind_index :email, insecure_key: true
-end
-```
## History
View the [changelog](https://github.com/ankane/blind_index/blob/master/CHANGELOG.md)