aegis-lock 2.0.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 API-Alchemist
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # aegis-lock
2
2
 
3
- [![npm version](https://badge.fury.io/js/aegis-lock.svg)](https://badge.fury.io/js/aegis-lock)
3
+ [![npm version](https://badge.fury.io/js/aegis-lock.svg?v=2.1.0)](https://badge.fury.io/js/aegis-lock)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- **Database-agnostic client-side AES-256-GCM field-level encryption with Contextual Binding and Blind Indexing.**
6
+ **Database-agnostic client-side AES-256-GCM field-level encryption with Contextual Binding, Blind Indexing, and Seamless Key Rotation.**
7
7
 
8
- Encrypt sensitive fields before they leave the browser or server. Decrypt after select. Zero plaintext hits the wire or your database. Works with **Supabase**, **MongoDB**, or any database via custom adapters.
8
+ Encrypt sensitive fields before they leave the browser or server. Decrypt after select. Zero plaintext hits the wire or your database. Works with Supabase, MongoDB, or any database via custom adapters.
9
9
 
10
10
  > **⚠️ SECURITY WARNING:** `aegis-lock` provides the cryptographic primitives, but **you are responsible for your keys.** Never hardcode `CryptoKey` exports in your source code. Always use a secure Key Management Service (KMS) or strict, vault-backed environment variables to inject your keys at runtime.
11
11
 
@@ -22,17 +22,22 @@ npm install aegis-lock
22
22
 
23
23
  ```typescript
24
24
  import { createClient } from "@supabase/supabase-js";
25
- import { AegisClient, SupabaseAdapter, generateKey, generateBidxKey, exportKey } from "aegis-lock";
25
+ import { AegisClient, SupabaseAdapter, importKey, generateBidxKey } from "aegis-lock";
26
26
 
27
27
  const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
28
28
  const adapter = new SupabaseAdapter(supabase);
29
29
 
30
- // Generate your master encryption key and searchable blind index key
31
- const key = await generateKey();
32
- const bidxKey = await generateBidxKey();
30
+ // 1. Setup your Key Ring for Key Rotation
31
+ // You should load these base64 strings securely from your environment variables
32
+ const keyRing = {
33
+ "v1": await importKey(process.env.AEGIS_KEY_V1),
34
+ "v2": await importKey(process.env.AEGIS_KEY_V2) // Your newest key
35
+ };
36
+ const activeVersion = "v2";
33
37
 
34
- // Export and save these securely! e.g., await exportKey(key)
38
+ const bidxKey = await generateBidxKey(); // Or import your saved blind index key
35
39
 
40
+ // 2. Initialize the Client
36
41
  const aegis = new AegisClient({
37
42
  adapter,
38
43
  primaryKeyField: "record_id", // REQUIRED: Binds ciphertext to the row to prevent tampering
@@ -42,9 +47,9 @@ const aegis = new AegisClient({
42
47
  bidxFields: {
43
48
  secure_fields: ["email"] // Optional: Creates an 'email_bidx' column for searching
44
49
  }
45
- }, key, bidxKey);
50
+ }, keyRing, activeVersion, bidxKey);
46
51
 
47
- // Insert — fields are auto-encrypted.
52
+ // 3. Insert — fields are auto-encrypted using the 'v2' key.
48
53
  // Note: You MUST provide the primary key application-side!
49
54
  await aegis.insert("secure_fields", {
50
55
  record_id: "uuid-1234-5678",
@@ -52,25 +57,39 @@ await aegis.insert("secure_fields", {
52
57
  encrypted_content: "Top secret",
53
58
  });
54
59
 
55
- // Select — Aegis automatically hashes the email to search the 'email_bidx' column securely
60
+ // 4. Select — Aegis automatically hashes the email to search the 'email_bidx' column securely.
61
+ // It will dynamically select the correct key from the KeyRing to decrypt the results.
56
62
  const { data } = await aegis.select("secure_fields", {
57
63
  column: "email",
58
64
  value: "alice@example.com"
59
65
  });
66
+
67
+ // 5. Update — automatically re-encrypts with a new IV and the active 'v2' key.
68
+ await aegis.update("secure_fields", {
69
+ record_id: "uuid-1234-5678", // Must include the primary key!
70
+ email: "new_alice@example.com",
71
+ encrypted_content: "New secret"
72
+ });
73
+
74
+ // 6. Delete — Aegis automatically hashes the email to find the correct row to delete
75
+ await aegis.delete("secure_fields", {
76
+ column: "email",
77
+ value: "new_alice@example.com"
78
+ });
60
79
  ```
61
80
 
62
81
  ## Quick Start — MongoDB
63
82
 
64
83
  ```typescript
65
84
  import { MongoClient } from "mongodb";
66
- import { AegisClient, MongoDBAdapter, generateKey } from "aegis-lock";
85
+ import { AegisClient, MongoDBAdapter, importKey } from "aegis-lock";
67
86
  import { v4 as uuidv4 } from "uuid";
68
87
 
69
88
  const mongo = new MongoClient("mongodb://localhost:27017");
70
89
  await mongo.connect();
71
90
  const adapter = new MongoDBAdapter(mongo.db("myapp"));
72
91
 
73
- const key = await generateKey();
92
+ const keyRing = { "v1": await importKey(process.env.AEGIS_MASTER_KEY) };
74
93
 
75
94
  const aegis = new AegisClient({
76
95
  adapter,
@@ -78,13 +97,22 @@ const aegis = new AegisClient({
78
97
  encryptedFields: {
79
98
  users: ["ssn", "credit_card"]
80
99
  }
81
- }, key);
100
+ }, keyRing, "v1");
101
+
102
+ const newUserId = uuidv4();
82
103
 
83
104
  // Insert with a client-generated ID
84
- await aegis.insert("users", { _id: uuidv4(), name: "Alice", ssn: "123-45-6789" });
105
+ await aegis.insert("users", {
106
+ _id: newUserId,
107
+ name: "Alice",
108
+ ssn: "123-45-6789"
109
+ });
85
110
 
86
111
  // Select by an unencrypted field
87
- const { data } = await aegis.select("users", { column: "name", value: "Alice" });
112
+ const { data } = await aegis.select("users", {
113
+ column: "name",
114
+ value: "Alice"
115
+ });
88
116
  // data[0].ssn → "123-45-6789" (decrypted)
89
117
  ```
90
118
 
@@ -104,21 +132,37 @@ class MyAdapter implements DatabaseAdapter {
104
132
  // your select logic
105
133
  return { data: [], error: null };
106
134
  }
135
+ async update(table: string, data: Record<string, unknown>) {
136
+ // your update logic
137
+ return { data: [data], error: null };
138
+ }
139
+ async delete(table: string, query: { column: string; value: unknown }) {
140
+ // your delete logic
141
+ return { data: [], error: null };
142
+ }
107
143
  }
108
144
  ```
109
145
 
110
146
  ## API
111
147
 
112
- ### `new AegisClient(config, key, bidxKey?)`
148
+ ### `new AegisClient(config, keyRing, currentKeyVersion, bidxKey?)`
149
+
150
+ * **`config`** — `AegisConfig` object:
151
+ * **`adapter`**: any `DatabaseAdapter` (`SupabaseAdapter`, `MongoDBAdapter`, or custom)
152
+ * **`primaryKeyField`**: `string` (The ID field used for cryptographic contextual binding)
153
+ * **`encryptedFields`**: `Record<tableName, fieldName[]>`
154
+ * **`bidxFields`**: *(Optional)* `Record<tableName, fieldName[]>`
155
+ * **`keyRing`** — `Record<string, CryptoKey>` (A dictionary of all active and historical keys).
156
+ * **`currentKeyVersion`** — `string` (The version tag of the key to use for *new* encryptions).
157
+ * **`bidxKey`** — *(Optional)* `CryptoKey` from `generateBidxKey()` or `importKey()`
113
158
 
114
- * `config` — `AegisConfig` object:
115
- * `adapter`: any `DatabaseAdapter` (SupabaseAdapter, MongoDBAdapter, or custom)
116
- * `primaryKeyField`: `string` (The ID field used for cryptographic contextual binding)
117
- * `encryptedFields`: `Record<tableName, fieldName[]>`
118
- * `bidxFields`: *(Optional)* `Record<tableName, fieldName[]>`
159
+ ### `AegisClient` Methods
119
160
 
120
- * `key` CryptoKey from `generateKey()` or `importKey()`
121
- * `bidxKey` — *(Optional)* CryptoKey from `generateBidxKey()` or `importKey()`
161
+ * **`insert(table, data)`**: Encrypts data and creates blind indexes before saving.
162
+ * **`select(table, query)`**: Fetches and automatically decrypts data. Intercepts blind index queries.
163
+ * **`update(table, data)`**: Re-encrypts modified fields with new IVs and updates blind indexes.
164
+ * **`delete(table, query)`**: Intercepts queries to securely delete by blind-indexed fields.
165
+ * **`selectRaw(table, query)`**: Bypasses decryption to return raw database records (useful for auditing or migrations).
122
166
 
123
167
  ### Adapters
124
168
 
@@ -130,14 +174,17 @@ class MyAdapter implements DatabaseAdapter {
130
174
  * `generateKey()` / `generateBidxKey()`
131
175
  * `exportKey(key)` / `importKey(base64)`
132
176
 
177
+ ---
178
+
133
179
  ## How It Works (Security Architecture)
134
180
 
135
- * **Web Crypto API (AES-256-GCM):** Runs natively in any modern browser or edge runtime.
136
- * **Field-Level IVs:** Every single encrypted field gets a unique, mathematically random Initialization Vector (IV) stored as a composite string (`iv:ciphertext`) to prevent keystream reuse attacks.
181
+ * **Web Crypto API (AES-256-GCM):** Runs natively in any modern browser or edge runtime without bloated dependencies.
182
+ * **Seamless Key Rotation:** Aegis-Lock accepts a dictionary of keys. It tags every database payload with the active key's version string. If a key is compromised, you simply introduce a `v2` key. New data is secured with `v2`, while historical data seamlessly decrypts using `v1` without a single second of database downtime.
183
+ * **Field-Level IVs:** Every single encrypted field gets a unique, mathematically random Initialization Vector (IV). The final database payload is formatted as `version:iv:ciphertext` to prevent keystream reuse attacks.
137
184
  * **Contextual Binding (AAD):** Ciphertexts are cryptographically bound to the row's `primaryKeyField`. If an attacker copies an encrypted SSN from User A and pastes it into User B's row, the decryption will strictly fail.
138
185
  * **Blind Indexing (HMAC-SHA256):** Because AES-GCM is non-deterministic (the same text encrypts differently every time), you cannot query standard encrypted fields. If configured via `bidxFields`, Aegis-Lock automatically generates deterministic, memory-aligned HMAC hashes. This allows you to search for exact matches (like looking up an email address) without exposing the plaintext to the database.
139
- * **Database-agnostic:** Swap adapters without changing your core application code.
186
+ * **Database-Agnostic:** Swap adapters without changing your core application code.
140
187
 
141
188
  ## License
142
189
 
143
- MIT
190
+ MIT
@@ -1,19 +1,8 @@
1
1
  import type { DatabaseAdapter } from "../types";
2
2
  /**
3
- * MongoDB adapter for aegis-mern.
3
+ * MongoDB adapter for aegis-lock.
4
4
  *
5
- * Works with any MongoDB client that exposes a `db()` method (e.g. the official
6
- * `mongodb` Node.js driver). Pass the Db instance directly.
7
- *
8
- * Usage:
9
- * ```ts
10
- * import { MongoClient } from "mongodb";
11
- * import { MongoDBAdapter } from "aegis-mern/adapters/mongodb";
12
- *
13
- * const client = new MongoClient(uri);
14
- * await client.connect();
15
- * const adapter = new MongoDBAdapter(client.db("mydb"));
16
- * ```
5
+ * Works with any MongoDB client that exposes a `db()` method.
17
6
  */
18
7
  export declare class MongoDBAdapter implements DatabaseAdapter {
19
8
  private db;
@@ -38,7 +27,23 @@ export declare class MongoDBAdapter implements DatabaseAdapter {
38
27
  data: null;
39
28
  error: unknown;
40
29
  }>;
41
- /** Access the underlying MongoDB Db instance. */
30
+ update(table: string, data: Record<string, unknown>): Promise<{
31
+ data: Record<string, unknown>[];
32
+ error: null;
33
+ } | {
34
+ data: null;
35
+ error: unknown;
36
+ }>;
37
+ delete(table: string, query: {
38
+ column: string;
39
+ value: unknown;
40
+ }): Promise<{
41
+ data: never[];
42
+ error: null;
43
+ } | {
44
+ data: null;
45
+ error: unknown;
46
+ }>;
42
47
  get database(): any;
43
48
  }
44
49
  //# sourceMappingURL=mongodb.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mongodb.d.ts","sourceRoot":"","sources":["../../adapters/mongodb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,EAAE,CAAM;gBAEJ,EAAE,EAAE,GAAG;IAIb,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;IAWnD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;cAY7D,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;;;;;;IAMpD,iDAAiD;IACjD,IAAI,QAAQ,QAEX;CACF"}
1
+ {"version":3,"file":"mongodb.d.ts","sourceRoot":"","sources":["../../adapters/mongodb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD;;;;GAIG;AACH,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,EAAE,CAAM;gBAEJ,EAAE,EAAE,GAAG;IAIb,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;IAWnD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;cAY7D,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;;;;;;IAM9C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;IAqBnD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE;;;;;;;IAWrE,IAAI,QAAQ,QAEX;CACF"}
@@ -1,18 +1,7 @@
1
1
  /**
2
- * MongoDB adapter for aegis-mern.
2
+ * MongoDB adapter for aegis-lock.
3
3
  *
4
- * Works with any MongoDB client that exposes a `db()` method (e.g. the official
5
- * `mongodb` Node.js driver). Pass the Db instance directly.
6
- *
7
- * Usage:
8
- * ```ts
9
- * import { MongoClient } from "mongodb";
10
- * import { MongoDBAdapter } from "aegis-mern/adapters/mongodb";
11
- *
12
- * const client = new MongoClient(uri);
13
- * await client.connect();
14
- * const adapter = new MongoDBAdapter(client.db("mydb"));
15
- * ```
4
+ * Works with any MongoDB client that exposes a `db()` method.
16
5
  */
17
6
  export class MongoDBAdapter {
18
7
  constructor(db) {
@@ -47,7 +36,32 @@ export class MongoDBAdapter {
47
36
  return { data: null, error };
48
37
  }
49
38
  }
50
- /** Access the underlying MongoDB Db instance. */
39
+ async update(table, data) {
40
+ try {
41
+ const collection = this.db.collection(table);
42
+ // Auto-detect the primary key field for MongoDB (usually _id or id)
43
+ const pkField = data._id ? '_id' : (data.id ? 'id' : null);
44
+ if (!pkField)
45
+ throw new Error("MongoDB Adapter: Missing '_id' or 'id' in data payload for update.");
46
+ const { [pkField]: pkValue, ...updateData } = data;
47
+ await collection.updateOne({ [pkField]: pkValue }, { $set: updateData });
48
+ return { data: [data], error: null };
49
+ }
50
+ catch (error) {
51
+ return { data: null, error };
52
+ }
53
+ }
54
+ async delete(table, query) {
55
+ try {
56
+ const collection = this.db.collection(table);
57
+ const filter = { [query.column]: query.value };
58
+ await collection.deleteMany(filter);
59
+ return { data: [], error: null };
60
+ }
61
+ catch (error) {
62
+ return { data: null, error };
63
+ }
64
+ }
51
65
  get database() {
52
66
  return this.db;
53
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mongodb.js","sourceRoot":"","sources":["../../adapters/mongodb.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,cAAc;IAGzB,YAAY,EAAO;QACjB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,IAA6B;QACvD,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YAC7C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAChD,MAAM,QAAQ,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;YACrD,OAAO,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAC3C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,KAA4D;QACtF,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YAC7C,MAAM,MAAM,GAA4B,EAAE,CAAC;YAC3C,IAAI,KAAK,EAAE,MAAM,IAAI,KAAK,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;gBAChD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;YACrC,CAAC;YACD,IAAI,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrC,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;gBACjB,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACrC,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,OAAO,EAAE,IAAI,EAAE,IAAiC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAClE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,EAAE,CAAC;IACjB,CAAC;CACF"}
1
+ {"version":3,"file":"mongodb.js","sourceRoot":"","sources":["../../adapters/mongodb.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import type { SupabaseClient } from "@supabase/supabase-js";
2
2
  import type { DatabaseAdapter } from "../types";
3
- /** Supabase adapter for aegis-mern. */
3
+ /** Supabase adapter for aegis-lock. */
4
4
  export declare class SupabaseAdapter implements DatabaseAdapter {
5
5
  private supabase;
6
6
  constructor(supabase: SupabaseClient);
@@ -16,7 +16,20 @@ export declare class SupabaseAdapter implements DatabaseAdapter {
16
16
  data: Record<string, unknown>[] | null;
17
17
  error: import("@supabase/postgrest-js").PostgrestError | null;
18
18
  }>;
19
- /** Access the underlying Supabase client for non-encrypted ops. */
19
+ update(table: string, data: Record<string, unknown>): Promise<{
20
+ data: null;
21
+ error: Error;
22
+ } | {
23
+ data: Record<string, unknown>[] | null;
24
+ error: import("@supabase/postgrest-js").PostgrestError | null;
25
+ }>;
26
+ delete(table: string, query: {
27
+ column: string;
28
+ value: unknown;
29
+ }): Promise<{
30
+ data: Record<string, unknown>[] | null;
31
+ error: import("@supabase/postgrest-js").PostgrestError | null;
32
+ }>;
20
33
  get client(): SupabaseClient<any, "public", "public", any, any>;
21
34
  }
22
35
  //# sourceMappingURL=supabase.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../adapters/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,uCAAuC;AACvC,qBAAa,eAAgB,YAAW,eAAe;IACrD,OAAO,CAAC,QAAQ,CAAiB;gBAErB,QAAQ,EAAE,cAAc;IAI9B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;cAE9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI;;;IAGrD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;cAS/D,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI;;;IAGzD,mEAAmE;IACnE,IAAI,MAAM,sDAET;CACF"}
1
+ {"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../adapters/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,uCAAuC;AACvC,qBAAa,eAAgB,YAAW,eAAe;IACrD,OAAO,CAAC,QAAQ,CAAiB;gBAErB,QAAQ,EAAE,cAAc;IAI9B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;cAE9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI;;;IAGrD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;cAS/D,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI;;;IAGnD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;cAc9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI;;;IAGrD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE;cAO1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI;;;IAG3D,IAAI,MAAM,sDAET;CACF"}
@@ -1,4 +1,4 @@
1
- /** Supabase adapter for aegis-mern. */
1
+ /** Supabase adapter for aegis-lock. */
2
2
  export class SupabaseAdapter {
3
3
  constructor(supabase) {
4
4
  this.supabase = supabase;
@@ -18,7 +18,27 @@ export class SupabaseAdapter {
18
18
  const { data, error } = await q;
19
19
  return { data: data, error };
20
20
  }
21
- /** Access the underlying Supabase client for non-encrypted ops. */
21
+ async update(table, data) {
22
+ // Auto-detect primary key (Supabase usually uses 'id')
23
+ const pkField = data.id ? 'id' : (data._id ? '_id' : null);
24
+ if (!pkField) {
25
+ return { data: null, error: new Error("Supabase Adapter: Missing 'id' in data payload for update.") };
26
+ }
27
+ const { data: result, error } = await this.supabase
28
+ .from(table)
29
+ .update(data)
30
+ .eq(pkField, data[pkField])
31
+ .select();
32
+ return { data: result, error };
33
+ }
34
+ async delete(table, query) {
35
+ const { data: result, error } = await this.supabase
36
+ .from(table)
37
+ .delete()
38
+ .eq(query.column, query.value)
39
+ .select();
40
+ return { data: result, error };
41
+ }
22
42
  get client() {
23
43
  return this.supabase;
24
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"supabase.js","sourceRoot":"","sources":["../../adapters/supabase.ts"],"names":[],"mappings":"AAGA,uCAAuC;AACvC,MAAM,OAAO,eAAe;IAG1B,YAAY,QAAwB;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,IAA6B;QACvD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;QACtF,OAAO,EAAE,IAAI,EAAE,MAA0C,EAAE,KAAK,EAAE,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,KAA4D;QACtF,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,KAAK,EAAE,MAAM,IAAI,KAAK,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;YAChD,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;YACjB,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,CAAC;QAChC,OAAO,EAAE,IAAI,EAAE,IAAwC,EAAE,KAAK,EAAE,CAAC;IACnE,CAAC;IAED,mEAAmE;IACnE,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF"}
1
+ {"version":3,"file":"supabase.js","sourceRoot":"","sources":["../../adapters/supabase.ts"],"names":[],"mappings":"AAGA,uCAAuC;AACvC,MAAM,OAAO,eAAe;IAG1B,YAAY,QAAwB;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,IAA6B;QACvD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;QACtF,OAAO,EAAE,IAAI,EAAE,MAA0C,EAAE,KAAK,EAAE,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,KAA4D;QACtF,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,KAAK,EAAE,MAAM,IAAI,KAAK,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;YAChD,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;YACjB,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,CAAC;QAChC,OAAO,EAAE,IAAI,EAAE,IAAwC,EAAE,KAAK,EAAE,CAAC;IACnE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,IAA6B;QACvD,uDAAuD;QACvD,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAE3D,IAAI,CAAC,OAAO,EAAE,CAAC;YACZ,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,KAAK,CAAC,4DAA4D,CAAC,EAAE,CAAC;QACzG,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ;aAChD,IAAI,CAAC,KAAK,CAAC;aACX,MAAM,CAAC,IAAI,CAAC;aACZ,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;aAC1B,MAAM,EAAE,CAAC;QAEZ,OAAO,EAAE,IAAI,EAAE,MAA0C,EAAE,KAAK,EAAE,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,KAAyC;QACnE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ;aAChD,IAAI,CAAC,KAAK,CAAC;aACX,MAAM,EAAE;aACR,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC;aAC7B,MAAM,EAAE,CAAC;QAEZ,OAAO,EAAE,IAAI,EAAE,MAA0C,EAAE,KAAK,EAAE,CAAC;IACrE,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF"}
package/dist/client.d.ts CHANGED
@@ -1,16 +1,38 @@
1
1
  import type { DatabaseAdapter, AegisConfig } from "./types";
2
+ /**
3
+ * The primary client for aegis-lock.
4
+ * Handles automatic encryption, decryption, contextual binding, blind indexing,
5
+ * and Key Rotation before interacting with the underlying database adapter.
6
+ */
2
7
  export declare class AegisClient {
3
8
  private adapter;
4
- private key;
9
+ private keyRing;
10
+ private currentKeyVersion;
5
11
  private bidxKey?;
6
12
  private encryptedFields;
7
13
  private bidxFields;
8
14
  private primaryKeyField;
9
- constructor(config: AegisConfig, key: CryptoKey, bidxKey?: CryptoKey);
15
+ /**
16
+ * Initializes the AegisClient with Key Rotation support.
17
+ *
18
+ * @param config - Configuration including the database adapter, primary key field, and field rules.
19
+ * @param keyRing - A dictionary of historical and active CryptoKeys (e.g., { v1: key1, v2: key2 }).
20
+ * @param currentKeyVersion - The string identifier of the key to use for NEW encryptions (e.g., "v2").
21
+ * @param bidxKey - (Optional) The CryptoKey used for generating HMAC-SHA256 blind indexes.
22
+ */
23
+ constructor(config: AegisConfig, keyRing: Record<string, CryptoKey>, currentKeyVersion: string, bidxKey?: CryptoKey);
24
+ /**
25
+ * Securely inserts a new record into the database.
26
+ * Automatically generates blind indexes and encrypts configured fields using the CURRENT key version.
27
+ */
10
28
  insert(table: string, data: Record<string, unknown>): Promise<{
11
29
  data: Record<string, unknown>[] | null;
12
30
  error: unknown;
13
31
  }>;
32
+ /**
33
+ * Retrieves and automatically decrypts records from the database.
34
+ * Dynamically selects the correct decryption key based on the payload's version tag.
35
+ */
14
36
  select(table: string, query?: {
15
37
  column?: string;
16
38
  value?: unknown;
@@ -19,6 +41,21 @@ export declare class AegisClient {
19
41
  data: Record<string, unknown>[] | null;
20
42
  error: unknown;
21
43
  }>;
44
+ /**
45
+ * Securely modifies an existing record.
46
+ * Re-encrypts data with a new unique IV and the CURRENT key version.
47
+ */
48
+ update(table: string, data: Record<string, unknown>): Promise<{
49
+ data: any[] | null;
50
+ error: any;
51
+ }>;
52
+ delete(table: string, query: {
53
+ column: string;
54
+ value: unknown;
55
+ }): Promise<{
56
+ data: any[] | null;
57
+ error: any;
58
+ }>;
22
59
  selectRaw(table: string, query?: {
23
60
  column?: string;
24
61
  value?: unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG5D,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,OAAO,CAAC,CAAY;IAC5B,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,eAAe,CAAS;gBAGpB,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,SAAS;IAS9D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;IAyCnD,MAAM,CACV,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;;;;IA6DxD,SAAS,CACb,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;;;;IAK9D,IAAI,EAAE,IAAI,eAAe,CAExB;CACF"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG5D;;;;GAIG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,OAAO,CAAC,CAAY;IAC5B,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,eAAe,CAAS;IAEhC;;;;;;;OAOG;gBAED,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAClC,iBAAiB,EAAE,MAAM,EACzB,OAAO,CAAC,EAAE,SAAS;IAWrB;;;OAGG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;IA6CzD;;;OAGG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;;;;IAgE9D;;;OAGG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;IAsCnD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE;;;;IAgB/D,SAAS,CACb,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;;;;IAK9D,IAAI,EAAE,IAAI,eAAe,CAExB;CACF"}
package/dist/client.js CHANGED
@@ -1,14 +1,31 @@
1
1
  import { encrypt, decrypt, generateBlindIndex } from "./crypto";
2
+ /**
3
+ * The primary client for aegis-lock.
4
+ * Handles automatic encryption, decryption, contextual binding, blind indexing,
5
+ * and Key Rotation before interacting with the underlying database adapter.
6
+ */
2
7
  export class AegisClient {
3
- // Updated constructor to accept the optional BIDX key
4
- constructor(config, key, bidxKey) {
8
+ /**
9
+ * Initializes the AegisClient with Key Rotation support.
10
+ *
11
+ * @param config - Configuration including the database adapter, primary key field, and field rules.
12
+ * @param keyRing - A dictionary of historical and active CryptoKeys (e.g., { v1: key1, v2: key2 }).
13
+ * @param currentKeyVersion - The string identifier of the key to use for NEW encryptions (e.g., "v2").
14
+ * @param bidxKey - (Optional) The CryptoKey used for generating HMAC-SHA256 blind indexes.
15
+ */
16
+ constructor(config, keyRing, currentKeyVersion, bidxKey) {
5
17
  this.adapter = config.adapter;
6
- this.key = key;
18
+ this.keyRing = keyRing;
19
+ this.currentKeyVersion = currentKeyVersion;
7
20
  this.bidxKey = bidxKey;
8
21
  this.encryptedFields = config.encryptedFields;
9
22
  this.bidxFields = config.bidxFields || {};
10
23
  this.primaryKeyField = config.primaryKeyField;
11
24
  }
25
+ /**
26
+ * Securely inserts a new record into the database.
27
+ * Automatically generates blind indexes and encrypts configured fields using the CURRENT key version.
28
+ */
12
29
  async insert(table, data) {
13
30
  const fields = this.encryptedFields[table] || [];
14
31
  const bidxFields = this.bidxFields[table] || [];
@@ -19,29 +36,32 @@ export class AegisClient {
19
36
  throw new Error(`Aegis: Cannot encrypt. Missing primary key '${this.primaryKeyField}' in payload.`);
20
37
  }
21
38
  const aadContext = String(rowId);
22
- // 1. Handle Blind Indexing FIRST (While row data is still plaintext)
39
+ const activeKey = this.keyRing[this.currentKeyVersion]; // Grab the active key
40
+ // 1. Handle Blind Indexing FIRST
23
41
  for (const field of bidxFields) {
24
42
  if (row[field] != null && this.bidxKey) {
25
- row[`${field}_bidx`] = await generateBlindIndex(String(row[field]), // Safe: This is still "alice@example.com"
26
- this.bidxKey);
43
+ row[`${field}_bidx`] = await generateBlindIndex(String(row[field]), this.bidxKey);
27
44
  }
28
45
  }
29
- // 2. Handle Encryption SECOND (This overwrites the plaintext)
46
+ // 2. Handle Encryption SECOND
30
47
  for (const field of fields) {
31
48
  if (row[field] != null) {
32
- const { ciphertext, iv } = await encrypt(String(row[field]), this.key, aadContext);
33
- row[field] = `${iv}:${ciphertext}`;
49
+ // Pass the active key and the version tag to the new encrypt function
50
+ const { version, ciphertext, iv } = await encrypt(String(row[field]), activeKey, this.currentKeyVersion, aadContext);
51
+ // Store it in the DB as "version:iv:ciphertext"
52
+ row[field] = `${version}:${iv}:${ciphertext}`;
34
53
  }
35
54
  }
36
55
  }
37
56
  return this.adapter.insert(table, row);
38
57
  }
58
+ /**
59
+ * Retrieves and automatically decrypts records from the database.
60
+ * Dynamically selects the correct decryption key based on the payload's version tag.
61
+ */
39
62
  async select(table, query) {
40
- // Intercept and swap query for Blind Indexing (NEW)
41
63
  const bidxFields = this.bidxFields[table] || [];
42
64
  let activeQuery = query;
43
- // Make sure this uses THIS.bidxKey
44
- // Inside your select method in client.ts
45
65
  if (query?.column &&
46
66
  query?.value &&
47
67
  bidxFields.includes(query.column) &&
@@ -50,7 +70,7 @@ export class AegisClient {
50
70
  activeQuery = {
51
71
  ...query,
52
72
  column: `${query.column}_bidx`,
53
- value: blindIndexValue, // Pass the resulting string
73
+ value: blindIndexValue,
54
74
  };
55
75
  }
56
76
  const { data, error } = await this.adapter.select(table, activeQuery);
@@ -66,14 +86,19 @@ export class AegisClient {
66
86
  return decRow;
67
87
  const aadContext = String(rowId);
68
88
  for (const field of fields) {
69
- const payload = decRow[field];
70
- if (typeof payload === "string" && payload.includes(":")) {
71
- const [iv, ciphertext] = payload.split(":");
72
- try {
73
- decRow[field] = await decrypt({ ciphertext, iv }, this.key, aadContext);
74
- }
75
- catch {
76
- // Tampering detected
89
+ const payloadStr = decRow[field];
90
+ if (typeof payloadStr === "string" && payloadStr.includes(":")) {
91
+ const parts = payloadStr.split(":");
92
+ // Check for our new 3-part versioned payload
93
+ if (parts.length === 3) {
94
+ const [version, iv, ciphertext] = parts;
95
+ try {
96
+ // Pass the whole KeyRing. crypto.ts will pick the right one.
97
+ decRow[field] = await decrypt({ version, ciphertext, iv }, this.keyRing, aadContext);
98
+ }
99
+ catch {
100
+ // Tampering detected or wrong key
101
+ }
77
102
  }
78
103
  }
79
104
  }
@@ -81,6 +106,48 @@ export class AegisClient {
81
106
  }));
82
107
  return { data: decrypted, error };
83
108
  }
109
+ /**
110
+ * Securely modifies an existing record.
111
+ * Re-encrypts data with a new unique IV and the CURRENT key version.
112
+ */
113
+ async update(table, data) {
114
+ const fields = this.encryptedFields[table] || [];
115
+ const bidxFields = this.bidxFields[table] || [];
116
+ const row = { ...data };
117
+ const rowId = row[this.primaryKeyField];
118
+ if (!rowId) {
119
+ throw new Error(`Aegis: Cannot update. Missing primary key '${this.primaryKeyField}' in payload.`);
120
+ }
121
+ const aadContext = String(rowId);
122
+ const activeKey = this.keyRing[this.currentKeyVersion];
123
+ if (fields.length > 0 || bidxFields.length > 0) {
124
+ for (const field of bidxFields) {
125
+ if (row[field] != null && this.bidxKey) {
126
+ row[`${field}_bidx`] = await generateBlindIndex(String(row[field]), this.bidxKey);
127
+ }
128
+ }
129
+ for (const field of fields) {
130
+ if (row[field] != null) {
131
+ const { version, ciphertext, iv } = await encrypt(String(row[field]), activeKey, this.currentKeyVersion, aadContext);
132
+ row[field] = `${version}:${iv}:${ciphertext}`;
133
+ }
134
+ }
135
+ }
136
+ return this.adapter.update(table, row);
137
+ }
138
+ async delete(table, query) {
139
+ const bidxFields = this.bidxFields[table] || [];
140
+ let activeQuery = query;
141
+ if (bidxFields.includes(query.column) && this.bidxKey) {
142
+ const blindIndexValue = await generateBlindIndex(String(query.value), this.bidxKey);
143
+ activeQuery = {
144
+ ...query,
145
+ column: `${query.column}_bidx`,
146
+ value: blindIndexValue,
147
+ };
148
+ }
149
+ return this.adapter.delete(table, activeQuery);
150
+ }
84
151
  async selectRaw(table, query) {
85
152
  return this.adapter.select(table, query);
86
153
  }
@@ -88,138 +155,4 @@ export class AegisClient {
88
155
  return this.adapter;
89
156
  }
90
157
  }
91
- // export class AegisClient {
92
- // private adapter: DatabaseAdapter;
93
- // private key: CryptoKey;
94
- // private bidxKey?: CryptoKey;
95
- // private encryptedFields: Record<string, string[]>;
96
- // private bidxFields: Record<string, string[]>;
97
- // private primaryKeyField: string;
98
- // constructor(config: AegisConfig, key: CryptoKey) {
99
- // this.adapter = config.adapter;
100
- // this.key = key;
101
- // this.bidxKey = bidxKey;
102
- // this.encryptedFields = config.encryptedFields;
103
- // this.bidxFields = config.bidxFields || {};
104
- // this.primaryKeyField = config.primaryKeyField;
105
- // }
106
- // async insert(table: string, data: Record<string, unknown>) {
107
- // const fields = this.encryptedFields[table] || [];
108
- // const row: Record<string, unknown> = { ...data };
109
- // if (fields.length > 0) {
110
- // const rowId = row[this.primaryKeyField];
111
- // if (!rowId) {
112
- // throw new Error(`Aegis: Cannot encrypt. Missing primary key '${this.primaryKeyField}' in payload.`);
113
- // }
114
- // const aadContext = String(rowId);
115
- // for (const field of fields) {
116
- // if (row[field] != null) {
117
- // // Generates unique IV per field and binds to the row ID
118
- // const { ciphertext, iv } = await encrypt(String(row[field]), this.key, aadContext);
119
- // row[field] = `${iv}:${ciphertext}`;
120
- // }
121
- // }
122
- // }
123
- // return this.adapter.insert(table, row);
124
- // }
125
- // async select(table: string, query?: { column?: string; value?: unknown; limit?: number }) {
126
- // const { data, error } = await this.adapter.select(table, query);
127
- // if (error || !data) return { data, error };
128
- // const fields = this.encryptedFields[table] || [];
129
- // if (fields.length === 0) return { data, error };
130
- // const decrypted = await Promise.all(
131
- // data.map(async (row: Record<string, unknown>) => {
132
- // const decRow = { ...row };
133
- // const rowId = decRow[this.primaryKeyField];
134
- // if (!rowId) return decRow; // Cannot decrypt without context
135
- // const aadContext = String(rowId);
136
- // for (const field of fields) {
137
- // const payload = decRow[field];
138
- // if (typeof payload === 'string' && payload.includes(':')) {
139
- // const [iv, ciphertext] = payload.split(':');
140
- // try {
141
- // decRow[field] = await decrypt({ ciphertext, iv }, this.key, aadContext);
142
- // } catch {
143
- // // Tampering detected (invalid tag or swapped ciphertext). Leave as raw string.
144
- // }
145
- // }
146
- // }
147
- // return decRow;
148
- // })
149
- // );
150
- // return { data: decrypted, error };
151
- // }
152
- // async selectRaw(table: string, query?: { column?: string; value?: unknown; limit?: number }) {
153
- // return this.adapter.select(table, query);
154
- // }
155
- // get db(): DatabaseAdapter {
156
- // return this.adapter;
157
- // }
158
- // }
159
- // import type { DatabaseAdapter } from "./types";
160
- // import { encrypt, decrypt } from "./crypto";
161
- // export class AegisClient {
162
- // private adapter: DatabaseAdapter;
163
- // private key: CryptoKey;
164
- // private encryptedFields: Record<string, string[]>;
165
- // constructor(adapter: DatabaseAdapter, key: CryptoKey, encryptedFields: Record<string, string[]>) {
166
- // this.adapter = adapter;
167
- // this.key = key;
168
- // this.encryptedFields = encryptedFields;
169
- // }
170
- // /** Insert a row, auto-encrypting configured fields. Returns a shared IV for the row. */
171
- // async insert(table: string, data: Record<string, unknown>) {
172
- // const fields = this.encryptedFields[table] || [];
173
- // const row: Record<string, unknown> = { ...data };
174
- // // Generate a single IV and reuse it for all fields in this row
175
- // const ivBuffer = crypto.getRandomValues(new Uint8Array(12));
176
- // const sharedIv = btoa(String.fromCharCode(...ivBuffer));
177
- // for (const field of fields) {
178
- // if (row[field] != null) {
179
- // const { ciphertext } = await encrypt(String(row[field]), this.key, ivBuffer);
180
- // row[field] = ciphertext;
181
- // }
182
- // }
183
- // if (fields.length > 0) {
184
- // row.iv = sharedIv;
185
- // }
186
- // return this.adapter.insert(table, row);
187
- // }
188
- // /** Select rows, auto-decrypting configured fields. */
189
- // async select(table: string, query?: { column?: string; value?: unknown; limit?: number }) {
190
- // const { data, error } = await this.adapter.select(table, query);
191
- // if (error || !data) return { data, error };
192
- // const fields = this.encryptedFields[table] || [];
193
- // if (fields.length === 0) return { data, error };
194
- // const decrypted = await Promise.all(
195
- // data.map(async (row: Record<string, unknown>) => {
196
- // const decRow = { ...row };
197
- // const iv = row.iv as string;
198
- // if (!iv) return decRow;
199
- // for (const field of fields) {
200
- // if (decRow[field] != null) {
201
- // try {
202
- // decRow[field] = await decrypt(
203
- // { ciphertext: String(decRow[field]), iv },
204
- // this.key
205
- // );
206
- // } catch {
207
- // // leave as ciphertext if decryption fails
208
- // }
209
- // }
210
- // }
211
- // return decRow;
212
- // })
213
- // );
214
- // return { data: decrypted, error };
215
- // }
216
- // /** Select rows WITHOUT decrypting — exposes raw ciphertext. */
217
- // async selectRaw(table: string, query?: { column?: string; value?: unknown; limit?: number }) {
218
- // return this.adapter.select(table, query);
219
- // }
220
- // /** Access the underlying database adapter. */
221
- // get db(): DatabaseAdapter {
222
- // return this.adapter;
223
- // }
224
- // }
225
158
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../client.ts"],"names":[],"mappings":"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"}
package/dist/crypto.d.ts CHANGED
@@ -1,11 +1,56 @@
1
1
  import { EncryptedPayload } from "./types";
2
+ /**
3
+ * Generates a strong, 256-bit master key for AES-GCM encryption and decryption.
4
+ * * @returns A Promise resolving to a native Web Crypto API CryptoKey.
5
+ */
2
6
  export declare function generateKey(): Promise<CryptoKey>;
7
+ /**
8
+ * Exports a CryptoKey into a raw Base64 string so it can be safely stored
9
+ * in an environment variable or Key Management Service (KMS).
10
+ * * @param key - The CryptoKey to export.
11
+ * @returns A Promise resolving to the Base64 representation of the key.
12
+ */
3
13
  export declare function exportKey(key: CryptoKey): Promise<string>;
14
+ /**
15
+ * Imports a Base64 string back into a usable CryptoKey for AES-GCM operations.
16
+ * * @param base64 - The Base64 encoded key string (usually from environment variables).
17
+ * @returns A Promise resolving to the imported CryptoKey.
18
+ */
4
19
  export declare function importKey(base64: string): Promise<CryptoKey>;
5
- export declare function encrypt(plaintext: string, key: CryptoKey, aadContext: string): Promise<EncryptedPayload>;
6
- export declare function decrypt(payload: EncryptedPayload, key: CryptoKey, aadContext: string): Promise<string>;
7
- /** Generates a dedicated key for deterministic Blind Indexing */
20
+ /**
21
+ * Encrypts a plaintext string using AES-256-GCM.
22
+ * Automatically generates a unique 12-byte Initialization Vector (IV) and applies
23
+ * Contextual Binding (AAD) to tie the ciphertext to a specific database row.
24
+ * @param plaintext - The sensitive data to encrypt.
25
+ * @param key - The master AES-GCM CryptoKey.
26
+ * @param keyVersion - The string identifier for the active key (e.g., "v2").
27
+ * @param aadContext - The row ID or primary key to bind this ciphertext to.
28
+ * @returns A Promise resolving to an object containing the Base64 `ciphertext` and `iv`.
29
+ */
30
+ export declare function encrypt(plaintext: string, key: CryptoKey, keyVersion: string, aadContext: string): Promise<EncryptedPayload>;
31
+ /**
32
+ * Decrypts an AES-256-GCM payload back into plaintext.
33
+ * Supports Key Rotation by reading the payload's version and selecting the correct key.
34
+ * Strictly verifies the Context (AAD) to ensure data integrity.
35
+ *
36
+ * @param payload - The EncryptedPayload containing `version`, `ciphertext`, and `iv`.
37
+ * @param keyRing - A dictionary of historical and active CryptoKeys (e.g., { "v1": key1, "v2": key2 }).
38
+ * @param aadContext - The row ID or primary key that this ciphertext is bound to.
39
+ * @returns A Promise resolving to the decrypted plaintext string.
40
+ */
41
+ export declare function decrypt(payload: EncryptedPayload, keyRing: Record<string, CryptoKey>, // Accepts multiple keys
42
+ aadContext: string): Promise<string>;
43
+ /** * Generates a dedicated HMAC-SHA256 key for deterministic Blind Indexing.
44
+ * This key should be kept separate from the master encryption key.
45
+ * * @returns A Promise resolving to an HMAC CryptoKey.
46
+ */
8
47
  export declare function generateBidxKey(): Promise<CryptoKey>;
9
- /** Generates a deterministic hash for database searching */
48
+ /** * Generates a deterministic hash for database searching without exposing plaintext.
49
+ * Safely extracts the underlying memory buffer to guarantee identical hashes
50
+ * across different JavaScript runtimes (Node.js, Browsers, Edge).
51
+ * * @param plaintext - The data to hash (e.g., an email address).
52
+ * @param key - The HMAC Blind Index CryptoKey.
53
+ * @returns A Promise resolving to a deterministic Base64 hash string.
54
+ */
10
55
  export declare function generateBlindIndex(plaintext: string, key: CryptoKey): Promise<string>;
11
56
  //# sourceMappingURL=crypto.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AA0B3C,wBAAsB,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC,CAKtD;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/D;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CASlE;AAED,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,SAAS,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,CAAC,CAsB3B;AAED,wBAAsB,OAAO,CAC3B,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,SAAS,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAsBjB;AAID,iEAAiE;AACjE,wBAAsB,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAK1D;AAED,4DAA4D;AAC5D,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,SAAS,GACb,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAqC3C;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,SAAS,CAAC,CAKtD;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/D;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CASlE;AAED;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,SAAS,EACd,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,CAAC,CAsB3B;AAED;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,wBAAwB;AAC5D,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CA6BjB;AAID;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAK1D;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,SAAS,GACb,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
package/dist/crypto.js CHANGED
@@ -1,6 +1,11 @@
1
1
  const ALGO = "AES-GCM";
2
2
  const KEY_LENGTH = 256;
3
- // Memory-safe Base64 conversion helpers
3
+ /**
4
+ * Safely converts an ArrayBuffer or Uint8Array to a Base64 string.
5
+ * Used internally to format ciphertexts, IVs, and exported keys for safe database storage.
6
+ * * @param buffer - The raw byte array to convert.
7
+ * @returns A Base64 encoded string.
8
+ */
4
9
  function bufferToBase64(buffer) {
5
10
  let binary = "";
6
11
  // Normalize to Uint8Array safely
@@ -11,6 +16,12 @@ function bufferToBase64(buffer) {
11
16
  }
12
17
  return btoa(binary);
13
18
  }
19
+ /**
20
+ * Converts a Base64 string back into a Uint8Array.
21
+ * Used internally to reconstruct buffers for decryption or key importing.
22
+ * * @param base64 - The Base64 encoded string.
23
+ * @returns A Uint8Array containing the raw bytes.
24
+ */
14
25
  function base64ToBuffer(base64) {
15
26
  const binaryString = atob(base64);
16
27
  const bytes = new Uint8Array(binaryString.length);
@@ -19,21 +30,46 @@ function base64ToBuffer(base64) {
19
30
  }
20
31
  return bytes;
21
32
  }
33
+ /**
34
+ * Generates a strong, 256-bit master key for AES-GCM encryption and decryption.
35
+ * * @returns A Promise resolving to a native Web Crypto API CryptoKey.
36
+ */
22
37
  export async function generateKey() {
23
38
  return crypto.subtle.generateKey({ name: ALGO, length: KEY_LENGTH }, true, [
24
39
  "encrypt",
25
40
  "decrypt",
26
41
  ]);
27
42
  }
43
+ /**
44
+ * Exports a CryptoKey into a raw Base64 string so it can be safely stored
45
+ * in an environment variable or Key Management Service (KMS).
46
+ * * @param key - The CryptoKey to export.
47
+ * @returns A Promise resolving to the Base64 representation of the key.
48
+ */
28
49
  export async function exportKey(key) {
29
50
  const raw = await crypto.subtle.exportKey("raw", key);
30
51
  return bufferToBase64(raw);
31
52
  }
53
+ /**
54
+ * Imports a Base64 string back into a usable CryptoKey for AES-GCM operations.
55
+ * * @param base64 - The Base64 encoded key string (usually from environment variables).
56
+ * @returns A Promise resolving to the imported CryptoKey.
57
+ */
32
58
  export async function importKey(base64) {
33
59
  const raw = base64ToBuffer(base64);
34
60
  return crypto.subtle.importKey("raw", raw, { name: ALGO, length: KEY_LENGTH }, true, ["encrypt", "decrypt"]);
35
61
  }
36
- export async function encrypt(plaintext, key, aadContext) {
62
+ /**
63
+ * Encrypts a plaintext string using AES-256-GCM.
64
+ * Automatically generates a unique 12-byte Initialization Vector (IV) and applies
65
+ * Contextual Binding (AAD) to tie the ciphertext to a specific database row.
66
+ * @param plaintext - The sensitive data to encrypt.
67
+ * @param key - The master AES-GCM CryptoKey.
68
+ * @param keyVersion - The string identifier for the active key (e.g., "v2").
69
+ * @param aadContext - The row ID or primary key to bind this ciphertext to.
70
+ * @returns A Promise resolving to an object containing the Base64 `ciphertext` and `iv`.
71
+ */
72
+ export async function encrypt(plaintext, key, keyVersion, aadContext) {
37
73
  const iv = crypto.getRandomValues(new Uint8Array(12)); // ALWAYS unique
38
74
  const encoded = new TextEncoder().encode(plaintext);
39
75
  const algorithm = {
@@ -44,9 +80,25 @@ export async function encrypt(plaintext, key, aadContext) {
44
80
  algorithm.additionalData = new TextEncoder().encode(aadContext);
45
81
  }
46
82
  const cipherBuffer = await crypto.subtle.encrypt(algorithm, key, encoded);
47
- return { ciphertext: bufferToBase64(cipherBuffer), iv: bufferToBase64(iv) };
83
+ return { version: keyVersion, ciphertext: bufferToBase64(cipherBuffer), iv: bufferToBase64(iv) };
48
84
  }
49
- export async function decrypt(payload, key, aadContext) {
85
+ /**
86
+ * Decrypts an AES-256-GCM payload back into plaintext.
87
+ * Supports Key Rotation by reading the payload's version and selecting the correct key.
88
+ * Strictly verifies the Context (AAD) to ensure data integrity.
89
+ *
90
+ * @param payload - The EncryptedPayload containing `version`, `ciphertext`, and `iv`.
91
+ * @param keyRing - A dictionary of historical and active CryptoKeys (e.g., { "v1": key1, "v2": key2 }).
92
+ * @param aadContext - The row ID or primary key that this ciphertext is bound to.
93
+ * @returns A Promise resolving to the decrypted plaintext string.
94
+ */
95
+ export async function decrypt(payload, keyRing, // Accepts multiple keys
96
+ aadContext) {
97
+ // Identify which key to use based on the payload's version tag
98
+ const targetKey = keyRing[payload.version];
99
+ if (!targetKey) {
100
+ throw new Error(`CRITICAL: Key version [${payload.version}] not found in provided KeyRing.`);
101
+ }
50
102
  const cipherBytes = base64ToBuffer(payload.ciphertext);
51
103
  const iv = base64ToBuffer(payload.iv);
52
104
  const algorithm = {
@@ -56,18 +108,28 @@ export async function decrypt(payload, key, aadContext) {
56
108
  if (aadContext) {
57
109
  algorithm.additionalData = new TextEncoder().encode(aadContext);
58
110
  }
59
- const decrypted = await crypto.subtle.decrypt(algorithm, key, cipherBytes);
111
+ const decrypted = await crypto.subtle.decrypt(algorithm, targetKey, // Use the dynamically selected key
112
+ cipherBytes);
60
113
  return new TextDecoder().decode(decrypted);
61
114
  }
62
115
  const HMAC_ALGO = "HMAC";
63
- /** Generates a dedicated key for deterministic Blind Indexing */
116
+ /** * Generates a dedicated HMAC-SHA256 key for deterministic Blind Indexing.
117
+ * This key should be kept separate from the master encryption key.
118
+ * * @returns A Promise resolving to an HMAC CryptoKey.
119
+ */
64
120
  export async function generateBidxKey() {
65
121
  return crypto.subtle.generateKey({ name: HMAC_ALGO, hash: "SHA-256" }, true, [
66
122
  "sign",
67
123
  "verify",
68
124
  ]);
69
125
  }
70
- /** Generates a deterministic hash for database searching */
126
+ /** * Generates a deterministic hash for database searching without exposing plaintext.
127
+ * Safely extracts the underlying memory buffer to guarantee identical hashes
128
+ * across different JavaScript runtimes (Node.js, Browsers, Edge).
129
+ * * @param plaintext - The data to hash (e.g., an email address).
130
+ * @param key - The HMAC Blind Index CryptoKey.
131
+ * @returns A Promise resolving to a deterministic Base64 hash string.
132
+ */
71
133
  export async function generateBlindIndex(plaintext, key) {
72
134
  const encoder = new TextEncoder();
73
135
  const encoded = encoder.encode(plaintext);
@@ -77,40 +139,4 @@ export async function generateBlindIndex(plaintext, key) {
77
139
  const signature = await crypto.subtle.sign("HMAC", key, cleanBuffer);
78
140
  return bufferToBase64(signature);
79
141
  }
80
- // import { EncryptedPayload } from "./types";
81
- // const ALGO = "AES-GCM";
82
- // const KEY_LENGTH = 256;
83
- // export async function generateKey(): Promise<CryptoKey> {
84
- // return crypto.subtle.generateKey(
85
- // { name: ALGO, length: KEY_LENGTH },
86
- // true,
87
- // ["encrypt", "decrypt"]
88
- // );
89
- // }
90
- // export async function exportKey(key: CryptoKey): Promise<string> {
91
- // const raw = await crypto.subtle.exportKey("raw", key);
92
- // return btoa(String.fromCharCode(...new Uint8Array(raw)));
93
- // }
94
- // export async function importKey(base64: string): Promise<CryptoKey> {
95
- // const raw = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
96
- // return crypto.subtle.importKey("raw", raw, { name: ALGO, length: KEY_LENGTH }, true, [
97
- // "encrypt",
98
- // "decrypt",
99
- // ]);
100
- // }
101
- // export async function encrypt(plaintext: string, key: CryptoKey, existingIv?: Uint8Array): Promise<EncryptedPayload> {
102
- // const iv = existingIv ? new Uint8Array(existingIv) : crypto.getRandomValues(new Uint8Array(12));
103
- // const encoded = new TextEncoder().encode(plaintext);
104
- // const cipherBuffer = await crypto.subtle.encrypt({ name: ALGO, iv }, key, encoded);
105
- // return {
106
- // ciphertext: btoa(String.fromCharCode(...new Uint8Array(cipherBuffer))),
107
- // iv: btoa(String.fromCharCode(...iv)),
108
- // };
109
- // }
110
- // export async function decrypt(payload: EncryptedPayload, key: CryptoKey): Promise<string> {
111
- // const cipherBytes = Uint8Array.from(atob(payload.ciphertext), (c) => c.charCodeAt(0));
112
- // const iv = Uint8Array.from(atob(payload.iv), (c) => c.charCodeAt(0));
113
- // const decrypted = await crypto.subtle.decrypt({ name: ALGO, iv }, key, cipherBytes);
114
- // return new TextDecoder().decode(decrypted);
115
- // }
116
142
  //# sourceMappingURL=crypto.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"AAEA,MAAM,IAAI,GAAG,SAAS,CAAC;AACvB,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB,wCAAwC;AACxC,SAAS,cAAc,CAAC,MAAgC;IACtD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,iCAAiC;IACjC,MAAM,KAAK,GAAG,MAAM,YAAY,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IAC7E,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC;IAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,cAAc,CAAC,MAAc;IACpC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,KAAK,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,OAAO,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE;QACzE,SAAS;QACT,SAAS;KACV,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAc;IAC5C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACtD,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAc;IAC5C,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACnC,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAC5B,KAAK,EACL,GAAmB,EACnB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,EAClC,IAAI,EACJ,CAAC,SAAS,EAAE,SAAS,CAAC,CACvB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,SAAiB,EACjB,GAAc,EACd,UAAkB;IAElB,MAAM,EAAE,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,gBAAgB;IACvE,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAEpD,MAAM,SAAS,GAAiB;QAC9B,IAAI,EAAE,IAAI;QACV,EAAE,EAAE,EAAkB;KACvB,CAAC;IAEF,IAAI,UAAU,EAAE,CAAC;QACf,SAAS,CAAC,cAAc,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CACjD,UAAU,CACK,CAAC;IACpB,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAC9C,SAAS,EACT,GAAG,EACH,OAAuB,CACxB,CAAC;IAEF,OAAO,EAAE,UAAU,EAAE,cAAc,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,EAAE,CAAC,EAAE,CAAC;AAC9E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,OAAyB,EACzB,GAAc,EACd,UAAkB;IAElB,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACvD,MAAM,EAAE,GAAG,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAEtC,MAAM,SAAS,GAAiB;QAC9B,IAAI,EAAE,IAAI;QACV,EAAE,EAAE,EAAkB;KACvB,CAAC;IAEF,IAAI,UAAU,EAAE,CAAC;QACf,SAAS,CAAC,cAAc,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CACjD,UAAU,CACK,CAAC;IACpB,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAC3C,SAAS,EACT,GAAG,EACH,WAA2B,CAC5B,CAAC;IAEF,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,SAAS,GAAG,MAAM,CAAC;AAEzB,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,OAAO,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE;QAC3E,MAAM;QACN,QAAQ;KACT,CAAC,CAAC;AACL,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,SAAiB,EACjB,GAAc;IAEd,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAE1C,8CAA8C;IAC9C,mFAAmF;IACnF,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CACtC,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CACxC,CAAC;IAEF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CACxC,MAAM,EACN,GAAG,EACH,WAA2B,CAC5B,CAAC;IAEF,OAAO,cAAc,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC;AAED,8CAA8C;AAE9C,0BAA0B;AAC1B,0BAA0B;AAE1B,4DAA4D;AAC5D,sCAAsC;AACtC,0CAA0C;AAC1C,YAAY;AACZ,6BAA6B;AAC7B,OAAO;AACP,IAAI;AAEJ,qEAAqE;AACrE,2DAA2D;AAC3D,8DAA8D;AAC9D,IAAI;AAEJ,wEAAwE;AACxE,uEAAuE;AACvE,2FAA2F;AAC3F,iBAAiB;AACjB,iBAAiB;AACjB,QAAQ;AACR,IAAI;AAEJ,yHAAyH;AACzH,qGAAqG;AACrG,yDAAyD;AACzD,wFAAwF;AACxF,aAAa;AACb,8EAA8E;AAC9E,4CAA4C;AAC5C,OAAO;AACP,IAAI;AAEJ,8FAA8F;AAC9F,2FAA2F;AAC3F,0EAA0E;AAC1E,yFAAyF;AACzF,gDAAgD;AAChD,IAAI"}
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../crypto.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { AegisClient } from "./client";
2
- export { generateKey, exportKey, importKey, encrypt, decrypt } from "./crypto";
2
+ export { generateKey, generateBidxKey, exportKey, importKey } from "./crypto";
3
3
  export { SupabaseAdapter } from "./adapters/supabase";
4
4
  export { MongoDBAdapter } from "./adapters/mongodb";
5
5
  export type { AegisConfig, EncryptedPayload, AegisKeyPair, DatabaseAdapter } from "./types";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { AegisClient } from "./client";
2
- export { generateKey, exportKey, importKey, encrypt, decrypt } from "./crypto";
2
+ export { generateKey, generateBidxKey, exportKey, importKey } from "./crypto";
3
3
  export { SupabaseAdapter } from "./adapters/supabase";
4
4
  export { MongoDBAdapter } from "./adapters/mongodb";
5
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/types.d.ts CHANGED
@@ -11,6 +11,17 @@ export interface DatabaseAdapter {
11
11
  data: Record<string, unknown>[] | null;
12
12
  error: unknown;
13
13
  }>;
14
+ update(table: string, data: Record<string, unknown>): Promise<{
15
+ data: any[] | null;
16
+ error: any;
17
+ }>;
18
+ delete(table: string, query: {
19
+ column: string;
20
+ value: unknown;
21
+ }): Promise<{
22
+ data: any[] | null;
23
+ error: any;
24
+ }>;
14
25
  }
15
26
  export interface AegisConfig {
16
27
  adapter: DatabaseAdapter;
@@ -19,6 +30,7 @@ export interface AegisConfig {
19
30
  bidxFields?: Record<string, string[]>;
20
31
  }
21
32
  export interface EncryptedPayload {
33
+ version: string;
22
34
  ciphertext: string;
23
35
  iv: string;
24
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1H,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC1J;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,eAAe,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1C,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,SAAS,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1H,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACzJ,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;IAClG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;CAC/G;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,eAAe,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1C,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,SAAS,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB"}
package/dist/types.js CHANGED
@@ -1,24 +1,2 @@
1
1
  export {};
2
- // /** Generic database adapter interface — implement this for any database. */
3
- // export interface DatabaseAdapter {
4
- // /** Insert a row into a table/collection. Returns the inserted data. */
5
- // insert(table: string, data: Record<string, unknown>): Promise<{ data: Record<string, unknown>[] | null; error: unknown }>;
6
- // /** Select rows from a table/collection with optional filters. */
7
- // select(
8
- // table: string,
9
- // query?: { column?: string; value?: unknown; limit?: number }
10
- // ): Promise<{ data: Record<string, unknown>[] | null; error: unknown }>;
11
- // }
12
- // export interface AegisConfig {
13
- // adapter: DatabaseAdapter;
14
- // encryptedFields: Record<string, string[]>;
15
- // }
16
- // export interface EncryptedPayload {
17
- // ciphertext: string;
18
- // iv: string;
19
- // }
20
- // export interface AegisKeyPair {
21
- // key: CryptoKey;
22
- // exported: string;
23
- // }
24
2
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":";AAqBA,+EAA+E;AAC/E,qCAAqC;AACrC,4EAA4E;AAC5E,+HAA+H;AAE/H,sEAAsE;AACtE,YAAY;AACZ,qBAAqB;AACrB,mEAAmE;AACnE,4EAA4E;AAC5E,IAAI;AAEJ,iCAAiC;AACjC,8BAA8B;AAC9B,+CAA+C;AAC/C,IAAI;AAEJ,sCAAsC;AACtC,wBAAwB;AACxB,gBAAgB;AAChB,IAAI;AAEJ,kCAAkC;AAClC,oBAAoB;AACpB,sBAAsB;AACtB,IAAI"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,7 +1,15 @@
1
1
  {
2
2
  "name": "aegis-lock",
3
- "version": "2.0.1",
3
+ "version": "2.2.0",
4
4
  "description": "Database-agnostic client-side AES-256-GCM field-level encryption. Works with Supabase, MongoDB, or any database via pluggable adapters.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/hritesh-saha/aegis-lock.git"
8
+ },
9
+ "bugs": {
10
+ "url": "https://github.com/hritesh-saha/aegis-lock/issues"
11
+ },
12
+ "homepage": "https://github.com/hritesh-saha/aegis-lock#readme",
5
13
  "type": "module",
6
14
  "main": "dist/index.js",
7
15
  "module": "dist/index.js",
@@ -50,6 +58,9 @@
50
58
  "peerDependenciesMeta": {
51
59
  "@supabase/supabase-js": {
52
60
  "optional": true
61
+ },
62
+ "mongodb": {
63
+ "optional": true
53
64
  }
54
65
  },
55
66
  "devDependencies": {
@@ -57,6 +68,7 @@
57
68
  "@types/jest": "^30.0.0",
58
69
  "@types/node": "^25.3.5",
59
70
  "jest": "^30.2.0",
71
+ "mongodb": "^7.1.1",
60
72
  "ts-jest": "^29.4.6",
61
73
  "typescript": "^5.9.3"
62
74
  }