Documentation technique
Sous le capot d’une preuve TrueTake.
Tout ce qui compose une preuve est public et recalculable : formats, formules, clés et registre. Cette page résume le protocole ; le vérificateur en est l’implémentation de référence.
H(x) = SHA-256(C(x))
C(x) = UTF-8(JCS(x)) // RFC 8785
01Primitives
Des briques standard, choisies pour être simples à réimplémenter et à auditer. Aucun algorithme maison.
-
Ed25519
Signatures des QR, des checkpoints, du certificat et des projections publiques.
RFC 8032
-
SHA-256
Toutes les empreintes : segments, enregistrements, chaîne, checkpoints, vidéo finale.
FIPS 180-4
-
JCS
JSON canonique : un même objet donne toujours les mêmes octets, donc la même empreinte.
RFC 8785
-
CBOR + COSE_Sign1
Charge utile compacte et signée des QR de capture.
RFC 8949 · RFC 9052
-
Base45
Encodage alphanumérique dense : des QR plus petits, plus faciles à filmer.
RFC 9285
-
Merkle
Un arbre binaire trié qui engage un lot entier de preuves et de checkpoints dans une seule racine.
truetake-merkle-1
02Codes QR signés
Chaque code affiché par le téléphone A est un message COSE_Sign1 signé par le serveur (Ed25519), encodé en Base45 dans un QR de correction M. Il contient l’opération, le numéro d’étape, une fenêtre de validité et, à partir du deuxième code, un lien de 16 octets vers la chaîne de segments au dernier segment accepté et vers le QR précédent.
qr_(s+1).previous_link = first16(SHA-256("TrueTake-QR-link-v3\0" ‖ chain_j ‖ qr_payload_hash_s))
resume_qr.previous_link = first16(SHA-256("TrueTake-QR-resume-v1\0" ‖ closing_checkpoint_hash ‖ qr_payload_hash_(step-1)))
COSE_Sign1 = Ed25519("TrueTake-QR-v1\0" ‖ payload_cbor)
- Durée de validité : 20 secondes
- Préfixe de signature :
TrueTake-QR-v1\0 - Codes périmés ignorés, jamais acceptés
03Chaîne de segments et checkpoints
Chaque segment filmé produit un enregistrement canonique truetake.unit que le téléphone qui filme calcule avant l’envoi : SHA-256, taille, durée et empreinte du contexte (lieu, capteurs) quand il est autorisé. Chaque enregistrement est enchaîné au précédent. Toutes les deux minutes et à chaque interruption, le serveur signe un checkpoint qui engage la tête de chaîne, la séquence des QR, ses propres observations et les totaux de couverture ; les checkpoints sont ancrés eux aussi. Notation : H(x) = SHA-256(JCS(x)).
unit_record_u = { type:"truetake.unit", version:1, kind:"segment", operation_id, span, u, step_believed, media_sha256, media_size, device_start_time, duration_ms, context_hash, run:null }
unit_hash_u = H(unit_record_u)
span_head_j = H({ type:"truetake.span-head", version:1, operation_id, span:j, qr_hash, closing_checkpoint_hash })
chain_u = H({ type:"truetake.unit-chain", version:1, operation_id, u, previous: chain_(u-1) | span_head_j, unit_hash })
qr_seq_head_s = H({ type:"truetake.qr-seq", version:1, previous, step:s, qr_payload_hash })
checkpoint_k = Ed25519("TrueTake-Proof-v1\0" ‖ C({ type:"truetake.checkpoint", k, chain_head, qr_seq_head, observations_hash, previous_checkpoint_hash, totals, … }))
Le premier segment d’un span se rattache à la tête de span, qui engage le premier QR du span et, après une interruption, le checkpoint qui a fermé le span précédent. Modifier un seul segment change toutes les empreintes qui suivent, et le checkpoint signé ne correspond plus.
04Le certificat final
À la fin de la boucle, le serveur assemble la vidéo et signe le certificat truetake.final-proof (version 2). Il engage l’empreinte du fichier, le checkpoint final et, à travers lui, tout l’historique signé, la tête de chaîne, les spans, les totaux de couverture, le manifeste de capture et le rapport forensique.
signature = Ed25519("TrueTake-Proof-v1\0" ‖ C(final_proof ∖ signature))
proof_hash = H(final_proof)
merkle_leaf = H({ type:"truetake.proof-leaf", version:1, proof_hash })
checkpoint_leaf = H({ type:"truetake.checkpoint-leaf", version:1, checkpoint_hash })
05Ancrage Merkle
Les certificats et les checkpoints sont regroupés par lots. Chaque lot publie une seule racine ; chaque preuve garde son chemin de Merkle pour démontrer qu’elle en fait partie, sans révéler les autres.
Node(l, r) = H({ type:"truetake.merkle-node", version:1, left:l, right:r })
tx_hash = "0x" ‖ H({ type:"truetake.simulated-anchor", version:1, batch_id, merkle_root })
- Feuilles dédoublonnées et triées par valeur d’octets
- Un nœud impair en fin de niveau est dupliqué
- Le chemin indique de quel côté se trouve chaque voisin
- Une seule feuille : la racine est la feuille, chemin vide
Réseau simulé
Mode par défaut de la bêta. La transaction est une empreinte recalculable du lot (0x + H(lot, racine)), publiée dans le registre public. Le vérificateur affiche un badge « Réseau simulé » : c’est valide, mais ce n’est pas une blockchain publique.
Réseau de test
En option : une transaction réelle anchor(racine, lot) sur Base Sepolia. Le vérificateur affiche « Réseau de test ».
06Heuristiques forensiques
Onze contrôles simples et documentés, recalculés à chaque preuve. Ce sont des heuristiques de cohérence, pas une détection d’IA : le score n’est pas une probabilité de falsification. Aucun détecteur d’écran filmé ni d’image générée n’est actif ; ces analyses sont prévues.
| Contrôle | Mesure | Règle |
|---|---|---|
qr_presence |
Part des images où le bon QR est visible (minimum sur les segments en direct) | OK ≥ 30 %, alerte ≥ 10 % |
segment_duration |
Durée de chaque segment | Entre 0,7 et 2 s |
upload_latency |
Délai entre l’émission du code et la réception du segment | OK ≤ 15 s, alerte ≤ 50 s |
device_clock_skew |
Écart entre l’horloge du téléphone et celle du serveur | OK ≤ 5 s, alerte ≤ 30 s |
resolution_consistency |
Nombre de résolutions différentes | Une seule |
codec_consistency |
Nombre de codecs différents | Un seul |
frame_rate_consistency |
Écart de cadence d’images | OK ≤ 5 i/s, alerte ≤ 15 i/s |
sequence_monotonic |
Ordre des étapes | Strictement croissant |
context_continuity |
Segments accompagnés de leur contexte | Tous, ou non évalué |
coverage |
Part du temps de capture filmée en direct | Informatif, jamais un échec |
capture_integrity |
Segments dont le code contredit la séquence | OK à zéro, alerte sinon |
Décision : aucun échec → « aucune anomalie significative » ; un échec → « suspect » ; deux ou plus → « très suspect ». Un QR ou un ordre non évaluable rend l’analyse « non concluante ».
07Vérification
Le vérificateur rejoue treize contrôles ordonnés dans votre navigateur, page par page. Un échec se propage aux contrôles qui en dépendent : rien n’est passé sous silence.
-
01Format et profil cryptographique
schema_profile -
02Signature du certificat par une clé publiée
final_signature -
03Checkpoints signés, chacun lié au précédent
checkpoint_chain -
04Chaque page rejouée : chaîne de segments, QR et leurs liens, observations
pages -
05Couverture en direct recalculée à chaque checkpoint
coverage -
06Manifeste de capture et contextes des segments
snapshots_and_contexts -
07Rapport forensique engagé par le certificat
forensic_report -
08Empreinte de preuve et feuille Merkle
proof_hash_and_leaf -
09Chemin jusqu’à la racine du lot
merkle_path -
10Ancrage des checkpoints
checkpoint_anchors -
11Empreinte de la vidéo fournie
file_sha256 -
12Empreinte perceptuelle (pas encore implémentée)
perceptual_video_hash -
13Racine publiée dans le registre
network_contract_confirmation
08Confidentialité
La preuve n’a besoin que du minimum. Ce qui n’est pas nécessaire n’est pas collecté ; ce qui est facultatif est demandé explicitement.
-
Lieu facultatif et grossier
Coordonnées arrondies au millième de degré (environ 100 m), seulement si B l’autorise.
-
Capteurs réduits
Une moyenne quadratique par segment, en entiers. Pas de flux brut.
-
Rien en blockchain
Le registre ne contient que des racines de Merkle : ni vidéo, ni lieu, ni identifiant.
-
Vérification locale
Le vérificateur calcule tout dans le navigateur. Vos fichiers ne sont pas envoyés.
-
Conservation limitée
Vidéos et traces sont effacées à échéance ; voir la politique de confidentialité.