ACF
acfstandard.io
Developer docs
EN
Signatures

Vérifier en Node.js

Vérifiez la signature Ed25519 d’une sortie acf-mcp avec uniquement le module crypto standard de Node — zéro dépendance externe.

iNote
Le module node:crypto supporte Ed25519 nativement depuis Node 12. Aucune dépendance npm n’est requise. La clé publique est encodée en SPKI base64 (le format standard pour les clés Ed25519 publiques).

Version rapide

Si vous utilisez déjà le package acf-mcp dans votre projet, importez la fonction de vérification embarquée :

verify-quick.tstypescript
import { readFileSync } from "node:fs";
import { verifyDoctrineSignature } from "acf-mcp/lib/doctrine-signature";

const signed = JSON.parse(readFileSync("./tool-output.json", "utf8"));
const ok = verifyDoctrineSignature({
  contentHash: signed.doctrine_hash,
  signature: signed.doctrine_signature,
  publicKey: signed.doctrine_public_key,
});
console.log(ok ? "✓ signature valid" : "✗ signature INVALID");

Version standalone (zéro dépendance)

Si vous voulez intégrer la vérification dans un pipeline d’audit qui ne dépend pas du package acf-mcp (par exemple un job CI qui audite des sorties archivées), le snippet ci-dessous suffit. Il utilise uniquement node:crypto.

verify-doctrine.tstypescript
import { createPublicKey, verify } from "node:crypto";
import { readFileSync } from "node:fs";

// 1. Load the public key embedded in the acf-mcp release.
//    (For Node.js apps consuming the npm package, this lives at
//    node_modules/acf-mcp/dist/archive/doctrine-v1.0.json under
//    .meta.doctrine_public_key — the SPKI base64 form.)
const PUBLIC_KEY_SPKI_B64 =
  "MCowBQYDK2VwAyEAojtKfh20SGGV63LMETjZBXRWo2tY0viAYziG/y3/L0s=";

const publicKey = createPublicKey({
  key: Buffer.from(PUBLIC_KEY_SPKI_B64, "base64"),
  format: "der",
  type: "spki",
});

// 2. Read the signed tool output (anything returned by an acf.* tool).
const signed = JSON.parse(readFileSync("./tool-output.json", "utf8"));

// 3. Recompute what was signed: the doctrine_hash field as raw UTF-8.
const message = Buffer.from(signed.doctrine_hash, "utf8");

// 4. Strip the "ed25519:" prefix and decode the signature from base64.
const sigB64 = signed.doctrine_signature.replace(/^ed25519:/, "");
const signature = Buffer.from(sigB64, "base64");

// 5. Verify.
const ok = verify(null, message, publicKey, signature);
console.log(ok ? "✓ signature valid" : "✗ signature INVALID");

Ce qui est signé

La signature porte sur le hash de contenu (champ doctrine_hash, encodé sha256:hex) en tant que chaîne UTF-8. Ce hash est lui-même la somme SHA-256 du bundle de doctrine canonicalisé (fichiers triés par chemin, contenu brut, paths relatifs à la racine du contenu). Le code de calcul est dans le repo : scripts/build-archive-bundle.ts.

Modes d’échec

  • signature INVALID le contenu a été altéré OU la clé publique fournie n’est pas la bonne (mauvaise version d’acf-mcp). Re-télécharger la sortie de bout en bout et reverifier.
  • ERR_OSSL_EVP_DECODE_ERROR la signature ou la clé n’est pas du base64 valide. Vérifier qu’aucun caractère n’a été perdu en copier-coller.
  • UnsupportedKeyType Node < 12. Mettre à jour vers une version supportée par notre engine (node ≥ 18).