Verifier SDK
Reference implementations in JavaScript, Python, and Go. Each verifies a Sanad-signed artifact with no network calls, no external dependencies beyond standard libraries (Go) or one well-known crypto library (Python).
Every signed Sanad artifact ships exactly three top-level fields:
signed_payload — the JSON object that was signedsignature — 64-byte Ed25519 signature, hex-encodedpublic_key — 32-byte raw Ed25519 public key, hex-encodedThe signature is over canonical-JSON: keys sorted lexicographically, no whitespace, standard escaping. Both signer and verifier must produce the same byte string for the same logical object — that's what canonical-JSON guarantees.
// JavaScript / Node — verify a Sanad artifact offline.
import { webcrypto } from "node:crypto"; // Node 18+
function canonical(value) {
if (value === null || typeof value !== "object") return JSON.stringify(value);
if (Array.isArray(value)) return "[" + value.map(canonical).join(",") + "]";
return "{" + Object.keys(value).sort()
.map(k => JSON.stringify(k) + ":" + canonical(value[k])).join(",") + "}";
}
function hexToBytes(hex) {
const clean = hex.replace(/\s+/g, "");
const out = new Uint8Array(clean.length / 2);
for (let i = 0; i < clean.length; i += 2) out[i / 2] = parseInt(clean.slice(i, i + 2), 16);
return out;
}
const SPKI_PREFIX = new Uint8Array([
0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
]);
export async function verifySanadArtifact(artifact) {
const sig = hexToBytes(artifact.signature);
const raw = hexToBytes(artifact.public_key);
const spki = new Uint8Array(SPKI_PREFIX.length + raw.length);
spki.set(SPKI_PREFIX, 0);
spki.set(raw, SPKI_PREFIX.length);
const key = await webcrypto.subtle.importKey(
"spki", spki, { name: "Ed25519" }, true, ["verify"],
);
const payload = new TextEncoder().encode(canonical(artifact.signed_payload));
return webcrypto.subtle.verify("Ed25519", key, sig, payload);
}
// Usage:
const valid = await verifySanadArtifact(JSON.parse(artifactJson));
console.log(valid ? "verifies" : "does NOT verify");# Python — verify a Sanad artifact offline.
# pip install cryptography
import json
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
from cryptography.exceptions import InvalidSignature
def canonical(value) -> str:
if value is None or not isinstance(value, (dict, list)):
return json.dumps(value, separators=(",", ":"))
if isinstance(value, list):
return "[" + ",".join(canonical(x) for x in value) + "]"
keys = sorted(value.keys())
return "{" + ",".join(json.dumps(k) + ":" + canonical(value[k]) for k in keys) + "}"
def verify_sanad_artifact(artifact: dict) -> bool:
pub = Ed25519PublicKey.from_public_bytes(bytes.fromhex(artifact["public_key"]))
sig = bytes.fromhex(artifact["signature"])
payload = canonical(artifact["signed_payload"]).encode("utf-8")
try:
pub.verify(sig, payload)
return True
except InvalidSignature:
return False
# Usage:
with open("artifact.json") as f:
artifact = json.load(f)
print("verifies" if verify_sanad_artifact(artifact) else "does NOT verify")// Go — verify a Sanad artifact offline. Standard library only.
package sanadverify
import (
"crypto/ed25519"
"encoding/hex"
"encoding/json"
"fmt"
"sort"
"strings"
)
func canonical(v any) string {
switch x := v.(type) {
case nil:
return "null"
case bool, float64:
b, _ := json.Marshal(x)
return string(b)
case string:
b, _ := json.Marshal(x)
return string(b)
case []any:
parts := make([]string, len(x))
for i, item := range x { parts[i] = canonical(item) }
return "[" + strings.Join(parts, ",") + "]"
case map[string]any:
keys := make([]string, 0, len(x))
for k := range x { keys = append(keys, k) }
sort.Strings(keys)
parts := make([]string, len(keys))
for i, k := range keys {
kb, _ := json.Marshal(k)
parts[i] = string(kb) + ":" + canonical(x[k])
}
return "{" + strings.Join(parts, ",") + "}"
}
return "null"
}
type Artifact struct {
SignedPayload any `json:"signed_payload"`
Signature string `json:"signature"`
PublicKey string `json:"public_key"`
}
func Verify(a *Artifact) (bool, error) {
pub, err := hex.DecodeString(a.PublicKey)
if err != nil { return false, fmt.Errorf("public_key hex: %w", err) }
if len(pub) != ed25519.PublicKeySize {
return false, fmt.Errorf("public_key wrong size: %d", len(pub))
}
sig, err := hex.DecodeString(a.Signature)
if err != nil { return false, fmt.Errorf("signature hex: %w", err) }
payload := []byte(canonical(a.SignedPayload))
return ed25519.Verify(pub, payload, sig), nil
}The reference implementations above are MIT-licensed. Copy them into your audit toolchain. We'll publish packaged libraries under @sanad/verifier (npm), sanad-verifier (PyPI), and github.com/anupam9091/sanad-verifier-go as the open-source repos mature post first-pilot.
Found a bug? Email security@cognoshift.in — covered by our disclosure programme.