L'évolution de l'architecture de confidentialité : des mixers aux protocoles programmables
Les mixers classiques tels que Tornado Cash ou Sinbad deviennent obsolètes sous la pression des régulateurs, des sanctions de l'OFAC (Office of Foreign Assets Control) et de l'analyse des graphes de transactions par suivi heuristique par clusters. L'anonymisation native au niveau des pools de liquidité est bloquée au niveau des smart contracts via des listes d'adresses à haut risque (Chainalysis, Elliptic) intégrées aux nœuds RPC des principaux fournisseurs (Infura, Alchemy).
L'industrie s'oriente vers le concept de la confidentialité programmable (Programmable Privacy). Plutôt que de masquer le fait même d'une transaction en diluant les dépôts dans un pool, les nouvelles solutions au niveau des protocoles permettent d'exécuter une logique métier arbitraire et des smart contracts sur des données chiffrées. Les pionniers de cette transition sont les réseaux basés sur des architectures zk-rollup prenant en charge la Programmable Privacy, tels qu'Aztec (Noir), ainsi que les réseaux L1 confidentiels spécialisés comme COTI 2.0, qui exploitent des primitives matérielles et cryptographiques de nouvelle génération.
Circuits brouillés (Garbled Circuits) dans la blockchain
Au cœur des plateformes telles que COTI 2.0 se trouve une primitive cryptographique classique, le protocole de Yao (Yao's Garbled Circuits), adapté à l'environnement décentralisé de la blockchain. Contrairement aux zk-SNARK, qui prouvent la validité d'une affirmation sans révéler les données sous-jacentes, les Garbled Circuits permettent à deux parties (ou plus) ne se faisant pas confiance d'évaluer une fonction booléenne arbitraire sur des entrées confidentielles, de sorte qu'aucune des parties ne voit les données de l'autre.
Mécanique d'un circuit brouillé
- 1. Représentation de la logique sous forme de circuit booléen : Tout calcul (transfert de jetons, vérification de solde, scoring de crédit) est compilé en un graphe orienté acyclique composé de portes logiques (AND, XOR, NOT).
- 2. Brouillage (Garbling) : Le créateur du circuit (le Garbler) génère des clés aléatoires de 128 bits pour chaque entrée et chaque sortie de chaque porte. Les tables de vérité des portes sont chiffrées à l'aide de ces clés dans un ordre aléatoire.
- 3. Transfert inconscient (Oblivious Transfer, OT) : L'évaluateur du circuit (l'Evaluator) obtient ses clés d'entrée auprès du Garbler via le protocole cryptographique OT. L'Evaluator ne découvre que les clés correspondant à sa propre entrée réelle, sans la révéler au Garbler et sans obtenir accès aux autres clés.
- 4. Calcul élément par élément : L'Evaluator déchiffre les tables de vérité chiffrées de bas en haut dans le circuit, calculant le résultat sans pouvoir connaître les valeurs intermédiaires des variables.
Optimisations ingénieriques pour la blockchain
Les Garbled Circuits bruts nécessitent un volume considérable de communications réseau. Pour les intégrer dans un environnement blockchain, les développeurs appliquent deux optimisations clés :
- Technique Free-XOR : Permet d'exécuter des portes XOR sans chiffrement ni transmission de données, réduisant considérablement la charge mémoire et la bande passante du bus.
- Point-and-permute : Une méthode de masquage de bits permettant à l'Evaluator de trouver immédiatement la bonne ligne dans la table de vérité chiffrée sans avoir à parcourir toutes les options de déchiffrement.
Comparaison des piles cryptographiques de confidentialité
Pour choisir la bonne pile technologique lors de la conception d'applications décentralisées axées sur la protection des données, on compare les métriques clés des protocoles modernes.
| Protocole / Technologie | Base cryptographique | Support des smart contracts | Surcharge de calcul | Modèle de conformité (Compliance) |
|---|---|---|---|---|
| Tornado Cash (Mixer historique) | zk-SNARK (Groth16) | Aucun (montants fixes) | Faible (vérification de preuve uniquement) | Aucun (résistance totale à la censure) |
| Aztec Network | zk-SNARKs + Langage Noir | Turing-complet (smart contracts privés) | Modérée (génération de preuve côté client) | View Keys, notes d'audit programmables |
| COTI 2.0 | Garbled Circuits + MPC | Support natif des contrats compatibles EVM | Élevée (nécessite des circuits optimisés) | Divulgation sélective (Selective Disclosure) |
| Zcash (Shielded Pool) | zk-SNARKs (Halo 2 / Sapling) | Limitée (pools transparents vs blindés) | Moyenne | Clés de visionnage (Viewing keys) |
Pratique : Divulgation sélective (Selective Disclosure) et stablecoins
La conformité (compliance) moderne exige de passer d'un concept d'« opacité totale » au principe de la divulgation sélective (Selective Disclosure). L'utilisateur conserve le contrôle absolu de l'historique de son capital tout en pouvant prouver à un tiers, à un régulateur ou au fisc la légitimité de ses fonds en cas de besoin, sans avoir à exposer l'intégralité du solde de son portefeuille ni toute la matrice des relations avec d'autres adresses.
Dans l'architecture d'Aztec, cela se concrétise via un système de clés distinctes et une exécution côté client au sein du Private Execution Environment (PXE).
Architecture des clés dans Aztec
Chaque utilisateur gère un ensemble déterministe de clés liées au smart contract de son compte :
- Nullifier Keys ($nhk$) : Utilisées pour générer des preuves de dépense (nullifier) sans fuiter d'informations sur le solde exact ou la note (note) en cours de dépense.
- Incoming Viewing Keys ($ivsk$) : Permettent d'accorder un accès d'audit à des transactions entrantes spécifiques. Vous pouvez transmettre une clé de visualisation chiffrée à un tiers ou à un régulateur, leur donnant uniquement la visibilité sur la transaction de stablecoin ciblée (par exemple, un USDT/USDC encapsulé sur L2) tout en gardant vos autres actifs totalement masqués.
Exemple d'implémentation : Transfert privé de stablecoins en Noir
Vous trouverez ci-dessous un extrait de code production-ready en langage Noir (le DSL de base pour écrire des circuits dans Aztec), mettant en œuvre la vérification de solde privé et la génération d'un engagement de transfert de jetons sans publier les montants sur un registre public.
Extrait de code
// Dépendance dans Nargo.toml : poseidon = { tag = "...", git = "https://github.com/noir-lang/poseidon" }
use poseidon::poseidon::bn254::{hash_2, hash_3};
global TREE_DEPTH: u32 = 32;
struct Note {
owner: Field,
amount: u64,
randomness: Field,
}
fn commit(note: Note) -> Field {
hash_3([note.owner, note.amount as Field, note.randomness])
}
fn merkle_root(leaf: Field, index: u32, path: [Field; TREE_DEPTH]) -> Field {
let bits: [u1; TREE_DEPTH] = (index as Field).to_le_bits();
let mut node = leaf;
for i in 0..TREE_DEPTH {
node = if bits[i] == 0 {
hash_2([node, path[i]])
} else {
hash_2([path[i], node])
};
}
node
}
fn main(
// Entrées publiques : aucune information sur les montants ou les adresses
merkle_root_pub: pub Field,
nullifier: pub Field,
recipient_commitment: pub Field,
change_commitment: pub Field,
// Entrées privées
sender_sk: Field,
sender_note: Note,
path: [Field; TREE_DEPTH],
leaf_index: u32,
transfer_amount: u64,
recipient_owner: Field,
recipient_randomness: Field,
change_randomness: Field,
) {
// 1. Propriété de la note (avec tag de domaine)
assert(hash_2([sender_sk, 1]) == sender_note.owner);
// 2. Appartenance à l'arbre par rapport à la racine publique
let sender_commitment = commit(sender_note);
assert(merkle_root(sender_commitment, leaf_index, path) == merkle_root_pub);
// 3. Suffisance des fonds (en cas d'insuffisance, la soustraction u64 échouera également)
assert(sender_note.amount >= transfer_amount);
let change_amount = sender_note.amount - transfer_amount;
// 4. Nullifier
assert(hash_3([sender_commitment, sender_sk, 2]) == nullifier);
// 5. Les deux nouvelles notes sont liées aux engagements publics
assert(commit(Note {
owner: recipient_owner,
amount: transfer_amount,
randomness: recipient_randomness,
}) == recipient_commitment);
assert(commit(Note {
owner: sender_note.owner,
amount: change_amount,
randomness: change_randomness,
}) == change_commitment);
}Restent hors du circuit : le chiffrement des notes pour le destinataire, le stockage et la mise à jour de l'arbre sur le contrat, la vérification de l'unicité du nullifier et la comparaison de merkle_root_pub avec la racine connue.
Recommandations d'intégration pour les développeurs
- 1. Abandonner la génération de preuves côté serveur : Ne confiez jamais la génération de preuves ZK à des serveurs API tiers distants. Tout le cycle de calcul (PXE dans Aztec ou scripts clients) doit s'exécuter localement sur l'appareil de l'utilisateur ou sur un nœud isolé.
- 2. Gestion des clés cloisonnées par application (App-Siloed Keys) : Utilisez des clés dérivées et isolées pour chaque application décentralisée. Cela garantit qu'une compromission de clé sur un protocole ne entraînera pas la dé-anonymisation de l'historique des transactions de l'utilisateur sur d'autres smart contracts.
- 3. Audit des canaux View Keys : Lors de la conception de passerelles d'entreprise ou de solutions de paiement basées sur la confidentialité programmable, intégrez une logique de génération de clés de visualisation temporaires à durée de vie limitée. Cela permet de satisfaire aux exigences de conformité bancaire et réglementaire (AML/KYT) sans publier les clés maîtresses permanentes du portefeuille.