How to verify a certificate without Needine

Everything the verification page checks can be repeated with standard tools and without relying on Needine. All you need is the certificate's JSON export.

1. Download the JSON export

On the certificate page, click “Export JSON”. The file contains the signed content, the signature, the Merkle proofs and the timestamp token.

2. Check integrity and signature

The SHA-256 of certificate.canonicalPayload must equal canonicalPayloadHash, and the Ed25519 signature must verify over that hash with a key Needine publishes at /.well-known/needine-keys.json.

3. Check the blockchain anchor

Applying blockchain.merkleProof to canonicalPayloadHash must give blockchain.merkleRoot. Then getAnchor(onChainAnchorId) on the contract on Arbitrum One must return that same root; any block explorer shows it.

4. Check the RFC 3161 timestamp

Applying qualifiedTimestamp.merkleProof to canonicalPayloadHash must give qualifiedTimestamp.merkleRoot. Save the 32 bytes of that root and the token, and verify them with OpenSSL:

# root.bin: the 32 bytes of qualifiedTimestamp.merkleRoot · token.tst: qualifiedTimestamp.tokenBase64
node -e "const t=require('./certificate.json').qualifiedTimestamp, fs=require('fs');
fs.writeFileSync('root.bin', Buffer.from(t.merkleRoot, 'hex'));
fs.writeFileSync('token.tst', Buffer.from(t.tokenBase64, 'base64'))"

# tsa-chain.pem: the certificate chain of the timestamp authority
openssl ts -verify -token_in -in token.tst -data root.bin -CAfile tsa-chain.pem

5. Check whether the authority was qualified

Look up the authority that signed the token in the EU trusted lists: a qualified time-stamping service (QTST) appears with status “granted” on the date of the stamp. The authority Needine uses today is not qualified, and the verification page says so. Use the official browser or validate the token with the European Commission's DSS tool.

6. Or do it all with our SDKs

The SDKs run the same checks locally: signature, Merkle proofs, RFC 3161 token and EU trusted lists.

npm install @needine/sdk

import { readFileSync } from "fs";
import { verifyBundle, verifyBundleTimestamp, verifyBundleQualification } from "@needine/sdk";

const bundle = JSON.parse(readFileSync("certificate.json", "utf8"));
const { keys } = await (await fetch("https://api.needine.com/.well-known/needine-keys.json")).json();

verifyBundle(bundle, keys);              // integrity, signature, Merkle proofs
await verifyBundleTimestamp(bundle);     // RFC 3161 token
await verifyBundleQualification(bundle); // EU trusted lists
pip install "needine-sdk[verify]"

from needine import verify_bundle
result = verify_bundle(bundle, keys)  # integrity, signature, Merkle proofs

Needine takes no part in any of these checks: if Needine disappeared, the proof would remain verifiable.