@vollcrypt/db-guard 0.9.0 → 0.9.1

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.
@@ -1,28 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.computeBlindIndex = computeBlindIndex;
4
- const security_1 = require("./security");
5
- /**
6
- * Computes a hardened, frequency-resistant blind index for a database field.
7
- *
8
- * Uses HKDF-SHA256 to derive a unique column key from the root salt,
9
- * preventing cross-column frequency analysis. Zeroizes intermediate keys immediately.
10
- */
11
- function computeBlindIndex(value, rootSalt, columnName) {
12
- if (value === null || value === undefined)
13
- return value;
14
- const plaintext = typeof value === 'string' ? value : JSON.stringify(value);
15
- const columnNameBuf = Buffer.from(columnName, 'utf8');
16
- // 1. Derive column-specific key using HKDF-SHA256
17
- const derivedColumnKey = (0, security_1.deriveHkdf)(rootSalt, null, columnNameBuf, 32);
18
- try {
19
- // 2. Compute the final blind index using the derived column key
20
- const plaintextBuf = Buffer.from(plaintext, 'utf8');
21
- const blindIndex = (0, security_1.deriveHkdf)(derivedColumnKey, null, plaintextBuf, 32);
22
- return blindIndex.toString('hex');
23
- }
24
- finally {
25
- // 3. RAM Security: Zeroize the derived key immediately (Anti-Core Dump)
26
- derivedColumnKey.fill(0);
27
- }
28
- }
3
+ exports.computeBlindIndex = void 0;
4
+ var security_1 = require("./security");
5
+ Object.defineProperty(exports, "computeBlindIndex", { enumerable: true, get: function () { return security_1.computeBlindIndex; } });
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- const prisma_1 = require("./prisma");
4
+ const security_1 = require("./security");
5
5
  function printProgressBar(current, total) {
6
6
  const percentage = Math.min(100, Math.floor((current / total) * 100));
7
7
  const barLength = 40;
@@ -138,7 +138,7 @@ async function migratePostgres(url, table, column, idCol, key, version, chunkSiz
138
138
  // 3. Encrypt and update each row
139
139
  for (const row of batchRes.rows) {
140
140
  const rawVal = row[column];
141
- const encryptedVal = (0, prisma_1.encryptValue)(rawVal, key, version);
141
+ const encryptedVal = (0, security_1.encryptValue)(rawVal, key, version);
142
142
  await client.query(`UPDATE "${table}" SET "${column}" = $1 WHERE "${idCol}" = $2`, [encryptedVal, row[idCol]]);
143
143
  processed++;
144
144
  printProgressBar(processed, total);
@@ -190,7 +190,7 @@ async function migrateMongo(url, collectionName, field, idCol, key, version, chu
190
190
  }
191
191
  for (const doc of batch) {
192
192
  const rawVal = doc[field];
193
- const encryptedVal = (0, prisma_1.encryptValue)(rawVal, key, version);
193
+ const encryptedVal = (0, security_1.encryptValue)(rawVal, key, version);
194
194
  await collection.updateOne({ [idCol]: doc[idCol] }, { $set: { [field]: encryptedVal } });
195
195
  processed++;
196
196
  printProgressBar(processed, total);
package/dist/drivers.js CHANGED
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.wrapSqliteDatabase = wrapSqliteDatabase;
4
4
  exports.wrapOracleConnection = wrapOracleConnection;
5
- const prisma_js_1 = require("./prisma.js");
6
5
  const security_js_1 = require("./security.js");
7
6
  function getKeys(options) {
8
7
  let keys = {};
@@ -66,7 +65,7 @@ function decryptRow(row, table, keys, options) {
66
65
  const val = row[i];
67
66
  if (typeof val === 'string' && val.startsWith('VOLLVALT:')) {
68
67
  try {
69
- cloned[i] = (0, security_js_1.decryptWithSecurity)(val, (v) => (0, prisma_js_1.decryptValue)(v, keys), table, `column_${i}`, undefined, options);
68
+ cloned[i] = (0, security_js_1.decryptWithSecurity)(val, (v) => (0, security_js_1.decryptValue)(v, keys), table, `column_${i}`, undefined, options);
70
69
  }
71
70
  catch {
72
71
  // Keep original on failure
@@ -80,7 +79,7 @@ function decryptRow(row, table, keys, options) {
80
79
  for (const [key, val] of Object.entries(row)) {
81
80
  if (typeof val === 'string' && val.startsWith('VOLLVALT:')) {
82
81
  try {
83
- cloned[key] = (0, security_js_1.decryptWithSecurity)(val, (v) => (0, prisma_js_1.decryptValue)(v, keys), table, key, row.id || row._id, options);
82
+ cloned[key] = (0, security_js_1.decryptWithSecurity)(val, (v) => (0, security_js_1.decryptValue)(v, keys), table, key, row.id || row._id, options);
84
83
  }
85
84
  catch {
86
85
  // Keep original on failure
@@ -114,7 +113,7 @@ function wrapSqliteDatabase(db, options) {
114
113
  const arrayParams = params[0].map((param, index) => {
115
114
  const colName = columns[index];
116
115
  if (colName && fieldsToEncrypt.includes(colName)) {
117
- return (0, prisma_js_1.encryptValue)(param, activeKey, activeVersion);
116
+ return (0, security_js_1.encryptValue)(param, activeKey, activeVersion);
118
117
  }
119
118
  return param;
120
119
  });
@@ -127,7 +126,7 @@ function wrapSqliteDatabase(db, options) {
127
126
  // Strip prefix character (@, :, $) if present
128
127
  const cleanKey = key.replace(/^[@:$]/, '');
129
128
  if (fieldsToEncrypt.includes(cleanKey)) {
130
- obj[key] = (0, prisma_js_1.encryptValue)(val, activeKey, activeVersion);
129
+ obj[key] = (0, security_js_1.encryptValue)(val, activeKey, activeVersion);
131
130
  }
132
131
  }
133
132
  return [obj];
@@ -136,7 +135,7 @@ function wrapSqliteDatabase(db, options) {
136
135
  return params.map((param, index) => {
137
136
  const colName = columns[index];
138
137
  if (colName && fieldsToEncrypt.includes(colName)) {
139
- return (0, prisma_js_1.encryptValue)(param, activeKey, activeVersion);
138
+ return (0, security_js_1.encryptValue)(param, activeKey, activeVersion);
140
139
  }
141
140
  return param;
142
141
  });
@@ -192,7 +191,7 @@ function wrapOracleConnection(connection, options) {
192
191
  processedBinds = bindParams.map((param, index) => {
193
192
  const colName = columns[index];
194
193
  if (colName && fieldsToEncrypt.includes(colName)) {
195
- return (0, prisma_js_1.encryptValue)(param, activeKey, activeVersion);
194
+ return (0, security_js_1.encryptValue)(param, activeKey, activeVersion);
196
195
  }
197
196
  return param;
198
197
  });
@@ -201,7 +200,7 @@ function wrapOracleConnection(connection, options) {
201
200
  processedBinds = { ...bindParams };
202
201
  for (const field of fieldsToEncrypt) {
203
202
  if (processedBinds[field] !== undefined && processedBinds[field] !== null) {
204
- processedBinds[field] = (0, prisma_js_1.encryptValue)(processedBinds[field], activeKey, activeVersion);
203
+ processedBinds[field] = (0, security_js_1.encryptValue)(processedBinds[field], activeKey, activeVersion);
205
204
  }
206
205
  }
207
206
  }
package/dist/drizzle.js CHANGED
@@ -1,11 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createDrizzleGuard = void 0;
4
- const pg_core_1 = require("drizzle-orm/pg-core");
5
- const mysql_core_1 = require("drizzle-orm/mysql-core");
6
- const sqlite_core_1 = require("drizzle-orm/sqlite-core");
7
- const prisma_1 = require("./prisma");
8
- const blind_index_1 = require("./blind-index");
9
4
  const security_1 = require("./security");
10
5
  function getKeys(options) {
11
6
  let keys;
@@ -24,6 +19,9 @@ function getKeys(options) {
24
19
  return { keys, activeVersion };
25
20
  }
26
21
  const createDrizzleGuard = (options) => {
22
+ const pgCustomType = require('drizzle-orm/pg-core').customType;
23
+ const mysqlCustomType = require('drizzle-orm/mysql-core').customType;
24
+ const sqliteCustomType = require('drizzle-orm/sqlite-core').customType;
27
25
  const { keys, activeVersion } = getKeys(options);
28
26
  const activeKey = keys[activeVersion];
29
27
  if (!activeKey) {
@@ -32,49 +30,49 @@ const createDrizzleGuard = (options) => {
32
30
  (0, security_1.registerKeysForZeroization)(keys);
33
31
  const rootSalt = options.blindIndexes?.rootSalt;
34
32
  return {
35
- pgText: (name, columnPath) => (0, pg_core_1.customType)({
33
+ pgText: (name, columnPath) => pgCustomType({
36
34
  dataType() {
37
35
  return 'text';
38
36
  },
39
37
  toDriver(value) {
40
- return (0, prisma_1.encryptValue)(value, activeKey, activeVersion);
38
+ return (0, security_1.encryptValue)(value, activeKey, activeVersion);
41
39
  },
42
40
  fromDriver(value) {
43
41
  const parts = columnPath?.split('.') || [name];
44
42
  const mName = parts[0] || 'Model';
45
43
  const fName = parts[1] || name;
46
- return (0, security_1.decryptWithSecurity)(value, (val) => (0, prisma_1.decryptValue)(val, keys), mName, fName, undefined, options);
44
+ return (0, security_1.decryptWithSecurity)(value, (val) => (0, security_1.decryptValue)(val, keys), mName, fName, undefined, options);
47
45
  }
48
46
  })(name),
49
- mysqlText: (name, columnPath) => (0, mysql_core_1.customType)({
47
+ mysqlText: (name, columnPath) => mysqlCustomType({
50
48
  dataType() {
51
49
  return 'text';
52
50
  },
53
51
  toDriver(value) {
54
- return (0, prisma_1.encryptValue)(value, activeKey, activeVersion);
52
+ return (0, security_1.encryptValue)(value, activeKey, activeVersion);
55
53
  },
56
54
  fromDriver(value) {
57
55
  const parts = columnPath?.split('.') || [name];
58
56
  const mName = parts[0] || 'Model';
59
57
  const fName = parts[1] || name;
60
- return (0, security_1.decryptWithSecurity)(value, (val) => (0, prisma_1.decryptValue)(val, keys), mName, fName, undefined, options);
58
+ return (0, security_1.decryptWithSecurity)(value, (val) => (0, security_1.decryptValue)(val, keys), mName, fName, undefined, options);
61
59
  }
62
60
  })(name),
63
- sqliteText: (name, columnPath) => (0, sqlite_core_1.customType)({
61
+ sqliteText: (name, columnPath) => sqliteCustomType({
64
62
  dataType() {
65
63
  return 'text';
66
64
  },
67
65
  toDriver(value) {
68
- return (0, prisma_1.encryptValue)(value, activeKey, activeVersion);
66
+ return (0, security_1.encryptValue)(value, activeKey, activeVersion);
69
67
  },
70
68
  fromDriver(value) {
71
69
  const parts = columnPath?.split('.') || [name];
72
70
  const mName = parts[0] || 'Model';
73
71
  const fName = parts[1] || name;
74
- return (0, security_1.decryptWithSecurity)(value, (val) => (0, prisma_1.decryptValue)(val, keys), mName, fName, undefined, options);
72
+ return (0, security_1.decryptWithSecurity)(value, (val) => (0, security_1.decryptValue)(val, keys), mName, fName, undefined, options);
75
73
  }
76
74
  })(name),
77
- pgBlindIndex: (name, columnName) => (0, pg_core_1.customType)({
75
+ pgBlindIndex: (name, columnName) => pgCustomType({
78
76
  dataType() {
79
77
  return 'text';
80
78
  },
@@ -82,13 +80,13 @@ const createDrizzleGuard = (options) => {
82
80
  if (!rootSalt) {
83
81
  throw new Error('Blind index root salt is not configured in Drizzle guard options.');
84
82
  }
85
- return (0, blind_index_1.computeBlindIndex)(value, rootSalt, columnName);
83
+ return (0, security_1.computeBlindIndex)(value, rootSalt, columnName);
86
84
  },
87
85
  fromDriver(value) {
88
86
  return value;
89
87
  }
90
88
  })(name),
91
- mysqlBlindIndex: (name, columnName) => (0, mysql_core_1.customType)({
89
+ mysqlBlindIndex: (name, columnName) => mysqlCustomType({
92
90
  dataType() {
93
91
  return 'text';
94
92
  },
@@ -96,13 +94,13 @@ const createDrizzleGuard = (options) => {
96
94
  if (!rootSalt) {
97
95
  throw new Error('Blind index root salt is not configured in Drizzle guard options.');
98
96
  }
99
- return (0, blind_index_1.computeBlindIndex)(value, rootSalt, columnName);
97
+ return (0, security_1.computeBlindIndex)(value, rootSalt, columnName);
100
98
  },
101
99
  fromDriver(value) {
102
100
  return value;
103
101
  }
104
102
  })(name),
105
- sqliteBlindIndex: (name, columnName) => (0, sqlite_core_1.customType)({
103
+ sqliteBlindIndex: (name, columnName) => sqliteCustomType({
106
104
  dataType() {
107
105
  return 'text';
108
106
  },
@@ -110,7 +108,7 @@ const createDrizzleGuard = (options) => {
110
108
  if (!rootSalt) {
111
109
  throw new Error('Blind index root salt is not configured in Drizzle guard options.');
112
110
  }
113
- return (0, blind_index_1.computeBlindIndex)(value, rootSalt, columnName);
111
+ return (0, security_1.computeBlindIndex)(value, rootSalt, columnName);
114
112
  },
115
113
  fromDriver(value) {
116
114
  return value;
package/dist/index.d.ts CHANGED
@@ -1,9 +1,5 @@
1
- export { prismaDbGuard, PrismaDbGuardOptions, encryptValue, decryptValue, resolveKeys } from './prisma';
2
- export { mongooseDbGuard, MongooseDbGuardOptions } from './mongoose';
3
- export { createDrizzleGuard } from './drizzle';
4
- export { createTypeOrmSubscriber } from './typeorm';
5
1
  export { wrapSqliteDatabase, wrapOracleConnection, DbGuardDriverOptions } from './drivers';
6
- export { KmsProvider, AwsKmsProvider, GcpKmsProvider, VaultKmsProvider, unwrapDekLocal, Pkcs11KmsProvider } from './kms';
2
+ export { KmsProvider, AwsKmsProvider, GcpKmsProvider, VaultKmsProvider, unwrapDekLocal, Pkcs11KmsProvider, resolveKeys, DbGuardKeysOptions } from './kms';
7
3
  export { computeBlindIndex } from './blind-index';
8
- export { dbGuardContextStore, configureAuditLogger, decryptWithSecurity, checkRateLimit, checkPageSize, resetFailClosedStatusForTesting, resetAuditLoggerForTesting, getCachedKey, setCachedKey, resetSecureKeyCacheForTesting, configureBreakGlass, deactivateBreakGlass, isBreakGlassActive, getBreakGlassKey, activateBreakGlass, parseCiphertext, CRYPTO_ALGORITHMS, VERSION_ALGORITHMS, maskValue } from './security';
4
+ export { dbGuardContextStore, configureAuditLogger, decryptWithSecurity, checkRateLimit, checkPageSize, resetFailClosedStatusForTesting, resetAuditLoggerForTesting, getCachedKey, setCachedKey, resetSecureKeyCacheForTesting, configureBreakGlass, deactivateBreakGlass, isBreakGlassActive, getBreakGlassKey, activateBreakGlass, parseCiphertext, CRYPTO_ALGORITHMS, VERSION_ALGORITHMS, maskValue, encryptValue, decryptValue } from './security';
9
5
  export { auditConfiguration, generateComplianceHtmlReport, ComplianceAuditInput, ComplianceScorecard } from './compliance';
package/dist/index.js CHANGED
@@ -1,17 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateComplianceHtmlReport = exports.auditConfiguration = exports.maskValue = exports.VERSION_ALGORITHMS = exports.CRYPTO_ALGORITHMS = exports.parseCiphertext = exports.activateBreakGlass = exports.getBreakGlassKey = exports.isBreakGlassActive = exports.deactivateBreakGlass = exports.configureBreakGlass = exports.resetSecureKeyCacheForTesting = exports.setCachedKey = exports.getCachedKey = exports.resetAuditLoggerForTesting = exports.resetFailClosedStatusForTesting = exports.checkPageSize = exports.checkRateLimit = exports.decryptWithSecurity = exports.configureAuditLogger = exports.dbGuardContextStore = exports.computeBlindIndex = exports.Pkcs11KmsProvider = exports.unwrapDekLocal = exports.VaultKmsProvider = exports.GcpKmsProvider = exports.AwsKmsProvider = exports.wrapOracleConnection = exports.wrapSqliteDatabase = exports.createTypeOrmSubscriber = exports.createDrizzleGuard = exports.mongooseDbGuard = exports.resolveKeys = exports.decryptValue = exports.encryptValue = exports.prismaDbGuard = void 0;
4
- var prisma_1 = require("./prisma");
5
- Object.defineProperty(exports, "prismaDbGuard", { enumerable: true, get: function () { return prisma_1.prismaDbGuard; } });
6
- Object.defineProperty(exports, "encryptValue", { enumerable: true, get: function () { return prisma_1.encryptValue; } });
7
- Object.defineProperty(exports, "decryptValue", { enumerable: true, get: function () { return prisma_1.decryptValue; } });
8
- Object.defineProperty(exports, "resolveKeys", { enumerable: true, get: function () { return prisma_1.resolveKeys; } });
9
- var mongoose_1 = require("./mongoose");
10
- Object.defineProperty(exports, "mongooseDbGuard", { enumerable: true, get: function () { return mongoose_1.mongooseDbGuard; } });
11
- var drizzle_1 = require("./drizzle");
12
- Object.defineProperty(exports, "createDrizzleGuard", { enumerable: true, get: function () { return drizzle_1.createDrizzleGuard; } });
13
- var typeorm_1 = require("./typeorm");
14
- Object.defineProperty(exports, "createTypeOrmSubscriber", { enumerable: true, get: function () { return typeorm_1.createTypeOrmSubscriber; } });
3
+ exports.generateComplianceHtmlReport = exports.auditConfiguration = exports.decryptValue = exports.encryptValue = exports.maskValue = exports.VERSION_ALGORITHMS = exports.CRYPTO_ALGORITHMS = exports.parseCiphertext = exports.activateBreakGlass = exports.getBreakGlassKey = exports.isBreakGlassActive = exports.deactivateBreakGlass = exports.configureBreakGlass = exports.resetSecureKeyCacheForTesting = exports.setCachedKey = exports.getCachedKey = exports.resetAuditLoggerForTesting = exports.resetFailClosedStatusForTesting = exports.checkPageSize = exports.checkRateLimit = exports.decryptWithSecurity = exports.configureAuditLogger = exports.dbGuardContextStore = exports.computeBlindIndex = exports.resolveKeys = exports.Pkcs11KmsProvider = exports.unwrapDekLocal = exports.VaultKmsProvider = exports.GcpKmsProvider = exports.AwsKmsProvider = exports.wrapOracleConnection = exports.wrapSqliteDatabase = void 0;
15
4
  var drivers_1 = require("./drivers");
16
5
  Object.defineProperty(exports, "wrapSqliteDatabase", { enumerable: true, get: function () { return drivers_1.wrapSqliteDatabase; } });
17
6
  Object.defineProperty(exports, "wrapOracleConnection", { enumerable: true, get: function () { return drivers_1.wrapOracleConnection; } });
@@ -21,6 +10,7 @@ Object.defineProperty(exports, "GcpKmsProvider", { enumerable: true, get: functi
21
10
  Object.defineProperty(exports, "VaultKmsProvider", { enumerable: true, get: function () { return kms_1.VaultKmsProvider; } });
22
11
  Object.defineProperty(exports, "unwrapDekLocal", { enumerable: true, get: function () { return kms_1.unwrapDekLocal; } });
23
12
  Object.defineProperty(exports, "Pkcs11KmsProvider", { enumerable: true, get: function () { return kms_1.Pkcs11KmsProvider; } });
13
+ Object.defineProperty(exports, "resolveKeys", { enumerable: true, get: function () { return kms_1.resolveKeys; } });
24
14
  var blind_index_1 = require("./blind-index");
25
15
  Object.defineProperty(exports, "computeBlindIndex", { enumerable: true, get: function () { return blind_index_1.computeBlindIndex; } });
26
16
  var security_1 = require("./security");
@@ -43,6 +33,8 @@ Object.defineProperty(exports, "parseCiphertext", { enumerable: true, get: funct
43
33
  Object.defineProperty(exports, "CRYPTO_ALGORITHMS", { enumerable: true, get: function () { return security_1.CRYPTO_ALGORITHMS; } });
44
34
  Object.defineProperty(exports, "VERSION_ALGORITHMS", { enumerable: true, get: function () { return security_1.VERSION_ALGORITHMS; } });
45
35
  Object.defineProperty(exports, "maskValue", { enumerable: true, get: function () { return security_1.maskValue; } });
36
+ Object.defineProperty(exports, "encryptValue", { enumerable: true, get: function () { return security_1.encryptValue; } });
37
+ Object.defineProperty(exports, "decryptValue", { enumerable: true, get: function () { return security_1.decryptValue; } });
46
38
  var compliance_1 = require("./compliance");
47
39
  Object.defineProperty(exports, "auditConfiguration", { enumerable: true, get: function () { return compliance_1.auditConfiguration; } });
48
40
  Object.defineProperty(exports, "generateComplianceHtmlReport", { enumerable: true, get: function () { return compliance_1.generateComplianceHtmlReport; } });
package/dist/kms.d.ts CHANGED
@@ -44,3 +44,13 @@ export declare class Pkcs11KmsProvider implements KmsProvider {
44
44
  });
45
45
  decrypt(ciphertext: Buffer): Promise<Buffer>;
46
46
  }
47
+ export interface DbGuardKeysOptions {
48
+ key?: Buffer | Record<string, Buffer>;
49
+ kms?: {
50
+ provider: KmsProvider;
51
+ wrappedKey: Buffer | Record<string, Buffer>;
52
+ wrappedKek?: Buffer | Record<string, Buffer>;
53
+ activeKeyVersion?: string;
54
+ };
55
+ }
56
+ export declare function resolveKeys(options: DbGuardKeysOptions): Promise<Record<string, Buffer>>;
package/dist/kms.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Pkcs11KmsProvider = exports.VaultKmsProvider = exports.GcpKmsProvider = exports.AwsKmsProvider = void 0;
4
4
  exports.unwrapDekLocal = unwrapDekLocal;
5
+ exports.resolveKeys = resolveKeys;
5
6
  const security_1 = require("./security");
6
7
  class AwsKmsProvider {
7
8
  config;
@@ -158,3 +159,52 @@ class Pkcs11KmsProvider {
158
159
  }
159
160
  }
160
161
  exports.Pkcs11KmsProvider = Pkcs11KmsProvider;
162
+ async function resolveKeys(options) {
163
+ let rawKeys = {};
164
+ if (options.key) {
165
+ if (Buffer.isBuffer(options.key)) {
166
+ rawKeys = { '1': options.key };
167
+ }
168
+ else {
169
+ rawKeys = { ...options.key };
170
+ }
171
+ }
172
+ else if (options.kms) {
173
+ const { provider, wrappedKey, wrappedKek } = options.kms;
174
+ if (Buffer.isBuffer(wrappedKey)) {
175
+ if (wrappedKek && Buffer.isBuffer(wrappedKek)) {
176
+ const unwrappedKek = await provider.decrypt(wrappedKek);
177
+ const dek = unwrapDekLocal(wrappedKey, unwrappedKek);
178
+ unwrappedKek.fill(0); // RAM Security: zeroize KEK immediately
179
+ rawKeys = { '1': dek };
180
+ }
181
+ else {
182
+ const key = await provider.decrypt(wrappedKey);
183
+ rawKeys = { '1': key };
184
+ }
185
+ }
186
+ else {
187
+ for (const [ver, wrapped] of Object.entries(wrappedKey)) {
188
+ if (wrappedKek) {
189
+ const wKek = Buffer.isBuffer(wrappedKek) ? wrappedKek : wrappedKek[ver];
190
+ if (wKek) {
191
+ const unwrappedKek = await provider.decrypt(wKek);
192
+ const dek = unwrapDekLocal(wrapped, unwrappedKek);
193
+ unwrappedKek.fill(0); // RAM Security: zeroize KEK immediately
194
+ rawKeys[ver] = dek;
195
+ }
196
+ else {
197
+ rawKeys[ver] = await provider.decrypt(wrapped);
198
+ }
199
+ }
200
+ else {
201
+ rawKeys[ver] = await provider.decrypt(wrapped);
202
+ }
203
+ }
204
+ }
205
+ }
206
+ else {
207
+ throw new Error("Either 'key' or 'kms' configuration must be provided.");
208
+ }
209
+ return rawKeys;
210
+ }
@@ -1,4 +1,4 @@
1
- import { Schema } from 'mongoose';
1
+ import type { Schema } from 'mongoose';
2
2
  import { RateLimiterOptions } from './security';
3
3
  export interface MongooseDbGuardOptions {
4
4
  key: Buffer | Record<string, Buffer>;
package/dist/mongoose.js CHANGED
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mongooseDbGuard = mongooseDbGuard;
4
- const prisma_1 = require("./prisma");
5
- const blind_index_1 = require("./blind-index");
4
+ const kms_1 = require("./kms");
6
5
  const security_1 = require("./security");
7
6
  function mongooseDbGuard(schema, options) {
8
7
  const { fields } = options;
@@ -58,7 +57,7 @@ function mongooseDbGuard(schema, options) {
58
57
  if (!tenantConfig) {
59
58
  throw new Error(`Vollcrypt Security: Configuration not found for tenantId "${tId}".`);
60
59
  }
61
- const resolvedTenantKeysRaw = await (0, prisma_1.resolveKeys)({
60
+ const resolvedTenantKeysRaw = await (0, kms_1.resolveKeys)({
62
61
  ...options,
63
62
  key: tenantConfig.key,
64
63
  kms: tenantConfig.kms
@@ -89,7 +88,7 @@ function mongooseDbGuard(schema, options) {
89
88
  // 1. Encrypt fields
90
89
  for (const field of fields) {
91
90
  if (doc.isModified(field) && doc[field] !== undefined && doc[field] !== null) {
92
- doc[field] = (0, prisma_1.encryptValue)(doc[field], resolved.activeKey, resolved.activeVersion);
91
+ doc[field] = (0, security_1.encryptValue)(doc[field], resolved.activeKey, resolved.activeVersion);
93
92
  }
94
93
  }
95
94
  // 2. Compute blind indexes
@@ -99,9 +98,9 @@ function mongooseDbGuard(schema, options) {
99
98
  const bidxField = `${field}_bidx`;
100
99
  // Decrypt temporary value if it was already encrypted in the previous step
101
100
  const rawVal = doc.isModified(field) && doc[field].startsWith('VOLLVALT:')
102
- ? (0, prisma_1.decryptValue)(doc[field], keys)
101
+ ? (0, security_1.decryptValue)(doc[field], keys)
103
102
  : doc[field];
104
- doc[bidxField] = (0, blind_index_1.computeBlindIndex)(rawVal, options.blindIndexes.rootSalt, `${modelName}.${field}`);
103
+ doc[bidxField] = (0, security_1.computeBlindIndex)(rawVal, options.blindIndexes.rootSalt, `${modelName}.${field}`);
105
104
  }
106
105
  }
107
106
  }
@@ -138,9 +137,9 @@ function mongooseDbGuard(schema, options) {
138
137
  if (obj[currentPart] !== undefined && obj[currentPart] !== null) {
139
138
  if (options.blindIndexes && options.blindIndexes.fields.includes(fullPath) && options.blindIndexes.rootSalt) {
140
139
  const bidxField = `${currentPart}_bidx`;
141
- obj[bidxField] = (0, blind_index_1.computeBlindIndex)(obj[currentPart], options.blindIndexes.rootSalt, `${modelName}.${fullPath}`);
140
+ obj[bidxField] = (0, security_1.computeBlindIndex)(obj[currentPart], options.blindIndexes.rootSalt, `${modelName}.${fullPath}`);
142
141
  }
143
- obj[currentPart] = (0, prisma_1.encryptValue)(obj[currentPart], encKey, encVer);
142
+ obj[currentPart] = (0, security_1.encryptValue)(obj[currentPart], encKey, encVer);
144
143
  }
145
144
  }
146
145
  else {
@@ -151,9 +150,9 @@ function mongooseDbGuard(schema, options) {
151
150
  if (obj[dotNotatedPath] !== undefined && obj[dotNotatedPath] !== null) {
152
151
  if (options.blindIndexes && options.blindIndexes.fields.includes(fullPath) && options.blindIndexes.rootSalt) {
153
152
  const bidxField = `${dotNotatedPath}_bidx`;
154
- obj[bidxField] = (0, blind_index_1.computeBlindIndex)(obj[dotNotatedPath], options.blindIndexes.rootSalt, `${modelName}.${fullPath}`);
153
+ obj[bidxField] = (0, security_1.computeBlindIndex)(obj[dotNotatedPath], options.blindIndexes.rootSalt, `${modelName}.${fullPath}`);
155
154
  }
156
- obj[dotNotatedPath] = (0, prisma_1.encryptValue)(obj[dotNotatedPath], encKey, encVer);
155
+ obj[dotNotatedPath] = (0, security_1.encryptValue)(obj[dotNotatedPath], encKey, encVer);
157
156
  }
158
157
  }
159
158
  };
@@ -188,7 +187,7 @@ function mongooseDbGuard(schema, options) {
188
187
  // 2. Process query criteria (rewrite exact match search queries on conditions)
189
188
  const conditions = typeof query.getQuery === 'function' ? query.getQuery() : null;
190
189
  if (conditions && options.blindIndexes && options.blindIndexes.rootSalt) {
191
- (0, prisma_1.rewriteQueryWhere)(conditions, options.blindIndexes.fields, options.blindIndexes.rootSalt, modelName);
190
+ (0, security_1.rewriteQueryWhere)(conditions, options.blindIndexes.fields, options.blindIndexes.rootSalt, modelName);
192
191
  }
193
192
  if (typeof next === 'function') {
194
193
  next();
@@ -220,7 +219,7 @@ function mongooseDbGuard(schema, options) {
220
219
  const modelName = options.blindIndexes?.modelName || query.model?.modelName || 'Model';
221
220
  const conditions = typeof query.getQuery === 'function' ? query.getQuery() : null;
222
221
  if (conditions && options.blindIndexes && options.blindIndexes.rootSalt) {
223
- (0, prisma_1.rewriteQueryWhere)(conditions, options.blindIndexes.fields, options.blindIndexes.rootSalt, modelName);
222
+ (0, security_1.rewriteQueryWhere)(conditions, options.blindIndexes.fields, options.blindIndexes.rootSalt, modelName);
224
223
  }
225
224
  next();
226
225
  });
@@ -232,7 +231,7 @@ function mongooseDbGuard(schema, options) {
232
231
  for (const field of fields) {
233
232
  if (doc[field] !== undefined && doc[field] !== null) {
234
233
  try {
235
- doc[field] = (0, security_1.decryptWithSecurity)(doc[field], (val) => (0, prisma_1.decryptValue)(val, decKeys), modelName, field, doc.id || doc._id, options);
234
+ doc[field] = (0, security_1.decryptWithSecurity)(doc[field], (val) => (0, security_1.decryptValue)(val, decKeys), modelName, field, doc.id || doc._id, options);
236
235
  }
237
236
  catch (err) {
238
237
  throw new Error(`Mongoose db-guard failed to decrypt field "${field}": ${err.message}`);
package/dist/prisma.d.ts CHANGED
@@ -1,13 +1,6 @@
1
- import { KmsProvider } from './kms';
1
+ import { DbGuardKeysOptions } from './kms';
2
2
  import { RateLimiterOptions } from './security';
3
- export interface PrismaDbGuardOptions {
4
- key?: Buffer | Record<string, Buffer>;
5
- kms?: {
6
- provider: KmsProvider;
7
- wrappedKey: Buffer | Record<string, Buffer>;
8
- wrappedKek?: Buffer | Record<string, Buffer>;
9
- activeKeyVersion?: string;
10
- };
3
+ export interface PrismaDbGuardOptions extends DbGuardKeysOptions {
11
4
  models: Record<string, string[]>;
12
5
  blindIndexes?: {
13
6
  rootSalt: Buffer;
@@ -31,24 +24,11 @@ export interface PrismaDbGuardOptions {
31
24
  } | undefined>;
32
25
  };
33
26
  }
34
- /**
35
- * Resolves the plaintext keys asynchronously from local config or KMS provider.
36
- */
37
- export declare function resolveKeys(options: PrismaDbGuardOptions): Promise<Record<string, Buffer>>;
38
- export declare function encryptValue(val: any, key: Buffer, version: string): string;
39
- export declare function decryptValue(stored: any, keys: Record<string, Buffer>): any;
40
- /**
41
- * Traverses query `where` arguments to rewrite exact match queries on encrypted fields
42
- * to target shadow `_bidx` columns using dynamic HKDF-SHA256 blind indexing.
43
- */
44
- export declare function rewriteQueryWhere(where: any, fields: string[], rootSalt: Buffer, modelName: string): void;
45
- /**
46
- * Appends calculated blind indexes to the write payload (create/update).
47
- */
48
- export declare function addBlindIndexes(data: any, fields: string[], rootSalt: Buffer, modelName: string): void;
49
27
  /**
50
28
  * Prisma DbGuard Extension Factory
51
29
  *
52
30
  * Bootstraps client-level field encryption, query translation, and automatic decryption.
53
31
  */
54
32
  export declare const prismaDbGuard: (options: PrismaDbGuardOptions, resolvedKeys?: Record<string, Buffer>) => (client: any) => import("@prisma/client").PrismaClientExtends<import("@prisma/client/runtime/library").InternalArgs<{}, {}, {}, {}> & import("@prisma/client/runtime/library").DefaultArgs>;
33
+ export { encryptValue, decryptValue, rewriteQueryWhere, addBlindIndexes } from './security';
34
+ export { resolveKeys } from './kms';