-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #32 from cipherstash/buld-operations
feat: bulk encryptions
- Loading branch information
Showing
8 changed files
with
386 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@cipherstash/jseql": minor | ||
--- | ||
|
||
Implemented bulk encryption and decryptions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@cipherstash/nextjs": minor | ||
"@cipherstash/jseql": minor | ||
--- | ||
|
||
Fixed the logtape peer dependency version. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -257,6 +257,160 @@ CREATE TABLE users ( | |
); | ||
``` | ||
|
||
### Buld Encryption/Decryption | ||
|
||
If you have a large list of items to encrypt or decrypt, you can use the **`bulkEncrypt`** and **`bulkDecrypt`** methods to batch encryption/decryption. | ||
These methods are more efficient and perform better than the single-item encryption/decryption methods. | ||
|
||
#### bulkEncrypt | ||
|
||
```ts | ||
const encryptedResults = await eqlClient.bulkEncrypt(plaintextsToEncrypt, { | ||
column: 'email', | ||
table: 'Users', | ||
// lockContext: someLockContext, // if you have one | ||
}) | ||
``` | ||
|
||
**Parameters** | ||
|
||
1. **`plaintexts`** | ||
- **Type**: `{ plaintext: string; id: string }[]` | ||
- **Description**: | ||
An array of objects containing the **plaintext** and an **id**. | ||
- **plaintext**: The string you want encrypted. | ||
- **id**: A unique identifier you can use to map the returned ciphertext back to its source. For example, if you have a `User` with `id: 1`, you might pass `id: '1'`. | ||
|
||
2. **`column`** | ||
- **Type**: `string` | ||
- **Description**: | ||
The name of the column you’re encrypting (e.g., "email"). This is typically used in logging or contextual purposes when constructing the payload for the encryption engine. | ||
|
||
3. **`table`** | ||
- **Type**: `string` | ||
- **Description**: | ||
The name of the table you’re encrypting data in (e.g., "Users"). | ||
|
||
4. **`lockContext`** (optional) | ||
- **Type**: `LockContext` | ||
- **Description**: | ||
Additional metadata and tokens for secure encryption/decryption. If not provided, encryption proceeds without a lock context. | ||
|
||
### Return Value | ||
|
||
- **Type**: `Promise<Array<{ c: string; id: string }> | null>` | ||
- Returns an array of objects, where: | ||
- **`c`** is the ciphertext. | ||
- **`id`** is the same **id** you passed in, so you can correlate which ciphertext matches which original plaintext. | ||
- If `plaintexts` is an empty array, it returns `null`. | ||
|
||
### Example Usage | ||
|
||
```ts | ||
// 1) Gather your data. For example, a list of users with plaintext fields. | ||
const users = [ | ||
{ id: '1', name: 'CJ', email: '[email protected]' }, | ||
{ id: '2', name: 'Alex', email: '[email protected]' }, | ||
] | ||
|
||
// 2) Prepare the array for bulk encryption (only encrypting the "email" field here). | ||
const plaintextsToEncrypt = users.map((user) => ({ | ||
plaintext: user.email, // The data to encrypt | ||
id: user.id, // Keep track by user ID | ||
})) | ||
|
||
// 3) Call bulkEncrypt | ||
const encryptedResults = await bulkEncrypt(plaintextsToEncrypt, { | ||
column: 'email', | ||
table: 'Users', | ||
// lockContext: someLockContext, // if you have one | ||
}) | ||
|
||
// encryptedResults might look like: | ||
// [ | ||
// { c: 'ENCRYPTED_VALUE_1', id: '1' }, | ||
// { c: 'ENCRYPTED_VALUE_2', id: '2' }, | ||
// ] | ||
|
||
// 4) Reassemble data by matching IDs | ||
if (encryptedResults) { | ||
encryptedResults.forEach((result) => { | ||
// Find the corresponding user | ||
const user = users.find((u) => u.id === result.id) | ||
if (user) { | ||
user.email = result.c // Store ciphertext back into the user object | ||
} | ||
}) | ||
} | ||
``` | ||
|
||
--- | ||
|
||
#### bulkDecrypt | ||
|
||
```ts | ||
const decryptedResults = await eqlClient.bulkDecrypt(encryptedPayloads, { | ||
// lockContext: someLockContext, // if needed | ||
}) | ||
``` | ||
|
||
**Parameters** | ||
|
||
1. **`encryptedPayloads`** | ||
- **Type**: `Array<{ c: string; id: string }> | null` | ||
- **Description**: | ||
An array of objects containing the **ciphertext** (`c`) and the **id**. If this array is empty or `null`, the function returns `null`. | ||
|
||
2. **`lockContext`** (optional) | ||
- **Type**: `LockContext` | ||
- **Description**: | ||
Additional metadata used to securely unlock ciphertext. If not provided, decryption proceeds without it. | ||
|
||
### Return Value | ||
|
||
- **Type**: `Promise<Array<{ plaintext: string; id: string }> | null>` | ||
- Returns an array of objects, where: | ||
- **`plaintext`** is the decrypted value. | ||
- **`id`** is the same **id** you passed in, so you can correlate which plaintext matches which original ciphertext. | ||
- Returns `null` if the provided `encryptedPayloads` is empty or `null`. | ||
|
||
### Example Usage | ||
|
||
```ts | ||
// Suppose you've retrieved an array of users where their email fields are ciphertext: | ||
const users = [ | ||
{ id: '1', name: 'CJ', email: 'ENCRYPTED_VALUE_1' }, | ||
{ id: '2', name: 'Alex', email: 'ENCRYPTED_VALUE_2' }, | ||
] | ||
|
||
// 1) Prepare the array for bulk decryption | ||
const encryptedPayloads = users.map((user) => ({ | ||
c: user.email, | ||
id: user.id, | ||
})) | ||
|
||
// 2) Call bulkDecrypt | ||
const decryptedResults = await bulkDecrypt(encryptedPayloads, { | ||
// lockContext: someLockContext, // if needed | ||
}) | ||
|
||
// decryptedResults might look like: | ||
// [ | ||
// { plaintext: '[email protected]', id: '1' }, | ||
// { plaintext: '[email protected]', id: '2' }, | ||
// ] | ||
|
||
// 3) Reassemble data by matching IDs | ||
if (decryptedResults) { | ||
decryptedResults.forEach((result) => { | ||
const user = users.find((u) => u.id === result.id) | ||
if (user) { | ||
user.email = result.plaintext // Put the decrypted value back in place | ||
} | ||
}) | ||
} | ||
``` | ||
|
||
## Searchable encrypted data | ||
|
||
`jseql` does not currently support searching encrypted data. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.