@northstartech/cipher 0.0.0-stage → 1.0.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.
Files changed (41) hide show
  1. package/README.md +541 -2
  2. package/dist/client.d.ts +237 -0
  3. package/dist/client.js +555 -0
  4. package/dist/client.js.map +1 -0
  5. package/dist/crypto.d.ts +72 -0
  6. package/dist/crypto.js +244 -0
  7. package/dist/crypto.js.map +1 -0
  8. package/dist/encoding.d.ts +17 -0
  9. package/dist/encoding.js +79 -0
  10. package/dist/encoding.js.map +1 -0
  11. package/dist/errors.d.ts +14 -0
  12. package/dist/errors.js +22 -0
  13. package/dist/errors.js.map +1 -0
  14. package/dist/index.d.ts +8 -0
  15. package/dist/index.js +6 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/integrations/drizzle.d.ts +96 -0
  18. package/dist/integrations/drizzle.js +285 -0
  19. package/dist/integrations/drizzle.js.map +1 -0
  20. package/dist/integrations/mongoose.d.ts +72 -0
  21. package/dist/integrations/mongoose.js +582 -0
  22. package/dist/integrations/mongoose.js.map +1 -0
  23. package/dist/integrations/prisma.d.ts +65 -0
  24. package/dist/integrations/prisma.js +588 -0
  25. package/dist/integrations/prisma.js.map +1 -0
  26. package/dist/integrations/sequelize.d.ts +62 -0
  27. package/dist/integrations/sequelize.js +677 -0
  28. package/dist/integrations/sequelize.js.map +1 -0
  29. package/dist/integrations/shared.d.ts +268 -0
  30. package/dist/integrations/shared.js +513 -0
  31. package/dist/integrations/shared.js.map +1 -0
  32. package/dist/integrations/typeorm.d.ts +109 -0
  33. package/dist/integrations/typeorm.js +457 -0
  34. package/dist/integrations/typeorm.js.map +1 -0
  35. package/dist/object.d.ts +53 -0
  36. package/dist/object.js +226 -0
  37. package/dist/object.js.map +1 -0
  38. package/dist/search.d.ts +250 -0
  39. package/dist/search.js +258 -0
  40. package/dist/search.js.map +1 -0
  41. package/package.json +101 -4
