Public Key Registry
๐Ÿ”‘ This key is used to sign Enterprise compliance reports. To generate signed evidence packages for your AI agents, contact us at hello@cyphrex.io Contact sales โ†’
ACTIVE

cyphrex-signer-prod-01

Ed25519 signing key ยท Active since 2026-05-06 ยท Public record

KEY ID

cyphrex-signer-prod-01

ALGORITHM

Ed25519 (EdDSA)

STATUS

Active

ACTIVATED

2026-05-06

KEY NUMBER

KEY โ„–0001

NETWORK

Public record

PUBLIC KEY

Loading key...

VERIFY A REPORT

Fetch this key

curl https://cyphrex.io/api/keys/cyphrex-signer-prod-01

Build canonical payload + verify (Node.js, v1.0.0)

The full timestamp object is included in the signed payload. Strip only sha256, signature, algorithm, and publicKeyUrl from the downloaded JSON before canonical JSON and verification.

// =============================================================================
// Cyphrex signed report โ€” build canonical bytes + verify (schemaVersion 1.0.0)
// =============================================================================
// Environment:
//   - Node.js 18+ (LTS recommended). Uses only the built-in `crypto` module โ€” no npm install.
//   - Optional: `fs` (also built-in) if you load JSON/PEM from disk; uncomment the example below.
//
// You must define these two values (paste JSON, or use fs.readFileSync โ€” see comments at bottom):
//   const report = ...        // full object from POST /v1/events/export-signed
//   const publicKeyPem = `...` // PEM from GET https://cyphrex.io/keys/<keyId> (this page)
// =============================================================================

const { createHash, verify, createPublicKey } = require('crypto');

function sortKeysDeep(value) {
  if (value === null || typeof value !== 'object') return value;
  if (Array.isArray(value)) return value.map(sortKeysDeep);
  const out = {};
  Object.keys(value)
    .sort()
    .forEach((k) => {
      out[k] = sortKeysDeep(value[k]);
    });
  return out;
}

function stableStringify(obj) {
  return JSON.stringify(sortKeysDeep(obj));
}

function signedReportCoreFromDownload(report) {
  const copy = JSON.parse(JSON.stringify(report));
  delete copy.sha256;
  delete copy.signature;
  delete copy.algorithm;
  delete copy.publicKeyUrl;
  // timestamp.anchor_tx_signature is part of the signed payload, no special exclusion needed.
  return copy;
}

// --- Example: load from files (optional) ---
// const fs = require('fs');
// const report = JSON.parse(fs.readFileSync('cyphrex-report.json', 'utf8'));
// const publicKeyPem = fs.readFileSync('cyphrex-public.pem', 'utf8');

// --- Example: inline paste (replace with your real values) ---
// const report = { ... };
// const publicKeyPem = `-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n`;

if (typeof report === 'undefined') throw new Error('Define `report` (see comments at top of this snippet).');
if (typeof publicKeyPem === 'undefined') throw new Error('Define `publicKeyPem` (see comments at top of this snippet).');

const reportContent = stableStringify(signedReportCoreFromDownload(report));

const computedHash = createHash('sha256').update(reportContent, 'utf8').digest('hex');
if (computedHash !== report.sha256) throw new Error('Hash mismatch');

const publicKey = createPublicKey(publicKeyPem);
const isValid = verify(
  null, // required for Ed25519
  Buffer.from(reportContent, 'utf8'),
  publicKey,
  Buffer.from(report.signature, 'base64')
);

console.log(isValid ? 'Valid signature' : 'Invalid signature');

Verify only (Node.js)

// =============================================================================
// Cyphrex signed report โ€” verify only (schemaVersion 1.0.0)
// =============================================================================
// Node.js 18+. Built-in `crypto` only โ€” no npm packages.
//
// You must define:
//   canonical   โ€” UTF-8 string: stableStringify(signedReportCoreFromDownload(report))
//                   (NOT the full downloaded JSON; see the "Build canonical" snippet above.)
//   signature   โ€” base64 string from report.signature
//   publicKeyPem โ€” PEM from this registry page
// =============================================================================

const { verify, createPublicKey } = require('crypto');

if (typeof canonical === 'undefined') throw new Error('Define `canonical` (see comments at top of this snippet).');
if (typeof signature === 'undefined') throw new Error('Define `signature` (see comments at top of this snippet).');
if (typeof publicKeyPem === 'undefined') throw new Error('Define `publicKeyPem` (see comments at top of this snippet).');

const publicKey = createPublicKey(publicKeyPem);
const isValid = verify(
  null, // null algorithm for Ed25519
  Buffer.from(canonical, 'utf8'),
  publicKey,
  Buffer.from(signature, 'base64')
);

console.log(isValid ? 'Valid signature' : 'Invalid signature');