Trustvice befindet sich in der eingeschränkten Beta. Bei der Registrierung oder Anmeldung müssen Sie das Beta-Tester-Passwort angeben, das Sie erhalten haben, oder eines anfordern unter preview@trustvice.com. Vielen Dank.
Wird geladen…
Engineering
Verifikation
Tutorial
Einen Beleg offline prüfen, in rund vierzig Zeilen Code
Ein durchgerechnetes Beispiel: Wir bauen mit WebCrypto einen Belegprüfer ohne Abhängigkeiten, testen ihn an einem signierten Testvektor, zeigen, dass er manipulierte Belege ablehnt, und übertragen das Verfahren auf Python und die Shell.
Von The Trustvice team··5 Min. Lesen
Kostenlos starten
Trustvice 360
Regeln festlegen. Jeden Lauf prüfen lassen.
Agenten, Nachweise, Governance, Handel und Offenlegung stecken in Trustvice 360. Kostenlos registrieren und alle Suiten in einem Dashboard öffnen.
Am stärksten prüfen Sie einen Trustvice-Beleg mit Code, den Sie kontrollieren, auf einem Rechner, den Sie kontrollieren, gegen Schlüssel, die Sie selbst gepinnt haben. Dieser Beitrag baut diesen Prüfer von null auf. Am Ende haben Sie ein einziges JavaScript-Modul ohne Abhängigkeiten, einen Testvektor, der beweist, dass es funktioniert, und Fälle, die beweisen, dass es scheitert, wenn es soll.
Node 20 oder neuer oder eine Runtime, deren crypto.subtle Ed25519 unterstützt: Aktuelle Browser, Deno, Bun und Cloudflare Workers erfüllen das alle. Nichts zu installieren. Auch ein Trustvice-Konto brauchen Sie nicht: Der Testvektor unten ist mit einem Wegwerfschlüssel signiert, der für diesen Beitrag erzeugt wurde.
Speichern Sie dies als receipt.json. Es ist ein Testbeleg, der mit diesem Wegwerfschlüssel signiert ist. Sein Body dient nur zur Illustration; entscheidend ist, dass er echt signiert ist.
Für echte Belege ersetzen Sie keys.json durch das publizierte Set unter https://trustvice.com/.well-known/receipt-keys.json, idealerweise eine gepinnte Kopie. Das Verfahren bleibt gleich.
Die Signatur deckt die kanonische Form nach RFC 8785 des Belegs ohne sein Feld signature ab. In JavaScript erzeugt JSON.stringify bereits die ECMAScript-Zahlendarstellung und minimales String-Escaping. Bleibt das rekursive Sortieren der Objekt-Keys nach UTF-16-Codeeinheit, die Standardreihenfolge von Array.prototype.sort:
js
function canonicalize(value) {
if (Array.isArray(value)) return value.map(canonicalize);
if (value && typeof value === "object") {
return Object.fromEntries(
Object.keys(value).sort().map((key) => [key, canonicalize(value[key])]),
);
}
return value;
}
exportconst jcs = (value) => JSON.stringify(canonicalize(value));
Für den Testvektor ist der kanonische String eine Zeile ohne Leerraum:
Beachten Sie die Destrukturierungszeile. Sie entfernt signature und behält alles andere, auch Felder, die dieser Code nie gesehen hat. Das ist Absicht: Jedes Feld außer signature ist signiert, also würde ein Prüfer, der ein Feld verwirft, das er nicht kennt, gültige Belege ablehnen.
Fügen Sie die drei Snippets in verify-receipt.mjs zusammen. Das ist der ganze Prüfer.
Ein kleiner Kommandozeilen-Wrapper liest die Dateien und endet mit 0 bei gültigem Beleg, sonst mit 1. Er akzeptiert auch den Wrapper { "receipt": … }, den die API liefert:
Die kid ist aus dem Schlüssel abgeleitet: base64url der ersten 16 Bytes des SHA-256 der 32 Rohbytes von x. Für den Testschlüssel ergibt das LfPAIisXFvNmFhD6vBQbBw. Die Neuberechnung bestätigt, dass der Eintrag in Ihrer Schlüsseldatei in sich stimmig ist:
js
exportasyncfunction keyIdOf(x) {
const digest = await crypto.subtle.digest("SHA-256", base64urlToBytes(x));
let bin = "";
for (const b ofnew Uint8Array(digest).slice(0, 16)) bin += String.fromCharCode(b);
return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
Das Verfahren ist überall gleich, aber zwei Sprachen brauchen Sorgfalt.
Python.json.dumps ist kein JCS: Es gibt ganzzahlige Floats als 1.0 aus, füllt Exponenten auf und escaped standardmäßig Nicht-ASCII. Eine Python-Portierung braucht einen kleinen RFC-8785-Serialisierer, der Keys nach UTF-16-Codeeinheit sortiert, und kann mit Ed25519PublicKey aus dem Paket cryptography prüfen.
Shell. Mit jq und OpenSSL 3 erzeugt jq -S -c 'del(.signature)' die kanonischen Bytes für Belege, weil deren Bodys nur Strings, Ganzzahlen, Booleans, null, Arrays und Objekte enthalten. Das ist keine allgemeine JCS-Implementierung, aber bei einem Beleg passt es oder scheitert; es lässt nie einen durch, der scheitern sollte. Der öffentliche Schlüssel wird als DER SubjectPublicKeyInfo verpackt, indem man den 32 Rohbytes einen festen 12-Byte-Header voranstellt, und openssl pkeyutl -verify -rawin erledigt den Rest. Das LibreSSL von macOS kann das nicht; installieren Sie OpenSSL 3.
Eine gültige Signatur beweist Herkunft, Integrität und eine signierte Zeit: Der Inhaber eines Trustvice-Signaturschlüssels signierte genau diese Bytes, seither änderte sich nichts, und Trustvice bestätigt die Zeit in issuedAt. Sie beweist nicht, dass ein von Ihnen gelieferter Fakt stimmt, und sie enthält Ihre Inhalte nicht. Um zu zeigen, dass ein Dokument zu einem Beleg passt, hashen Sie es selbst und vergleichen. Diese Grenzen behandelt Was ein Beleg beweist und was nicht.
Für eine schnelle Prüfung ohne Code fügen Sie einen beliebigen Beleg in /verify ein. Dort läuft dasselbe Verfahren in Ihrem Browser, und der Beleg geht nie an uns.
Fügen Sie einen beliebigen Trustvice-Beleg in den Prüfer ein. Er prüft die Signatur in Ihrem Browser gegen unsere veröffentlichten Schlüssel, ganz ohne Konto.