Skip to content

Commit 3372307

Browse files
-Update README.md
1 parent 84c8d38 commit 3372307

File tree

1 file changed

+59
-36
lines changed

1 file changed

+59
-36
lines changed

README.md

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -21,35 +21,35 @@ When data is fully encrypted, you lose the ability to perform meaningful queries
2121

2222
This package removes that trade-off by introducing a **detached searchable index** that maps encrypted records to deterministic tokens.
2323

24-
---\n
24+
---
2525

2626
## Key Features
2727

28-
* **Searchable encryption**: Enables exact and prefix-based searches over encrypted data.
29-
* **Detached search index**: Tokens are stored separately from the main data, reducing exposure risk.
30-
* **Deterministic hashing with peppering**: Each token is derived from normalized text combined with a secret pepper, preventing reverse-engineering.
31-
* **No blind indexes in primary tables**: Encrypted fields remain opaqueonly hashed references are stored elsewhere.
32-
* **High scalability**: Indexes can handle millions of records efficiently using native database indexes.
33-
* **Laravel-native integration**: Fully compatible with Eloquent models, query scopes, and events.
28+
* **Searchable encryption** Enables exact and prefix-based searches over encrypted data.
29+
* **Detached search index** Tokens are stored separately from the main data, reducing exposure risk.
30+
* **Deterministic hashing with peppering**Each token is derived from normalized text combined with a secret pepper.
31+
* **No blind indexes in primary tables**Encrypted fields remain opaque; only hashed references are stored elsewhere.
32+
* **High scalability** — Efficient for millions of records through database indexing.
33+
* **Laravel-native integration** — Works directly with Eloquent models, query scopes, and model events.
3434

3535
---
3636

3737
## How It Works
3838

39-
Each model can declare specific fields as searchable. When the model is saved, a background process normalizes the field value, generates one or more hashed tokens, and stores them in a separate database table named `encrypted_search_index`.
39+
Each model can declare specific fields as searchable. When the model is saved, the system normalizes the field value, generates one or more hashed tokens, and stores them in a separate table named `encrypted_search_index`.
4040

4141
When you search, the package hashes your input using the same process and retrieves matching model IDs from the index.
4242

4343
### 1. Token Generation
4444

4545
For each configured field:
4646

47-
* **Exact match token:** A SHA-256 hash of the normalized value plus a secret pepper.
48-
* **Prefix tokens:** Multiple SHA-256 hashes representing progressive prefixes of the normalized text (e.g., `w`, `wi`, `wie`).
47+
* **Exact match token:** A SHA-256 hash of the normalized value + secret pepper.
48+
* **Prefix tokens:** Multiple SHA-256 hashes representing progressive prefixes of the normalized text (e.g. `w`, `wi`, `wie`).
4949

5050
### 2. Token Storage
5151

52-
All tokens are stored in `encrypted_search_index` with the following structure:
52+
All tokens are stored in `encrypted_search_index`:
5353

5454
| model_type | model_id | field | type | token |
5555
| ----------------- | -------- | ---------- | ------ | ------ |
@@ -65,20 +65,20 @@ Client::encryptedExact('last_names', 'Vermeer')->get();
6565
Client::encryptedPrefix('first_names', 'Wie')->get();
6666
```
6767

68-
These queries use database-level indexes for efficient lookups even on large datasets.
68+
These use indexed lookups and remain performant even at scale.
6969

7070
---
7171

7272
## Security Model
7373

74-
| Threat | Mitigation |
75-
| ----------------------- | --------------------------------------------------------------------------- |
76-
| Database dump or breach | Tokens cannot be reversed to plaintext (salted and peppered SHA-256). |
77-
| Statistical analysis | Tokens are fully detached; frequency analysis yields no useful correlation. |
78-
| Insider access | No sensitive data in the index table; encrypted fields remain opaque. |
79-
| Leaked `APP_KEY` | Does not affect token security; the pepper is stored separately in `.env`. |
74+
| Threat | Mitigation |
75+
| ----------------------- | ----------------------------------------------------------------- |
76+
| Database dump or breach | Tokens cannot be reversed (salted + peppered SHA-256). |
77+
| Statistical analysis | Tokens are detached; frequency analysis yields no correlation. |
78+
| Insider access | No sensitive data in index table; encrypted fields remain opaque. |
79+
| Leaked `APP_KEY` | Irrelevant for tokens; pepper is stored separately in `.env`. |
8080

81-
The system follows a **defense-in-depth** approach: encrypted data remains fully protected, while token search provides limited, controlled visibility for queries.
81+
This design follows a **defense-in-depth** model: encrypted data stays secure, while search operations remain practical.
8282

8383
---
8484

@@ -90,7 +90,7 @@ php artisan vendor:publish --tag=config
9090
php artisan migrate
9191
```
9292

