Aller au contenu principal

appcore-dnt

Paquet publié

Stable 1.0.0 · MSRV Rust 1.89 · crates.io · docs.rs · code source

Guide et exemples maintenus par le crate

Le dépôt Runtime maintient le guide détaillé, exemple débutant et exemple intermédiaire. Le wiki résume la frontière publique ; les détails d’API et d’exécution restent avec le code du crate.

Responsabilité : contrats et helpers du conteneur chiffré générique DNT.

Dépendances internes : appcore-contracts, appcore-types.

API principale : seal, open, open_owned, inspect_header, verify, write_atomic, read_verified, rekey, migrate_envelope, DntKeyProvider, DntCodec, DntHeader, DntContext, DntCompression, KeyId, ContentType, CodecId, DntFlags, dnt_user_flag, dnt_compose_flags et DNT_FLAG_PAYLOAD_DEFLATE.

DNT est une enveloppe binaire pour des octets arbitraires. .dnt, .dntj, .dntb et .dnto sont seulement des conventions ; les consommateurs inspectent l'en-tête authentifié.

Disposition V1 :

en-tête canonique
magic
envelope_version
header_length
flags
algorithm
schema_version
created_at_ms
stored payload_length
nonce
payload_hash
public_metadata_length
encrypted_metadata_length
application_id
tenant_id optionnel
content_type
codec_id
key_id
public_metadata
ciphertext
encrypted_metadata_length
encrypted_metadata
payload encodé stocké
tag d'authentification

Tout l'en-tête est l'AAD de l'AEAD. La V1 utilise XChaCha20-Poly1305 avec une clé de 256 bits et un nonce aléatoire OS de 192 bits. Les clés sont résolues par DntKeyProvider ; elles ne sont jamais stockées dans l'enveloppe.

Pourquoi Utiliser DNT

DNT n'est pas destiné à remplacer tous les fichiers. Il est utile lorsque des octets doivent circuler entre providers de stockage, sauvegardes, transports de sync ou stockage local de secrets sans perdre leurs propriétés de sécurité.

Utiliser DNT lorsque le fichier exige :

  • confidentialité sans placer la clé à côté des octets chiffrés ;
  • identité authentifiée de l'application, du tenant, du type logique, du codec et de la clé ;
  • rejet d'une mauvaise application, d'un mauvais tenant ou d'un mauvais type logique avant de retourner du plaintext ;
  • détection de corruption et d'altération sur l'en-tête et le payload ;
  • helpers d'écriture atomique et de lecture vérifiée ;
  • rotation explicite de clé avec rekey ;
  • migration explicite d'enveloppe avec migrate_envelope ;
  • transport opaque par storage, sync ou gateway sans compréhension du domaine.

Ne pas utiliser DNT uniquement pour économiser du disque. JSON brut ou binaire brut est plus simple, plus petit et plus rapide lorsqu'il n'y a pas besoin de chiffrement, d'authentification, de liaison au contexte, de rotation de clé ou de migration versionnée.

Mode Compact

Le DNT normal stocke directement la sortie du codec avant chiffrement. Le DNT compact positionne le flag authentifié DNT_FLAG_PAYLOAD_DEFLATE et stocke un flux DEFLATE avec wrapper zlib à un niveau équilibré avant chiffrement. Les lecteurs V1 inspectent les deux modes ; ouvrir une enveloppe compacte exige DntOpenOptions.max_payload_bytes pour borner l'expansion.

Pour les buffers complets lus depuis un fichier, préférer open_owned ou read_verified ; ils déchiffrent l'enveloppe propriétaire in-place. Utiliser open lorsque l'appelant ne possède qu'une slice empruntée.

read_verified exige un DntOpenOptions.max_payload_bytes explicite et rejette un fichier trop grand avant l'allocation du buffer complet. Les métadonnées chiffrées V1 sont limitées à 64 Kio. OpenedDnt::zeroize_plaintext efface le plaintext et les métadonnées chiffrées dès que l'appelant n'en a plus besoin.

