README.md in blind_index-0.3.4 vs README.md in blind_index-0.3.5

- old
+ new

@@ -4,16 +4,24 @@ Designed for use with [attr_encrypted](https://github.com/attr-encrypted/attr_encrypted) Here’s a [full example](https://ankane.org/securing-user-emails-in-rails) of how to use it +Check out [this post](https://ankane.org/sensitive-data-rails) for more info on securing sensitive data with Rails + [![Build Status](https://travis-ci.org/ankane/blind_index.svg?branch=master)](https://travis-ci.org/ankane/blind_index) ## How It Works -We use [this approach](https://paragonie.com/blog/2017/05/building-searchable-encrypted-databases-with-php-and-sql) by Scott Arciszewski. To summarize, we compute a keyed hash of the sensitive data and store it in a column. To query, we apply the keyed hash function (PBKDF2-SHA256 by default) to the value we’re searching and then perform a database search. This results in performant queries for equality operations, while keeping the data secure from those without the key. +We use [this approach](https://paragonie.com/blog/2017/05/building-searchable-encrypted-databases-with-php-and-sql) by Scott Arciszewski. To summarize, we compute a keyed hash of the sensitive data and store it in a column. To query, we apply the keyed hash function to the value we’re searching and then perform a database search. This results in performant queries for exact matches. `LIKE` queries are not possible, but you can index expressions. +## Leakage + +An important consideration in searchable encryption is leakage, which is information an attacker can gain. Blind indexing leaks that rows have the same value. If you use this for a field like last name, an attacker can use frequency analysis to predict the values. In an active attack where an attacker can control the input values, they can learn which other values in the database match. + +Here’s a [great article](https://blog.cryptographyengineering.com/2019/02/11/attack-of-the-week-searchable-encryption-and-the-ever-expanding-leakage-function/) on leakage in searchable encryption. Blind indexing has the same leakage as deterministic encryption. + ## Installation Add this line to your application’s Gemfile: ```ruby @@ -29,30 +37,32 @@ ```ruby add_column :users, :encrypted_email_bidx, :string add_index :users, :encrypted_email_bidx ``` -And add to your model +Next, generate a key ```ruby -class User < ApplicationRecord - blind_index :email, key: [ENV["EMAIL_BLIND_INDEX_KEY"]].pack("H*") -end +BlindIndex.generate_key ``` -We use an environment variable to store the key as a hex-encoded string ([dotenv](https://github.com/bkeepers/dotenv) is great for this). [Here’s an explanation](https://ankane.org/encryption-keys) of why `pack` is used. *Do not commit it to source control.* This should be different than the key you use for encryption. You can generate a key in the Rails console with: +Store the key with your other secrets. This is typically Rails credentials or an environment variable ([dotenv](https://github.com/bkeepers/dotenv) is great for this). Be sure to use different keys in development and production, and be sure this is different than the key you use for encryption. Keys don’t need to be hex-encoded, but it’s often easier to store them this way. -```ruby -SecureRandom.hex(32) -``` +Here’s a key you can use in development -For development, you can use this: - ```sh EMAIL_BLIND_INDEX_KEY=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ``` +Add to your model + +```ruby +class User < ApplicationRecord + blind_index :email, key: ENV["EMAIL_BLIND_INDEX_KEY"] +end +``` + Backfill existing records ```ruby User.find_each do |user| user.compute_email_bidx @@ -210,12 +220,12 @@ And add to your model ```ruby class User < ApplicationRecord - blind_index :email, key: [ENV["EMAIL_BLIND_INDEX_KEY"]].pack("H*") - blind_index :email_v2, attribute: :email, key: [ENV["EMAIL_V2_BLIND_INDEX_KEY"]].pack("H*") + blind_index :email, key: ENV["EMAIL_BLIND_INDEX_KEY"] + blind_index :email_v2, attribute: :email, key: ENV["EMAIL_V2_BLIND_INDEX_KEY"] end ``` Backfill the data @@ -228,11 +238,11 @@ Then update your model ```ruby class User < ApplicationRecord - blind_index :email, bidx_attribute: :encrypted_email_v2_bidx, key: [ENV["EMAIL_V2_BLIND_INDEX_KEY"]].pack("H*") + blind_index :email, bidx_attribute: :encrypted_email_v2_bidx, key: ENV["EMAIL_V2_BLIND_INDEX_KEY"] # remove this line after dropping column self.ignored_columns = ["encrypted_email_bidx"] end ``` @@ -251,9 +261,15 @@ ``` Be sure to include the `inspect` at the end, or it won’t be encoded properly in YAML. ## Reference + +Set default options in an initializer with: + +```ruby +BlindIndex.default_options[:algorithm] = :argon2 +``` By default, blind indexes are encoded in Base64. Set a different encoding with: ```ruby class User < ApplicationRecord