Skip to main content

Offline verification library for Sanad Sign attestations — Ed25519 + CycloneDX + SHA-256 hash chain. India's sovereign attestation rail.

Project description

sanad-verify (Python)

Offline verification library for Sanad Sign attestations. Byte-for-byte compatible with the reference Node SDK — a signature produced by @cognoshift/sanad-sbom verifies here, and vice versa.

Built for CERT-In empanelled auditors, security reviewers, regulators, and internal compliance teams who live in Python.

Install

pip install sanad-verify

Only runtime dependency: cryptography. Supports Python 3.9+.

Verify a single attestation

import requests
from sanad_verify import verify_attestation

row = requests.get("https://sanad.cognoshift.in/api/sign/registry/<id>").json()

result = verify_attestation({
    "sbom":       row["sbom"],
    "signature":  row["signature"],
    "public_key": row["public_key"],
    "sbom_hash":  row["sbom_hash"],   # optional — recomputed regardless
})

print(result["valid"])            # True / False
print(result["signature_valid"])  # Ed25519 check
print(result["hash_match"])       # claimed vs recomputed SHA-256
print(result["computed_hash"])    # 'a3f5…'

Replay the hash chain

Given all attestations for a tenant (ordered ascending by created_at, id):

from sanad_verify import verify_chain

result = verify_chain(rows)

print(result["valid"])           # True when chain is intact
print(result["break_at"])        # id of first broken row, or None
print(result["first_mismatch"])  # detailed diagnostic

The genesis constant is SANAD_SIGN_GENESIS_2026 (exported as GENESIS). For a private deployment with a different genesis:

verify_chain(rows, genesis="MY_PRIVATE_GENESIS")

How verification works

  1. Canonicalize the SBOM — recursive sort of object keys, arrays preserve order, compact separators, UTF-8 preserved. Matches the subset of RFC 8785 JCS that CycloneDX exercises.
  2. Hash the canonical string with SHA-256. This is the sbom_hash.
  3. Verify the Ed25519 signature over the hex-encoded sbom_hash, using the public key stored on the row (SPKI format, base64-decoded from DER).
  4. Chain replay: for every row in the tenant's ledger, recompute SHA-256(event_hash || previous_chain_hash) and match against the stored chain_hash. previous_chain_hash is GENESIS for the first entry.

All four steps are deterministic. This library and the Node reference implementation produce identical output; either can verify attestations signed by the other.

Typing

The package ships a py.typed marker, so mypy / pyright / pylance pick up the full function signatures automatically.

License

Apache-2.0 — free for commercial audit use.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sanad_verify-0.1.0.tar.gz (5.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sanad_verify-0.1.0-py3-none-any.whl (5.7 kB view details)

Uploaded Python 3

File details

Details for the file sanad_verify-0.1.0.tar.gz.

File metadata

  • Download URL: sanad_verify-0.1.0.tar.gz
  • Upload date:
  • Size: 5.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for sanad_verify-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7e2ec0ca6b0d50996f89fb7c03ab8899813732536a0306f259b88b44441b66a6
MD5 c031602b0aabfcfca3f82885ddf6a911
BLAKE2b-256 bb3cc9dea9f778f4439b1d3c975b784eda299d58f87d06a6a9e061d150e95622

See more details on using hashes here.

File details

Details for the file sanad_verify-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: sanad_verify-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 5.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for sanad_verify-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 513b27a78e15f007fa73239ebbc8da867624a5259ea3dc386052bb7e31d11a31
MD5 f7b40dc022b3a3f4551a9a8cbe72c45f
BLAKE2b-256 663bb19617c6eceff36f38f49fc1688d3c3dffabe5735c5b1a729a86c486bc8f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page