BUILD · TOOLS · SD-JWT INSPECTOR
Decode an SD-JWT VC. In your terminal, today.
This page is not a working tool. What belongs here is a text box: paste a token, see its header, its payload, and every disclosure decoded beside the digest it has to match. It is waiting on client-side JavaScript, which this site does not ship on any page. Until it lands, the recipe below does the identical job from a shell, and is arguably more useful — you can pipe it, script it, and run it on a token you would never paste into a stranger's website.
An SD-JWT VC is a JWT, a run of base64url-encoded disclosures, and optionally a key-binding JWT — all joined by ~. Decoding it is three base64url decodes, not a service.
What the tool would show
- The JWT header and payload, decoded — issuer, credential type, the
_sddigest array, the holder's public key incnf. - Every disclosure, decoded from its own base64url segment into
[salt, claim name, claim value]. - Whether each disclosure's digest is actually present in the signed
_sdarray — the check a naive decoder skips, and the reason a fifth verification check exists at all.
The recipe that does the same job now
Split on ~, base64url-decode each part, and pretty-print the JSON. No service sees your token.
SDJWT='<paste the ~-joined token here>'
JWT=${SDJWT%%~*}
echo "$JWT" | cut -d. -f1 | tr '_-' '/+' | base64 -d 2>/dev/null; echo
echo "$JWT" | cut -d. -f2 | tr '_-' '/+' | base64 -d 2>/dev/null | python3 -m json.tool
echo "$SDJWT" | tr '~' '\n' | tail -n +2 | grep -v '^eyJ0eXAiOiJrYitqd3Qi' | while read -r d; do
[ -z "$d" ] && continue
echo "$d" | tr '_-' '/+' | base64 -d 2>/dev/null | python3 -m json.tool
done What is real here.
The format this tool would decode is real and live-issued today. The browser tool itself does not exist — this site ships no client-side JavaScript on any page, by law, not by oversight.
The register holds 17 live · 2 partial · 2 planned · 5 not yet.
1 of the 1 capabilities this page depends on have no row in the register yet, so this page will not print a state for them. They are named rather than dropped, because a slice that silently shortens itself is the same defect as a claim with no receipt.
- selective-disclosure
The register route serves, but it carries no row for these yet. List what it does carry:
curl -s https://id.orbis.id/api/site/register | jq -r '.entries[].slug' Straight answers
- Can I paste a token into a box on this page right now?
- No. There is no box. There is a shell recipe.
- Does the recipe send my token anywhere?
- No — every step is local shell and Python, nothing is transmitted.
Do not trust us. Check us.