Jede Version eines veröffentlichten TracePass-Passes wird als signiertes W3C-verifiable credential im Format des digitalen Produktpasses UNTP 0.7.0 ausgestellt. Sie können prüfen, dass die Daten eines Passes von TracePass stammen und nicht verändert wurden, ohne Konto und ohne uns zu fragen. Diese Seite zeigt es am öffentlichen Demo-Pass.
1. Credential abrufen
curl --http2 -H "Accept: application/vc+jwt" \
https://id.tracepass.eu/01/99999999999997/21/6B27A0000001 \
-o credential.jwtDie Pass-URL selbst liefert das Credential, wenn Sie application/vc+jwt anfordern. Pass-URLs verlangen HTTP/2 (EN 18216), Werkzeuge, die nur HTTP/1.1 sprechen, erhalten daher 505. Der Link-Header der Antwort, das Linkset des Passes und der Kopf der HTML-Seite weisen auf das Credential hin. Ein Pass ohne signierte aktuelle Version antwortet mit 406, ein ausgesetzter, abgelaufener oder archivierter Pass liefert keins.
2. Header lesen
Das Credential ist ein kompakter JWS. Sein geschützter Header zeigt, wie es signiert wurde:
{
"alg": "ES256",
"typ": "vc+jwt",
"cty": "vc",
"kid": "did:web:www.tracepass.eu#key-1"
}Die Nutzlast ist das Credential selbst (VC-JOSE-COSE), kein vc-Claim aus VC 1.1. kid nennt den Aussteller und den Schlüssel, mit dem signiert wurde.
3. Schlüssel des Ausstellers auflösen
Aussteller ist did:web:www.tracepass.eu. Ein did:web-Identifikator wird zu einem Dokument auf dieser Domain aufgelöst, hier https://www.tracepass.eu/.well-known/did.json, das den öffentlichen Schlüssel unter dem kid aus dem Header veröffentlicht. Die Signatur bindet das Credential an die Kontrolle über die Domain.
4. Signatur prüfen
Beide Beispiele laden den Schlüssel und prüfen die ES256-Signatur:
// npm install jose
import { readFileSync } from "node:fs";
import { decodeProtectedHeader, importJWK, jwtVerify } from "jose";
const jws = readFileSync("credential.jwt", "utf8").trim();
const { kid } = decodeProtectedHeader(jws); // did:web:www.tracepass.eu#key-1
const did = kid.split("#")[0];
// did:web:<host> resolves to https://<host>/.well-known/did.json
const doc = await (await fetch(`https://${did.slice("did:web:".length)}/.well-known/did.json`)).json();
const method = doc.verificationMethod.find((m) => m.id === kid);
const { payload } = await jwtVerify(jws, await importJWK(method.publicKeyJwk, "ES256"), { typ: "vc+jwt" });
console.log("Verified. Issuer:", payload.issuer.id, "Product:", payload.credentialSubject.id);# pip install "pyjwt[crypto]" requests
import jwt, requests
token = open("credential.jwt").read().strip()
kid = jwt.get_unverified_header(token)["kid"] # did:web:www.tracepass.eu#key-1
did = kid.split("#")[0]
# did:web:<host> resolves to https://<host>/.well-known/did.json
doc = requests.get(f"https://{did.removeprefix('did:web:')}/.well-known/did.json").json()
jwk = next(m["publicKeyJwk"] for m in doc["verificationMethod"] if m["id"] == kid)
claims = jwt.decode(token, jwt.PyJWK(jwk).key, algorithms=["ES256"])
print("Verified. Issuer:", claims["issuer"]["id"], "Product:", claims["credentialSubject"]["id"])Ein nach der Signatur auch nur um ein Zeichen verändertes Credential scheitert mit einem Signaturfehler.
5. Format prüfen (optional)
Um zu bestätigen, dass das Credential UNTP 0.7.0 folgt, validieren Sie es gegen das offizielle UNTP-Schema:
# pip install jsonschema requests "pyjwt[crypto]"
import jwt, requests
from jsonschema import Draft202012Validator
token = open("credential.jwt").read().strip()
credential = jwt.decode(token, options={"verify_signature": False}) # verify first, as above
for claim in ("iss", "sub", "iat"):
credential.pop(claim, None) # JWT claims, not part of the credential
schema = requests.get("https://untp.unece.org/artefacts/schema/v0.7.0/dpp/DigitalProductPassport.json").json()
errors = [e.message for e in Draft202012Validator(schema).iter_errors(credential)]
print("UNTP 0.7.0 schema errors:", errors or "none")UNTP verlangt außerdem die Kennung der Produktionsstätte und das Herstellungsland. Das Credential enthält sie, wenn der Pass sie erfasst, und lässt sie sonst weg; es ist daher nur für solche Pässe vollständig gültig gegenüber dem UNTP-Schema. Der Demo-Pass validiert ohne Fehler.
Was eine gültige Signatur belegt
Dass TracePass genau diese Daten für diese Pass-Version ausgestellt hat und niemand sie seitdem verändert hat. Es ist eine did:web-Signatur: Sie belegt die Kontrolle über tracepass.eu, so stark wie HTTPS. Sie ist kein qualifiziertes elektronisches Siegel nach eIDAS.
Sie umfasst nur die öffentliche Ansicht des Passes, nie eingeschränkte oder behördliche Felder, daher ist sie nicht der vollständige rechtliche Datensatz. Eine Widerrufsliste gibt es noch nicht: Eine bereits gespeicherte Kopie lässt sich auch nach dem Aussetzen eines Passes weiter prüfen. Den aktuellen Status zeigt der Live-Pass.