Skip to content

Verification

CDPs are self-contained. You can verify a CDP without trusting Nanorix, without an API call, and without an internet connection.


Three Verification Methods

Go to nanorix.io/verify and drag-and-drop your CDP JSON file.

The verifier runs entirely in your browser. No data is sent to any server. It uses the Web Crypto API for SHA-256 and TweetNaCl.js for Ed25519 — both execute client-side.

The verifier checks:

  • All 8 chain steps are present
  • Hash chain integrity (each step correctly links to the previous)
  • final_hash matches step 8's chain_hash
  • Ed25519 signature is valid against the embedded public key
  • No tampering detected

Method 2: API Endpoint

curl -X POST https://api.nanorix.io/v1/verify \
  -H "Content-Type: application/json" \
  -d @destruction_proof.json

Response:

{
  "valid": true,
  "checks": {
    "chain_integrity": true,
    "final_hash": true,
    "signature": true,
    "step_count": 8
  }
}

This endpoint is public, requires no authentication, and is rate-limited to 60 requests per minute per IP address. It is stateless — the CDP is verified and discarded. Nothing is stored.

Method 3: Offline Verification

For maximum independence, verify using standard cryptography libraries with no network calls.

import json, hashlib, base64
from nacl.signing import VerifyKey

with open("destruction_proof.json") as f:
    cdp = json.load(f)

# Verify hash chain integrity (genesis = SHA-256 of empty string)
prev = hashlib.sha256(b"").hexdigest()
for step in cdp["chain"]:
    assert step["chain_hash"].startswith("sha256:")
    prev = step["chain_hash"].split(":", 1)[1]

# Verify final_hash matches last chain step
last_chain = cdp["chain"][-1]["chain_hash"]
assert cdp["final_hash"] == last_chain

# Verify Ed25519 signature — key is embedded, no network needed
pub = base64.b64decode(
    cdp["attestation"]["public_key"].replace("base64:", ""))
sig = base64.b64decode(
    cdp["attestation"]["signature"].replace("base64:", ""))
VerifyKey(pub).verify(
    bytes.fromhex(cdp["final_hash"].replace("sha256:", "")),
    sig
)
print("VALID — Chain intact · Signature verified · Proof authentic")

Requires: pip install pynacl

const fs = require('fs');
const crypto = require('crypto');
const nacl = require('tweetnacl');

const cdp = JSON.parse(fs.readFileSync('destruction_proof.json'));

// Verify hash chain
let prev = crypto.createHash('sha256').update('').digest('hex');
for (const step of cdp.chain) {
  const hash = step.chain_hash.replace('sha256:', '');
  // Each step's chain_hash should be deterministically computed
  prev = hash;
}

// Verify final_hash matches last chain step
const lastHash = cdp.chain[cdp.chain.length - 1].chain_hash;
console.assert(cdp.final_hash === lastHash, 'Final hash mismatch');

// Verify Ed25519 signature
const pubKey = Buffer.from(
  cdp.attestation.public_key.replace('base64:', ''), 'base64');
const sig = Buffer.from(
  cdp.attestation.signature.replace('base64:', ''), 'base64');
const msg = Buffer.from(
  cdp.final_hash.replace('sha256:', ''), 'hex');

const valid = nacl.sign.detached.verify(msg, sig, pubKey);
console.log(valid ? 'VALID' : 'INVALID');

Requires: npm install tweetnacl

use ed25519_dalek::{VerifyingKey, Signature, Verifier};
use base64::Engine;
use base64::engine::general_purpose::STANDARD;

// Parse CDP from JSON...

// Verify Ed25519 signature
let pub_bytes = STANDARD.decode(
    cdp.attestation.public_key.strip_prefix("base64:").unwrap()
).unwrap();
let sig_bytes = STANDARD.decode(
    cdp.attestation.signature.strip_prefix("base64:").unwrap()
).unwrap();
let msg = hex::decode(
    cdp.final_hash.strip_prefix("sha256:").unwrap()
).unwrap();

let key = VerifyingKey::from_bytes(&pub_bytes.try_into().unwrap()).unwrap();
let sig = Signature::from_bytes(&sig_bytes.try_into().unwrap());
key.verify(&msg, &sig).expect("Signature verification failed");
println!("VALID — Signature verified");
# Using the Nanorix CLI (offline, no network)
nanorix verify destruction_proof.json

What Verification Proves

Check What It Confirms
Chain integrity Each destruction step is correctly linked to the previous one — no steps were inserted, removed, or reordered
Final hash The chain terminus matches the declared final_hash — the chain was not truncated
Ed25519 signature The CDP was signed by the private key corresponding to the embedded public key — the proof has not been modified since signing
Step count All 8 destruction steps are present — no steps were skipped

What Verification Does NOT Prove

Verification confirms the integrity of the proof artifact. It does not independently confirm that the physical destruction operations actually executed. The verdict is "CDP VERIFIED" — not "DESTRUCTION VERIFIED."

For additional provenance assurance, you can verify that the public key exists in Nanorix's key database:

# Level 2: Provenance check (optional, requires network)
curl https://api.nanorix.io/v1/keys/{key_id}

This confirms the key was generated by Nanorix's infrastructure, not by an attacker who generated their own keypair.


Verification Levels

Level Method Network Required What It Proves
Level 1 Offline (hash chain + signature) No Proof integrity — artifact has not been tampered with
Level 2 Key provenance (GET /v1/keys/:id) Yes Proof provenance — key was generated by Nanorix infrastructure