Docs
Le moteur, en pratique.
01
Vue d'ensemble
Le moteur QuorVault chiffre des colonnes de votre base de données avec un schéma hybride : X25519 + ML-KEM-768 combinés par HKDF-SHA256 protègent une clé de données AES-256, qui chiffre chaque valeur en AES-256-GCM, liée à sa table, sa colonne et sa ligne.
Il fournit un outil en ligne de commande pour migrer automatiquement des bases existantes, et une bibliothèque pour votre application. Le détail des garanties est sur la page Sécurité.
02
Prérequis
- Node.js 24.7+ (fournit OpenSSL 3.5, ML-KEM et Argon2id)
- PostgreSQL (14+), MySQL (8.0+), MariaDB ou SQLite
- Une clé primaire sur une seule colonne pour chaque table migrée
03
Installation
npm install @quorvault/engine
npx quorvault --help04
La méthode rapide
export DATABASE_URL="postgres://user:pass@host:5432/crm" # or mysql://… or sqlite:file.db
export QUORVAULT_PASSWORD="…" # otherwise prompted, hidden
# Is this machine, the database and the vault ready?
npx quorvault doctor
# Where is the personal data? (e-mails, phones, IBANs, cards, social security numbers…)
npx quorvault scan
# All-in-one for a table: vault, checks, rehearsal, encryption, search index, verification, report
npx quorvault protect --vault vault.json --table customers --columns email,phone --index email:lowerscan n'affiche jamais les valeurs lues, seulement le type de donnée détecté. protect s'arrête avant d'écrire si la répétition trouve un problème, et reprend là où il s'était arrêté si on le relance.
05
Pas à pas
# Secrets stay out of your shell history
export DATABASE_URL="postgres://user:pass@host:5432/crm"
export QUORVAULT_PASSWORD="…" # otherwise prompted, hidden
# 1. Create the vault (once per environment)
npx quorvault init --vault vault.json
# 2. Check the schema: column sizes, primary key, volume
npx quorvault plan --vault vault.json --table customers --columns email,phone
# 3. Dress rehearsal: reads and encrypts everything in memory, writes nothing
npx quorvault migrate --vault vault.json --table customers --columns email,phone --dry-run
# 4. Real migration (after a database backup)
npx quorvault migrate --vault vault.json --table customers --columns email,phone
# 5. Audit: every value must authenticate in its own row
npx quorvault verify --vault vault.json --table customers --columns email,phoneChaque lot (500 lignes par défaut) est verrouillé, chiffré, vérifié puis validé en une transaction. Relancer migrate reprend là où ça s'est arrêté. Les colonnes trop courtes ou non textuelles sont signalées par plan ; --alter-columns les convertit en TEXT.
06
Depuis un ancien chiffrement
export OLD_KEY="<64 hex characters>"
npx quorvault migrate … --from aes-256-cbc --legacy-key-env OLD_KEY
npx quorvault migrate … --from aes-256-gcm:hex --legacy-key-env OLD_KEYFormats reconnus : plaintext (par défaut), aes-256-cbc, aes-256-gcm, avec :hex si les valeurs sont en hexadécimal.
07
Dans votre application
import { openVault } from "@quorvault/engine";
const qv = await openVault("vault.json", process.env.QUORVAULT_PASSWORD!);
// Write: token, plus a search fingerprint if the column is searchable
const { token, index } = qv.seal("alice@acme.io", { table: "customers", column: "email", row: 42 });
// Read
const email = qv.decrypt(row.email, { table: "customers", column: "email", row: row.id });
// Exact lookup on an encrypted column
db.query("SELECT * FROM customers WHERE email_bidx = $1", [qv.blindIndex(input, { table: "customers", column: "email" })]);
// During a rollout: accepts plaintext or ciphertext
const value = qv.decryptIfEncrypted(row.email, { table: "customers", column: "email", row: row.id });Le mot de passe du coffre est fourni au démarrage, par une variable d'environnement ou un gestionnaire de secrets.
08
Rechercher dans une colonne chiffrée
Avec --index email:lower, une colonne email_bidx reçoit une empreinte à clé (HMAC-SHA256) de chaque valeur : WHERE email_bidx = ? retrouve la ligne, et l'index est UNIQUE si la colonne d'origine l'était. Sans le coffre, l'empreinte ne révèle rien ; elle laisse seulement voir quelles lignes partagent la même valeur. Modes : exact, lower (e-mails), digits (téléphones), compact (IBAN).
09
PHP, Python, Java… : le service local
export QUORVAULT_SERVE_TOKEN="$(openssl rand -base64 36)"
npx quorvault serve --vault vault.json # http://127.0.0.1:8750
curl -s http://127.0.0.1:8750/v1/encrypt \
-H "Authorization: Bearer $QUORVAULT_SERVE_TOKEN" -H "Content-Type: application/json" \
-d '{"table":"customers","column":"email","row":42,"value":"alice@acme.io"}'Le service n'écoute que sur la machine elle-même, exige un jeton et n'envoie aucun en-tête CORS. Endpoints : /v1/encrypt, /v1/decrypt, /v1/blind-index, avec traitement par lots (items). Des clients PHP et Python prêts à l'emploi sont fournis avec le moteur.
10
Gestion des clés
npx quorvault info --vault vault.json # vault details
npx quorvault passwd --vault vault.json # change the password (data untouched)
npx quorvault rotate-key --vault vault.json # new active data key
npx quorvault reencrypt --vault vault.json --table customers --columns email,phone
npx quorvault revert --vault vault.json --table customers --columns email,phoneLe coffre et son mot de passe doivent être sauvegardés séparément : sans l'un ou l'autre, les données sont définitivement illisibles.
11
Format des valeurs
qv1.<base64url( keyId:uint32 ‖ nonce:12 bytes ‖ AES-256-GCM ciphertext ‖ tag:16 bytes )>
AAD = "quorvault/field/v1" ‖ vaultId ‖ keyId ‖ table ‖ column ‖ rowId (length-prefixed)Du texte ASCII qui tient dans n'importe quelle colonne TEXT. Toute valeur copiée ailleurs, ou modifiée d'un seul octet, échoue à l'authentification.
12
Limites actuelles
- Pas encore de SQL Server, Oracle ni MongoDB. MySQL : tables InnoDB uniquement.
- Clés primaires composites non gérées.
- Sur les colonnes chiffrées : recherche exacte uniquement (via l'empreinte), pas de tri ni de recherche par préfixe.