ModeTaille disqueChemin de lecture
NormalEn-tête + métadonnées chiffrées + payload encodé + tag AEAD. La taille suit la sortie du codec et le coût CPU est minimal.Lire, authentifier, déchiffrer puis décoder le codec. C'est le chemin CPU le plus rapide pour les petits fichiers ou les données peu compressibles.
CompactEn-tête + métadonnées chiffrées + payload encodé compressé + tag AEAD. JSON répétitif, snapshots et logs sont souvent beaucoup plus petits ; les payloads déjà compressés ou aléatoires peuvent être identiques ou plus gros.Lire moins d'octets disque, authentifier, déchiffrer, inflater DEFLATE puis décoder le codec. L'inflation ajoute du travail, mais moins de ciphertext peut réduire assez l'AEAD et le digest pour améliorer la latence totale des payloads très compressibles.

Le mode compact n'est pas une frontière de sécurité. La taille du fichier révèle encore une approximation de la taille compressée. Éviter de compacter des secrets qui mélangent des octets contrôlés par un attaquant et des octets confidentiels lorsque l'observation de taille compte.

Comparaison De Référence

Le dépôt inclut une comparaison reproductible qui écrit chaque échantillon comme fichier plaintext, DNT normal et DNT compact. Elle chauffe chaque chemin et rapporte séparément les distributions espace, read/open, seal et rekey :

cargo run -p appcore-dnt --example compare --release

Exécution --release de référence sur Apple M1, séparée par catégorie :

Espace disque :

  • JSON répétitif : plaintext 1 048 557 octets ; normal 1 048 746 ; compact 4 403 ;
  • binaire incompressible : plaintext 1 048 576 octets ; normal 1 048 773 ; compact 1 048 949 ;
  • petit secret : plaintext 65 octets ; normal 252 ; compact 254.

Médiane du chemin de lecture avec cache chaud :

  • JSON répétitif : plaintext 42,7 us ; read/open normal 5,51 ms ; compact 321,2 us ;
  • binaire incompressible : plaintext 42,3 us ; normal 5,51 ms ; compact 6,33 ms ;
  • petit secret : plaintext 14,5 us ; normal 17,7 us ; compact 23,8 us.

Interprétation :

  • les snapshots JSON répétitifs gagnent parce que DNT authentifie et déchiffre beaucoup moins d'octets après compression ; lors de cette exécution, l'inflation de 1 Mio a coûté moins que l'AEAD et le digest du ciphertext supplémentaire ;
  • les données binaires déterministes sont pratiquement incompressibles, donc le mode compact ajoute du CPU et un faible overhead de format ;
  • les petits secrets se dégradent en mode compact parce que le wrapper de compression coûte plus d'octets et de CPU qu'il n'en économise ;
  • les fichiers plaintext sont plus rapides et plus petits lorsque les propriétés de sécurité ne sont pas nécessaires ; cette base ne comprend pas chiffrement, authentification, rotation de clé, liaison au contexte ni détection d'altération.

Le rapport mesuré complet enregistre matériel, APFS/SSD, alimentation secteur, Rust/profile, warm-up, échantillons, moyenne, écart, p95, p99, maximum, throughput, seal/rekey et preuves mémoire/CPU non mesurées. Régénérer sur la classe de déploiement concernée. DNT est un conteneur de sécurité et de portabilité, pas un remplaçant plus rapide du plaintext de confiance.

Flags

Le champ V1 flags est authentifié par l'AAD de l'en-tête AEAD et il est partitionné pour éviter les combinaisons impossibles :

PlagePropriétaireRègles
Bits 0..15comportement interne de l'enveloppe DNT/AppCoreSeuls les flags connus par ce crate sont acceptés. Les bits internes inconnus échouent avec DntError::InvalidFlags avant résolution de clé ou déchiffrement.
Bits 16..31annotations de l'application/appelantDNT authentifie et préserve ces bits, mais ne leur attribue pas de sémantique centrale. Les appelants doivent les allouer avec dnt_user_flag(index), où index vaut 0..16.

Utiliser DntFlags, dnt_user_flag, dnt_compose_flags ou DntSealOptions::with_user_flag au lieu de shifts manuels. Les helpers rejettent les index hors plage et les valeurs qui placent des flags appelant dans la plage interne.

Modèle de menace : DNT protège la confidentialité et l'intégrité contre l'inspection hors ligne et la modification du fichier sans la clé. Il ne protège pas contre un processus compromis qui détient légitimement la clé en mémoire.

Maturité : contrat additif stable. Manifest V1 ne change pas ; les deployments sélectionnent DNT via la configuration existante de providers/capabilities.