README.md in blind_index-2.1.0 vs README.md in blind_index-2.1.1
- old
+ new
@@ -8,11 +8,11 @@
[![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 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.
+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. Efficient `LIKE` queries are [not possible](#like-ilike-and-full-text-searching), 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.
@@ -286,9 +286,33 @@
or create `config/initializers/blind_index.rb` with something like
```ruby
BlindIndex.master_key = Rails.application.credentials.blind_index_master_key
```
+
+## LIKE, ILIKE, and Full-Text Searching
+
+Unfortunately, blind indexes can’t be used for `LIKE`, `ILIKE`, or full-text searching. Instead, records must be loaded, decrypted, and searched in memory.
+
+For `LIKE`, use:
+
+```ruby
+User.find { |u| u.email.include?("value") }
+```
+
+For `ILIKE`, use:
+
+```ruby
+User.find { |u| u.email =~ /value/i }
+```
+
+For full-text or fuzzy searching, use a gem like [FuzzyMatch](https://github.com/seamusabshere/fuzzy_match):
+
+```ruby
+FuzzyMatch.new(User.all, read: :email).find("value")
+```
+
+If the number of records is large, try to find a way to narrow it down. An [expression index](#expressions) is one way to do this, but leaks which records have the same value of the expression, so use it carefully.
## Reference
Set default options in an initializer with: