Here is the strongest claim we make about Probatum, stated plainly: you do not need to trust Probatum to verify a Probatum-issued credential. Most compliance tooling cannot say that. The proof lives inside the vendor’s platform; pull the plug and the proof goes dark with it. Our evidence packages are designed to outlive us. To show you exactly what that means, this is a hands-on walkthrough: verifying a real signed credential using only standard tools — openssl, jq, and a few lines of python. No Probatum binaries. No npm install. No login.
What’s in the package
A Probatum evidence package is a JSON file built on the W3C Verifiable Credentials data model. It has two halves that matter for verification:
- The credential body — the actual claim: which framework was audited, which controls, the score, timestamps, and the issuer’s decentralized identifier (
did:key). - The proof block — an
Ed25519Signature2020object containing the signature value and the verification method (which public key signed it).
The whole game is: recompute what was signed, fetch the public key, and check the signature. Then confirm the credential hasn’t been revoked. Five steps.
Step 1 — Extract the payload
Pull the credential apart so you can work with the signed body and the proof separately. jq is enough:
jq 'del(.proof)' package.vc.jsongives you the credential without its proof — this is what the signature actually covers.jq -r '.proof.proofValue' package.vc.jsongives you the signature.jq -r '.proof.verificationMethod' package.vc.jsontells you which key to check it against.
Nothing here is Probatum-specific. These are ordinary fields defined by the W3C spec, readable by any JSON tool on earth.
Step 2 — Recover the issuer’s public key
The verification method is a did:key identifier. The elegant property of did:key is that the public key is encoded inside the identifier itself — there is no registry to query, no server to call. The string after did:key:z is a multibase-encoded, multicodec-prefixed Ed25519 public key. Decode the base58 payload, strip the two-byte 0xed01 multicodec prefix, and you are left with the raw 32-byte Ed25519 public key. A few lines of Python with a base58 routine recover it; no network access required.
Step 3 — Canonicalize the credential
Signatures are computed over bytes, and JSON can serialize the same object many ways (key order, whitespace). So before signing, the credential is canonicalized with JCS (JSON Canonicalization Scheme, RFC 8785), which produces one deterministic byte sequence for a given object. To verify, you canonicalize the proof-stripped body the same way. Python’s json.dumps(obj, sort_keys=True, separators=(',', ':'), ensure_ascii=False) gets you the JCS form, and you hash it to get the exact digest that was signed.
Step 4 — Verify the Ed25519 signature
Now you have three things: the canonical bytes of the credential, the 32-byte public key from Step 2, and the signature from Step 1. Ed25519 verification is a single library call:
- With Python’s
cryptographypackage:Ed25519PublicKey.from_public_bytes(pubkey).verify(signature, message). It returns cleanly on success and raisesInvalidSignatureon failure. - Prefer no Python dependency?
openssl pkeyutl -verifywith the key in raw form does the same job.
If it verifies, you have established two facts with mathematical certainty: the credential was signed by the holder of that private key, and not a single byte has changed since. Edit any field — bump the score, change a date — and re-run: verification fails instantly. Try it. That is the whole point.
Step 5 — Check revocation
A valid signature proves authenticity and integrity, but not that the credential is still current. Probatum uses StatusList2021 for revocation: the credential references a position in a published, compressed bitstring. To check it, fetch the status list, decompress it, and read the bit at the credential’s index. 0 means active; 1 means revoked. The status list reveals nothing about any individual credential, which is exactly why it is privacy-preserving — but it lets anyone confirm a credential hasn’t been pulled.
Why there’s no server to call
It is worth dwelling on the did:key choice, because it is what makes the whole thing portable. Many identity systems put the public key behind a lookup — a DID registry, a hosted .well-known endpoint, a certificate authority. Every one of those is a dependency that can disappear, get blocked, or be quietly changed. did:key takes the opposite path: the key is the identifier. Decoding the DID yields the public key directly, with no third party in the loop.
That single decision is why an evidence package verifies offline, on a laptop with no network, a decade from now, long after any particular hosting arrangement has changed. The credential carries everything needed to check it. Combined with JCS canonicalization and a published status list for revocation, the only external thing you ever fetch is a public, privacy-preserving bitstring — and even that reveals nothing about the credential you hold. The trust surface is deliberately tiny.
Putting it together
End to end, the verification reads like a short script you could paste into a terminal: extract the body and proof with jq, decode the did:key to recover the public key, canonicalize the body with JCS and hash it, verify the Ed25519 signature against that digest, then read the revocation bit from the status list. Each step is a few lines; the whole thing runs in under a second and touches the network only to fetch the public status list. There is no point at which you hand control to a Probatum process or accept an answer on faith.
The deliberate design goal is that a skeptical auditor — someone whose job is to not trust vendors — can satisfy themselves entirely from first principles. They never have to believe a dashboard. They re-derive the result.
Common failure modes (and what they mean)
When verification fails, the failure is informative rather than mysterious:
- Signature invalid: either the credential body was altered after signing, or you canonicalized differently than the issuer. Re-check that you deleted the proof block before hashing and used strict JCS ordering.
- Key mismatch: the public key you decoded doesn’t match the one that signed. Confirm you stripped the multicodec prefix and used the key referenced by
verificationMethod, not a different one. - Revoked: the signature is fine but the status-list bit is flipped to
1. The credential was authentic but has since been pulled — itself a meaningful, verifiable fact.
In every case you learn something concrete about the credential, which is the opposite of a closed portal that simply shows a green checkmark you cannot interrogate.
Why this matters
Five steps, three commodity tools, zero vendor dependencies, no dashboard, no account. That is not a demo trick — it is the architecture. The proof of your compliance is a self-contained file whose validity rests on open standards and public-key cryptography, not on Probatum’s servers continuing to exist or our company continuing to pay its hosting bill.
Now run the same thought experiment against your current GRC tool. If the only way to confirm a finding is to log into the vendor’s portal, and pulling the plug on that vendor also pulls the proof, then you do not really have proof. You have a subscription that displays a claim. Probatum issues evidence an auditor can verify by hand, today or ten years from now. That is the difference between trusting a vendor and verifying the math.