93-
Update your `.env` file with a unique pepper:
93+
Then add a unique pepper to your `.env` file:
9494

9595
```
9696
SEARCH_PEPPER=your-random-secret-string
@@ -100,7 +100,7 @@ SEARCH_PEPPER=your-random-secret-string
100100

101101
## Configuration
102102

103-
`config/encrypted-search.php`
103+
`config/encrypted-search.php`:
104104

105105
```php
106106
return [
@@ -131,47 +131,70 @@ class Client extends Model
131131
}
132132
```
133133

134-
When a `Client` record is saved, its searchable tokens are automatically created or updated in the `encrypted_search_index` table.
134+
When a record is saved, searchable tokens are automatically generated in `encrypted_search_index`.
135135

136136
### Searching
137137

138138
```php
139-
// Exact match search
139+
// Exact match
140140
$clients = Client::encryptedExact('last_names', 'Vermeer')->get();
141141

142-
// Prefix match search
142+
// Prefix match
143143
$clients = Client::encryptedPrefix('first_names', 'Wie')->get();
144144
```
145145

146146
### Rebuilding the Index
147147

148-
You can rebuild the entire search index using an Artisan command:
148+
Rebuild indexes via Artisan:
149149

150150
```bash
151151
php artisan encryption:index-rebuild "App\\Models\\Client"
152152
```
153153

154-
This will reprocess all searchable fields for the specified model.
155-
156154
---
157155

158156
## Scalability and Performance
159157

160-
* **Optimized database lookups**: The `encrypted_search_index` table uses compound indexes for fast token-based lookups.
161-
* **Chunked rebuilds**: The `index-rebuild` command supports chunked processing to handle large datasets efficiently.
162-
* **Asynchronous rebuilds**: Can be safely run in queues or background jobs.
158+
* **Indexed database lookups** for efficient token search.
159+
* **Chunked rebuilds** for large datasets (`--chunk` option).
160+
* **Queue-compatible** for asynchronous index rebuilds.
163161

164-
Unlike in-memory search systems, this index-based approach scales linearly with the size of your dataset and can efficiently handle millions of records.
162+
The detached index structure scales linearly and supports millions of records efficiently.
165163

166164
---
167165

168-
## Compliance
166+
## Framework Compatibility
167+
168+
| Laravel Version | PHP Version(s) Supported |
169+
| --------------- | ------------------------ |
170+
| 8.x | 8.0 – 8.1 |
171+
| 9.x | 8.1 – 8.2 |
172+
| 10.x | 8.1 – 8.3 |
173+
| 11.x | 8.2 – 8.3 |
174+
| 12.x | 8.3+ |
175+
176+
The package is continuously tested across all supported combinations using GitHub Actions.
177+
178+
---
179+
180+
## Continuous Integration
169181

170-
This approach aligns with major privacy and compliance frameworks:
182+
This repository includes automated testing for all Laravel 8–12 releases.
183+
Each test matrix validates functionality on PHP 8.1, 8.2, and 8.3.
184+
185+
Example badge (replace `USERNAME/REPOSITORY` with yours):
186+
187+
```
188+
![Tests](https://github.com/USERNAME/REPOSITORY/actions/workflows/tests.yml/badge.svg)
189+
```
190+
191+
---
192+
193+
## Compliance
171194

172-
* GDPR: Minimal data exposure; encrypted and hashed data separation.
173-
* HIPAA: Ensures ePHI remains protected even in breach scenarios.
174-
* ISO 27001: Supports layered security controls for data confidentiality.
195+
* **GDPR** — Encrypted and hashed separation ensures minimal data exposure.
196+
* **HIPAA** — Meets encryption-at-rest requirements for ePHI.
197+
* **ISO 27001** — Aligns with confidentiality and cryptographic control standards.
175198

176199
---
177200

0 commit comments

Comments
 (0)