@cybercommand/crypto (0.2.0)
Installation
@cybercommand:registry=npm install @cybercommand/crypto@0.2.0"@cybercommand/crypto": "0.2.0"About this package
@cybercommand/crypto
Gedeelde AES-256-GCM veld-/bestandsencryptie-primitieven en een generieke Prisma Client
Extension, zodat elk CyberCommand-product dezelfde, geaudite encryptie-implementatie gebruikt
in plaats van elk zijn eigen variant te bouwen (zie SECURITY.md in de workspace-root — Fase 1
van het security-hardeningsplan).
Kern-API
import { loadMasterKeyFromEnv, deriveKey, KeyRing } from '@cybercommand/crypto';
import { encryptString, decryptString, encryptJson, decryptJson } from '@cybercommand/crypto';
import { encryptFile, decryptFile } from '@cybercommand/crypto';
import { createEncryptionExtension } from '@cybercommand/crypto';
const masterKey = loadMasterKeyFromEnv('FIELD_ENCRYPTION_KEY', process.env.FIELD_ENCRYPTION_KEY);
const ring = new KeyRing(masterKey);
const key = ring.key('myapp:db-field:v1'); // purpose-scoped subsleutel, nooit de masterkey direct gebruiken
const token = encryptString('geheime waarde', key); // "enc:v1:<iv>:<tag>:<ciphertext>"
decryptString(token, key); // "geheime waarde"
Prisma-integratie
const prisma = new PrismaClient().$extends(
createEncryptionExtension({
masterKey,
purpose: 'myapp:db-field:v1',
fields: {
User: { name: 'string', profile: 'json' },
},
}),
);
Velden worden transparant versleuteld bij create/update/upsert/createMany/updateMany en
ontsleuteld bij findUnique(OrThrow)/findFirst(OrThrow)/findMany. Niet gedekt: raw queries,
aggregate/groupBy/count — gebruik daar de encrypt/decrypt-functies handmatig.
Adapters (migratie, geen nieuwe code)
adapters.ts reproduceert exact (byte-voor-byte, zelfde KDF/purpose-string/envelope-formaat)
de bestaande, vóór deze package geschreven encryptie in cyberwerkboek en platform, zodat een
migratie naar deze package bestaande versleutelde data niet onleesbaar maakt:
cyberwerkboekEncryptFile/cyberwerkboekDecryptFile— vervangtcyberwerkboek/apps/api/src/upload-storage.service.ts'sencrypt()/decryptStoredEnvelope().cyberwerkboekDecryptLegacyAiCredential— vervangtcyberwerkboek/apps/api/src/legacy-ai-credential.ts'sdecryptLegacyAiCredential()(decrypt-only, voor de bestaande eenmalige uitfasering naar een centrale AI-credential-service).platformEncrypt/platformDecrypt— vervangtplatform/core/src/utils/crypto.ts'sencrypt()/decrypt()(let op: platform gebruikt de masterkey direct, zonder purpose-derivation — dat is een bewust behouden verschil, niet een bug).
Nieuwe code hoort de kern-API te gebruiken, niet de adapters. Adapters bestaan uitsluitend om bestaande call-sites 1-op-1 te kunnen vervangen zonder een data-migratie te forceren.
Belangrijkste randvoorwaarde
Wijzig nooit een bestaande purpose-string of envelope-formaat — dat verandert de afgeleide
sleutel/decodering en maakt alle bestaande ciphertext voor die purpose onleesbaar. Voeg een
nieuwe versie toe (:v2) i.p.v. een bestaande purpose te hergebruiken voor iets anders.
Dependencies
Development dependencies
| ID | Version |
|---|---|
| tsx | ^4.23.0 |
| typescript | ^6.0.3 |