@@ -0,0 +1,457 @@
1
+ /**
2
+ * TypeORM integration: an `@Encrypted()` property decorator and an entity subscriber.
3
+ *
4
+ * ```ts
5
+ * import { Encrypted, northstarCipherSubscriber, cipherWhere } from '@northstartech/cipher/typeorm'
6
+ *
7
+ * @Entity('todos')
8
+ * class Todo {
9
+ * @PrimaryGeneratedColumn('uuid') id!: string
10
+ * @Encrypted() @Column({ type: 'text', nullable: true }) title!: string | null
11
+ * @Encrypted({ searchable: 'email' }) @Column({ type: 'text', nullable: true }) email!: string | null
12
+ * @Index() @Column({ type: 'varchar', length: 64, nullable: true }) email_bidx!: string | null
13
+ * }
14
+ *
15
+ * const ds = new DataSource({ …, entities: [Todo], subscribers: [northstarCipherSubscriber(cipher)] })
16
+ * await ds.getRepository(Todo).save({ title: 'Buy milk', email: 'ana@example.com' })
17
+ * const todos = await ds.getRepository(Todo).find() // afterLoad decrypts in one batch request
18
+ * const mine = await ds.getRepository(Todo).findBy(await cipherWhere(ds, Todo, 'email', 'ANA@example.com'))
19
+ * ```
20
+ *
21
+ * Record ids: `uuid` primary keys are generated client-side before the insert;
22
+ * generated integer keys (increment/identity/rowid) use the two-phase write
23
+ * (sentinel, then ciphertext in `afterInsert`, inside `save()`'s transaction).
24
+ *
25
+ * Northstar Search: `northstarCipherSubscriber(cipher, { search: [{ entity: Todo, index: cipher.index('todos'), fields: ['title', 'email'] }] })`
26
+ * keeps an index in sync after each transaction commits (encrypted properties are
27
+ * indexed from their stored ciphertext, which the enclave decrypts);
28
+ * `searchDocuments(ds, Todo, rows, fields)` builds documents for a (re)index.
29
+ */
30
+ import { EventSubscriber, In, } from 'typeorm';
31
+ import { CipherError } from '../errors.js';
32
+ import { INDEX_SUFFIX, PENDING_SENTINEL, PlaintextLedger, SearchChangeSet, applySearchChange, configError, decryptOne, encryptCoalescer, isCiphertext, normalizeFieldSpec, normalizeSearchSync, plaintextOf, recordIdOf, requestError, searchDocumentOf, searchTokensFor, } from './shared.js';
33
+ export { CIPHERTEXT_PREFIX, PENDING_SENTINEL } from './shared.js';
34
+ /** Decorated properties per class (inherited through the prototype chain). */
35
+ const decorated = new Map();
36
+ /**
37
+ * Mark an entity property as encrypted. Use with a text column:
38
+ * `@Encrypted() @Column({ type: 'text', nullable: true }) title!: string | null`.
39
+ * Searchable properties need a `<property>_bidx` varchar(64) column (or `indexField`).
40
+ */
41
+ export function Encrypted(options = {}) {
42
+ normalizeFieldSpec(Object.keys(options).length ? options : true, 'TypeORM: @Encrypted()');
43
+ return (target, propertyKey) => {
44
+ if (typeof propertyKey !== 'string')
45
+ throw configError('TypeORM: @Encrypted() needs a string property name');
46
+ const ctor = target.constructor;
47
+ let m = decorated.get(ctor);
48
+ if (!m)
49
+ decorated.set(ctor, (m = new Map()));
50
+ m.set(propertyKey, options);
51
+ };
52
+ }
53
+ const STRING_COLUMN_TYPES = new Set([
54
+ 'text', 'varchar', 'character varying', 'nvarchar', 'national varchar', 'ntext', 'tinytext', 'mediumtext', 'longtext',
55
+ 'char', 'nchar', 'character', 'citext', 'clob', 'nclob', 'string', 'varchar2', 'nvarchar2', 'shorttext', 'alphanum',
56
+ ]);
57
+ const plans = new WeakMap();
58
+ function decoratedProps(target) {
59
+ const out = new Map();
60
+ const chain = [];
61
+ for (let c = target; typeof c === 'function' && c !== Function.prototype; c = Object.getPrototypeOf(c))
62
+ chain.unshift(c);
63
+ for (const c of chain)
64
+ for (const [k, v] of decorated.get(c) ?? [])
65
+ out.set(k, v);
66
+ return out;
67
+ }
68
+ function planFor(metadata) {
69
+ const cached = plans.get(metadata);
70
+ if (cached !== undefined)
71
+ return cached;
72
+ const props = decoratedProps(metadata.target);
73
+ if (!props.size) {
74
+ plans.set(metadata, null);
75
+ return null;
76
+ }
77
+ const name = metadata.name;
78
+ if (metadata.primaryColumns.length !== 1)
79
+ throw configError(`TypeORM: ${name} must have exactly one primary column to bind ciphertext to records`);
80
+ const pkCol = metadata.primaryColumns[0];
81
+ const fields = [];
82
+ for (const [prop, opts] of props) {
83
+ const lb = `TypeORM: ${name}.${prop}`;
84
+ const col = metadata.findColumnWithPropertyPath(prop);
85
+ if (!col)
86
+ throw configError(`${lb}: @Encrypted() properties need a @Column()`);
87
+ if (col === pkCol)
88
+ throw configError(`${lb}: the primary key cannot be encrypted`);
89
+ const t = col.type;
90
+ if (!(t === String || (typeof t === 'string' && STRING_COLUMN_TYPES.has(t.toLowerCase()))))
91
+ throw configError(`${lb}: encrypted columns must be text (got ${String(typeof t === 'function' ? t.name : t)})`);
92
+ const n = normalizeFieldSpec(Object.keys(opts).length ? opts : true, lb);
93
+ let indexProp;
94
+ if (n.searchable) {
95
+ indexProp = n.indexField ?? [`${prop}${INDEX_SUFFIX}`, `${prop}Bidx`].find((p) => metadata.findColumnWithPropertyPath(p));
96
+ if (!indexProp || !metadata.findColumnWithPropertyPath(indexProp))
97
+ throw configError(`${lb}: searchable properties need a blind-index column (${prop}${INDEX_SUFFIX} varchar(64), indexed) or indexField`);
98
+ }
99
+ fields.push({ prop, column: col.databaseName, ...(n.normalization ? { normalization: n.normalization } : {}), ...(indexProp ? { indexProp } : {}) });
100
+ }
101
+ const gen = pkCol.isGenerated ? pkCol.generationStrategy : undefined;
102
+ const plan = {
103
+ table: metadata.tableName,
104
+ pk: pkCol.propertyName,
105
+ strategy: gen === 'uuid' ? 'uuid' : gen ? 'two-phase' : 'explicit',
106
+ fields,
107
+ byProp: new Map(fields.map((f) => [f.prop, f])),
108
+ };
109
+ plans.set(metadata, plan);
110
+ return plan;
111
+ }
112
+ /** Search document fields of an entity (encrypted properties carry the context of their stored ciphertext). */
113
+ function searchFieldPlans(metadata, props) {
114
+ const plan = planFor(metadata);
115
+ return props.map((prop) => {
116
+ if (!metadata.findColumnWithPropertyPath(prop))
117
+ throw configError(`TypeORM: ${metadata.name}.${prop}: search fields must be columns`);
118
+ const f = plan?.byProp.get(prop);
119
+ return { attr: prop, ...(f ? { encrypted: { collection: plan.table, field: f.column } } : {}) };
120
+ });
121
+ }
122
+ function primaryProp(metadata) {
123
+ if (metadata.primaryColumns.length !== 1)
124
+ throw configError(`TypeORM: ${metadata.name} must have exactly one primary column to be indexed`);
125
+ return metadata.primaryColumns[0].propertyName;
126
+ }
127
+ /**
128
+ * Entity subscriber that encrypts `@Encrypted()` properties before INSERT/UPDATE
129
+ * and decrypts them after load. Register an instance (or use
130
+ * {@link northstarCipherSubscriber} for the DataSource `subscribers` option).
131
+ */
132
+ export class NorthstarCipherSubscriber {
133
+ cipher;
134
+ options;
135
+ ledger = new PlaintextLedger();
136
+ encrypt;
137
+ searchPlans = new WeakMap();
138
+ /** Index changes per query runner and transaction depth, applied when the outermost transaction commits. */
139
+ pendingSearch = new WeakMap();
140
+ constructor(cipher, options = {}) {
141
+ if (!cipher || typeof cipher.encryptManySettled !== 'function')
142
+ throw configError('TypeORM: NorthstarCipherSubscriber requires a NorthstarCipher client');
143
+ this.cipher = cipher;
144
+ this.options = options;
145
+ this.encrypt = encryptCoalescer(cipher, { keyId: options.keyId });
146
+ if (options.search !== undefined && !Array.isArray(options.search))
147
+ throw configError('TypeORM: search must be a list of { entity, index, fields }');
148
+ for (const s of options.search ?? []) {
149
+ normalizeSearchSync(s, 'TypeORM: search');
150
+ if (typeof s.entity !== 'function' && (typeof s.entity !== 'string' || !s.entity))
151
+ throw configError('TypeORM: search entries need an entity (class or name)');
152
+ }
153
+ }
154
+ searchPlanFor(metadata) {
155
+ const cached = this.searchPlans.get(metadata);
156
+ if (cached !== undefined)
157
+ return cached;
158
+ const sync = this.options.search?.find((s) => s.entity === metadata.target || s.entity === metadata.name) ?? null;
159
+ const plan = sync ? { sync, pk: primaryProp(metadata), fields: searchFieldPlans(metadata, sync.fields), label: metadata.tableName } : null;
160
+ this.searchPlans.set(metadata, plan);
161
+ return plan;
162
+ }
163
+ /** Index a change now, or once the transaction it belongs to commits. */
164
+ async queueSearch(queryRunner, sync, change) {
165
+ if (!queryRunner?.isTransactionActive)
166
+ return applySearchChange(sync, change);
167
+ const depth = queryRunner.transactionDepth ?? 1;
168
+ let levels = this.pendingSearch.get(queryRunner);
169
+ if (!levels)
170
+ this.pendingSearch.set(queryRunner, (levels = new Map()));
171
+ let set = levels.get(depth);
172
+ if (!set)
173
+ levels.set(depth, (set = new SearchChangeSet()));
174
+ set.add(sync, change);
175
+ }
176
+ async afterTransactionCommit(event) {
177
+ const levels = this.pendingSearch.get(event.queryRunner);
178
+ if (!levels)
179
+ return;
180
+ const depth = event.queryRunner.transactionDepth ?? 0;
181
+ if (event.queryRunner.isTransactionActive) {
182
+ // A savepoint was released: its changes now belong to the enclosing transaction.
183
+ let target = levels.get(depth);
184
+ if (!target)
185
+ levels.set(depth, (target = new SearchChangeSet()));
186
+ for (const [d, set] of levels) {
187
+ if (d > depth) {
188
+ target.merge(set);
189
+ levels.delete(d);
190
+ }
191
+ }
192
+ return;
193
+ }
194
+ this.pendingSearch.delete(event.queryRunner);
195
+ for (const d of [...levels.keys()].sort((a, b) => a - b))
196
+ await levels.get(d).apply(true);
197
+ }
198
+ afterTransactionRollback(event) {
199
+ const levels = this.pendingSearch.get(event.queryRunner);
200
+ if (!levels)
201
+ return;
202
+ if (!event.queryRunner.isTransactionActive)
203
+ return void this.pendingSearch.delete(event.queryRunner);
204
+ const depth = event.queryRunner.transactionDepth ?? 0;
205
+ for (const d of [...levels.keys()])
206
+ if (d > depth)
207
+ levels.delete(d);
208
+ }
209
+ searchDocument(sp, entity, id) {
210
+ return searchDocumentOf(entity, { id, fields: sp.fields, label: sp.label });
211
+ }
212
+ /** Encrypt `fields` of one entity (one batch, coalesced with other entities of the same save). */
213
+ async encryptEntity(plan, entity, id, fields) {
214
+ const items = [];
215
+ const targets = [];
216
+ for (const f of fields) {
217
+ const v = this.ledger.resolve(entity, f.prop, entity[f.prop]);
218
+ if (v === null) {
219
+ entity[f.prop] = null;
220
+ if (f.indexProp)
221
+ entity[f.indexProp] = null;
222
+ continue;
223
+ }
224
+ const lb = `${plan.table}.${f.column}`;
225
+ const recordId = recordIdOf(id, lb);
226
+ items.push({ collection: plan.table, field: f.column, recordId, plaintext: plaintextOf(v, lb), normalization: f.normalization, label: `${lb} (${plan.pk}=${recordId})` });
227
+ targets.push({ f, plaintext: v });
228
+ }
229
+ const enc = await this.encrypt(items);
230
+ enc.forEach((e, i) => {
231
+ const { f, plaintext } = targets[i];
232
+ entity[f.prop] = e.ciphertext;
233
+ if (f.indexProp)
234
+ entity[f.indexProp] = e.index ?? null;
235
+ this.ledger.set(entity, f.prop, plaintext, e.ciphertext);
236
+ });
237
+ }
238
+ restore(entity) {
239
+ for (const [prop, e] of this.ledger.entries(entity))
240
+ if (entity[prop] === e.ciphertext)
241
+ entity[prop] = e.plaintext;
242
+ this.ledger.clear(entity);
243
+ }
244
+ async beforeInsert(event) {
245
+ const entity = event.entity;
246
+ const plan = entity && event.metadata ? planFor(event.metadata) : null;
247
+ if (!plan)
248
+ return;
249
+ const touched = plan.fields.filter((f) => entity[f.prop] !== undefined);
250
+ if (!touched.length)
251
+ return;
252
+ let id = entity[plan.pk];
253
+ if (id === undefined || id === null) {
254
+ if (plan.strategy === 'uuid')
255
+ entity[plan.pk] = id = globalThis.crypto.randomUUID();
256
+ else if (plan.strategy === 'two-phase') {
257
+ for (const f of touched) {
258
+ const v = this.ledger.resolve(entity, f.prop, entity[f.prop]);
259
+ if (f.indexProp)
260
+ entity[f.indexProp] = null;
261
+ if (v === null)
262
+ continue;
263
+ this.ledger.set(entity, f.prop, plaintextOf(v, `${plan.table}.${f.column}`), PENDING_SENTINEL);
264
+ entity[f.prop] = PENDING_SENTINEL;
265
+ }
266
+ return;
267
+ }
268
+ else
269
+ throw requestError(`${plan.table}.${plan.pk} must be set before writing encrypted columns`);
270
+ }
271
+ await this.encryptEntity(plan, entity, id, touched);
272
+ }
273
+ async afterInsert(event) {
274
+ const entity = event.entity;
275
+ const plan = entity && event.metadata ? planFor(event.metadata) : null;
276
+ if (!plan)
277
+ return this.indexPlain(event);
278
+ const pending = plan.fields.filter((f) => this.ledger.get(entity, f.prop)?.ciphertext === PENDING_SENTINEL);
279
+ if (pending.length) {
280
+ // Two-phase write, step 2: bind to the generated id and replace the sentinel in the same transaction.
281
+ const id = entity[plan.pk] ?? event.entityId?.[plan.pk];
282
+ try {
283
+ if (id === undefined || id === null)
284
+ throw new CipherError('PROTOCOL_ERROR', `${plan.table}: the generated id is not available after insert`);
285
+ await this.encryptEntity(plan, entity, id, pending);
286
+ const set = {};
287
+ const where = { [plan.pk]: id };
288
+ for (const f of pending) {
289
+ set[f.prop] = entity[f.prop];
290
+ if (f.indexProp)
291
+ set[f.indexProp] = entity[f.indexProp];
292
+ where[f.prop] = PENDING_SENTINEL;
293
+ }
294
+ const res = await event.queryRunner.manager
295
+ .createQueryBuilder()
296
+ .update(event.metadata.target)
297
+ .set(set)
298
+ .where(where)
299
+ .callListeners(false)
300
+ .updateEntity(false)
301
+ .execute();
302
+ if (res.affected !== undefined && res.affected !== 1)
303
+ throw new CipherError('PROTOCOL_ERROR', `${plan.table}: two-phase write could not find the pending row ${plan.pk}=${String(id)}`);
304
+ }
305
+ catch (e) {
306
+ // Fail closed: drop the sentinel row (save() also rolls its transaction back).
307
+ if (id !== undefined && id !== null) {
308
+ await event.queryRunner.manager
309
+ .createQueryBuilder()
310
+ .delete()
311
+ .from(event.metadata.target)
312
+ .where({ [plan.pk]: id })
313
+ .callListeners(false)
314
+ .execute()
315
+ .catch(() => undefined);
316
+ }
317
+ this.restore(entity);
318
+ throw e;
319
+ }
320
+ }
321
+ const sp = event.metadata ? this.searchPlanFor(event.metadata) : null;
322
+ const id = sp ? (entity[sp.pk] ?? event.entityId?.[sp.pk]) : undefined;
323
+ // Before restore(): encrypted properties still hold the ciphertext just written.
324
+ const doc = sp && id !== undefined && id !== null ? this.searchDocument(sp, entity, id) : undefined;
325
+ this.restore(entity);
326
+ if (sp && doc)
327
+ await this.queueSearch(event.queryRunner, sp.sync, { upsert: [doc] });
328
+ }
329
+ async beforeUpdate(event) {
330
+ const entity = event.entity;
331
+ const plan = entity && event.metadata ? planFor(event.metadata) : null;
332
+ if (!plan || !entity)
333
+ return;
334
+ const db = event.databaseEntity;
335
+ if (!db) {
336
+ // QueryBuilder/Repository.update(): the target rows (and so the record ids) are unknown here.
337
+ if (plan.fields.some((f) => entity[f.prop] !== undefined) || plan.fields.some((f) => f.indexProp && entity[f.indexProp] !== undefined)) {
338
+ throw requestError(`${plan.table}: update() cannot write encrypted columns (each row needs its own ciphertext); load the entity and save() it`);
339
+ }
340
+ return;
341
+ }
342
+ if (entity[plan.pk] !== undefined && entity[plan.pk] !== null && String(entity[plan.pk]) !== String(db[plan.pk])) {
343
+ throw requestError(`${plan.table}.${plan.pk}: changing the primary key would invalidate the record's ciphertext`);
344
+ }
345
+ const touched = plan.fields.filter((f) => {
346
+ const v = this.ledger.resolve(entity, f.prop, entity[f.prop]);
347
+ return v !== undefined && v !== db[f.prop];
348
+ });
349
+ if (!touched.length)
350
+ return;
351
+ await this.encryptEntity(plan, entity, db[plan.pk], touched);
352
+ }
353
+ async afterUpdate(event) {
354
+ const entity = event.entity;
355
+ if (!entity)
356
+ return;
357
+ const sp = event.metadata ? this.searchPlanFor(event.metadata) : null;
358
+ // Only full saves (the stored row is known): QueryBuilder updates do not say which rows changed.
359
+ const id = sp && event.databaseEntity ? event.databaseEntity[sp.pk] : undefined;
360
+ const touched = sp && id !== undefined && id !== null && event.updatedColumns.some((c) => sp.sync.fields.includes(c.propertyName));
361
+ const doc = touched ? this.searchDocument(sp, entity, id) : undefined;
362
+ this.restore(entity);
363
+ if (sp && doc)
364
+ await this.queueSearch(event.queryRunner, sp.sync, { upsert: [doc] });
365
+ }
366
+ async afterRemove(event) {
367
+ await this.unindex(event);
368
+ }
369
+ async afterSoftRemove(event) {
370
+ await this.unindex(event);
371
+ }
372
+ async unindex(event) {
373
+ const sp = event.metadata ? this.searchPlanFor(event.metadata) : null;
374
+ if (!sp)
375
+ return;
376
+ const id = event.entityId?.[sp.pk] ?? event.databaseEntity?.[sp.pk] ?? event.entity?.[sp.pk];
377
+ if (id !== undefined && id !== null)
378
+ await this.queueSearch(event.queryRunner, sp.sync, { delete: [recordIdOf(id, sp.label)] });
379
+ }
380
+ /** afterInsert of an entity without encrypted properties. */
381
+ async indexPlain(event) {
382
+ const sp = event.entity && event.metadata ? this.searchPlanFor(event.metadata) : null;
383
+ if (!sp)
384
+ return;
385
+ const id = event.entity[sp.pk] ?? event.entityId?.[sp.pk];
386
+ if (id !== undefined && id !== null)
387
+ await this.queueSearch(event.queryRunner, sp.sync, { upsert: [this.searchDocument(sp, event.entity, id)] });
388
+ }
389
+ afterLoad(entity, event) {
390
+ const metadata = event?.metadata;
391
+ const plan = metadata ? planFor(metadata) : null;
392
+ if (!plan)
393
+ return;
394
+ const opts = { purpose: this.options.purpose, readLegacyPlaintext: this.options.readLegacyPlaintext === true };
395
+ const jobs = [];
396
+ for (const f of plan.fields) {
397
+ const stored = entity[f.prop];
398
+ if (stored === undefined || stored === null)
399
+ continue;
400
+ const lb = `${plan.table}.${f.column}`;
401
+ const recordId = recordIdOf(entity[plan.pk], lb);
402
+ // One `cipher.decrypt` per value: the SDK coalesces every call made while TypeORM maps a result set into batch requests.
403
+ jobs.push(decryptOne(this.cipher, { collection: plan.table, field: f.column, recordId, stored, label: `${lb} (${plan.pk}=${recordId})` }, opts).then((p) => {
404
+ entity[f.prop] = p;
405
+ }));
406
+ }
407
+ if (jobs.length)
408
+ return Promise.all(jobs).then(() => undefined);
409
+ }
410
+ }
411
+ /** Subscriber class bound to `cipher`, for `new DataSource({ subscribers: [northstarCipherSubscriber(cipher)] })`. */
412
+ export function northstarCipherSubscriber(cipher, options = {}) {
413
+ class BoundNorthstarCipherSubscriber extends NorthstarCipherSubscriber {
414
+ constructor() {
415
+ super(cipher, options);
416
+ }
417
+ }
418
+ // TypeORM only instantiates `subscribers` classes registered with @EventSubscriber(); the
419
+ // registration is inert until a DataSource lists this class.
420
+ EventSubscriber()(BoundNorthstarCipherSubscriber);
421
+ return BoundNorthstarCipherSubscriber;
422
+ }
423
+ /**
424
+ * Exact-match condition for a searchable encrypted property:
425
+ * `repo.findBy(await cipherWhere(ds, Todo, 'email', 'ana@example.com'))` → `{ email_bidx: In(tokens) }`.
426
+ */
427
+ export async function cipherWhere(dataSource, entity, property, value) {
428
+ const sub = dataSource.subscribers.find((s) => s instanceof NorthstarCipherSubscriber);
429
+ if (!sub)
430
+ throw configError('TypeORM: register northstarCipherSubscriber(cipher) on the DataSource first');
431
+ const metadata = dataSource.getMetadata(entity);
432
+ const plan = planFor(metadata);
433
+ const f = plan?.byProp.get(property);
434
+ if (!plan || !f)
435
+ throw configError(`TypeORM: ${metadata.name}.${property} is not @Encrypted()`);
436
+ if (!f.indexProp)
437
+ throw configError(`TypeORM: ${metadata.name}.${property} is not searchable (@Encrypted({ searchable: … }))`);
438
+ const tokens = await searchTokensFor(sub.cipher, { collection: plan.table, field: f.column, normalization: f.normalization, values: value, keyId: sub.options.keyId, label: `${plan.table}.${f.column}` });
439
+ return { [f.indexProp]: In(tokens) };
440
+ }
441
+ /**
442
+ * Northstar Search documents for entities or rows of `entity`. Rows read without
443
+ * the subscriber's decryption (e.g. `ds.createQueryBuilder(Todo, 't').getRawMany()`
444
+ * mapped to property names, or a DataSource without the subscriber) hold stored
445
+ * ciphertext, sent with the context it is bound to and decrypted inside the
446
+ * enclave; decrypted entities send their plaintext.
447
+ */
448
+ export function searchDocuments(dataSource, entity, rows, fields) {
449
+ const metadata = dataSource.getMetadata(entity);
450
+ const pk = primaryProp(metadata);
451
+ const plans = searchFieldPlans(metadata, fields);
452
+ return rows.map((row) => searchDocumentOf(row, { id: row[pk], fields: plans, label: metadata.tableName }));
453
+ }
454
+ /** True when a raw column value is Northstar ciphertext (useful in migrations and tests). */
455
+ export { isCiphertext };
456
+ export { CipherError };
457
+ //# sourceMappingURL=typeorm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeorm.js","sourceRoot":"","sources":["../../src/integrations/typeorm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Object encryption, format NSOB v1 (protocol §13): AES-256-GCM in blocks under
3
+ * a content key derived from a random per-object key and the object's context.
4
+ * Pure functions; `NorthstarCipher.encryptObject()` / `decryptObject()` generate
5
+ * the object key and protect it with Cipher.
6
+ *
7
+ * ```
8
+ * header = "NSOB" ‖ 0x01 ‖ log2(B) ‖ 0^10 ‖ object_id (16)
9
+ * content_key = HKDF-SHA-256(object_key, salt = object_id, info = "northstar-cipher/v1/object" ‖ 0x00 ‖ ctx)
10
+ * block i = AES-256-GCM(content_key, 0^4 ‖ u64(i), aad = header ‖ u64(i) ‖ u8(last))
11
+ * ```
12
+ */
13
+ import { type CipherContext } from './client.js';
14
+ import { CipherError } from './errors.js';
15
+ /**
16
+ * Result of `NorthstarCipher.encryptObject()`. Store `wrappedKey` with the record
17
+ * (it is an ordinary `nsc:v1:` ciphertext) and `object` in object storage.
18
+ * `toString()` and `util.inspect` never show the wrapped key or the object bytes.
19
+ */
20
+ export declare class EncryptedObject {
21
+ /** The object key encrypted by Cipher for the object's context (`nsc:v1:…`). */
22
+ readonly wrappedKey: string;
23
+ /** The NSOB v1 object. */
24
+ readonly object: Uint8Array;
25
+ readonly keyId: string;
26
+ readonly keyVersion: number;
27
+ constructor(wrappedKey: string, object: Uint8Array, keyId: string, keyVersion: number);
28
+ toString(): string;
29
+ }
30
+ /**
31
+ * Seal `plaintext` under `objectKey` (32 random bytes, never reused) for `context`.
32
+ * `objectId` is 16 random bytes; `blockLog2` is 12 … 24 (default 16, 64 KiB blocks).
33
+ */
34
+ export declare function sealObject(objectKey: Uint8Array, objectId: Uint8Array, context: CipherContext, plaintext: Uint8Array | string, blockLog2?: number): Promise<Uint8Array>;
35
+ /**
36
+ * Open an NSOB v1 object. Every block is authenticated before the plaintext is
37
+ * returned. Any failure is `INVALID_CIPHERTEXT` with one message.
38
+ */
39
+ export declare function openObject(objectKey: Uint8Array, context: CipherContext, object: Uint8Array): Promise<Uint8Array>;
40
+ /**
41
+ * The content key (32 bytes): HKDF-SHA-256(object_key, salt = object_id,
42
+ * info = "northstar-cipher/v1/object" ‖ 0x00 ‖ canonical context). For the vectors.
43
+ */
44
+ export declare function objectContentKey(objectKey: Uint8Array, objectId: Uint8Array, context: CipherContext): Promise<Uint8Array>;
45
+ /**
46
+ * Canonical context bytes (protocol §3.1): u32(count) ‖ for each (k, v) sorted by k: lp(k) ‖ lp(v).
47
+ * camelCase keys become snake_case and `undefined`/`null` values are dropped, as for every request.
48
+ */
49
+ export declare function canonicalContext(context: CipherContext): Uint8Array;
50
+ /** Size of the object for a plaintext of `length` bytes. */
51
+ export declare function objectLength(length: number, blockLog2?: number): number;
52
+ /** The single error for every failure to open an object (also a wrapped key that is not an object key). */
53
+ export declare function invalidObject(): CipherError;