Skip to main content

sovp-python

sovp-python is the reference implementation of the Sovereign Validation Protocol (SOVP) — a pre-ingestion verification protocol that lets LLMs and autonomous agents cryptographically confirm the identity and integrity of a data source before parsing it. It exists because existing mechanisms (DANE, DIDs, TLS) operate at the wrong layer for agentic pipelines: SOVP sits at Layer 0, before the body is read. To get started: clone the repo and run pip install -e . — this exposes both a sovp.core Python API and a sovp CLI with three commands.

Protocol specification: draft-litzki-sovp — IETF Internet-Draft

CI License Python IETF Draft Status


What SOVP does

SOVP answers one question deterministically: does this data originate from the declared entity, and has it been tampered with?

It does not validate semantic accuracy or truthfulness. It validates identity and integrity only.

Psi_core = Verify(K_pub, sigma, JCS(M))

Psi_core = 1 — source verified, proceed with ingestion.
Psi_core = 0 — verification failed, ingestion blocked.

Scope of this reference implementation: This library provides Ed25519 signing and verification primitives for SOVP identity documents. Full protocol execution — including DNS TXT record resolution, HTTP retrieval of /.well-known/sovp-identity.json, and Mode B gateway behavior — is implementation-defined and not included in this package.


Position in the agentic trust stack

SOVP is the infrastructure attestation layer inside a broader agentic trust stack. The four layers, from discovery to runtime:

Layer Concern Mechanism
Discovery Is the source findable and routable? DNS, service registries, ai-catalog.json
Install safety Is the artifact what it claims to be before execution? contentAddress digest (SHA-256 over JCS bytes), SOVP trustManifest type
Infrastructure trust Does the serving entity control the domain and key? SOVP sovp-identity.json, _sovp DNS TXT, Ed25519 proof
Runtime governance Is the agent permitted to act on this data in this context? Policy engines, capability tokens, audit logs

SOVP operates at layers 2 and 3. If you arrived here from ards-project/ard-spec issue #41: the trustManifest type in an ai-catalog.json entry maps to layer 2 — it binds a catalog entry's contentAddress digest to an independently verifiable infrastructure attestation, so a consuming agent can confirm the entry was produced by the declared entity before acting on it.


How is this different from DANE or DIDs?

SOVP DANE W3C DIDs
Target Agentic / LLM ingestion pipelines TLS certificate validation Decentralized identity
Layer Layer 0 (pre-ingestion) Transport layer Application layer
Trigger Before body parsing TLS handshake On-demand resolution
DNS anchor _sovp TXT record _dane TLSA record DID document

Installation

pip install sovp

For development, clone the repo instead:

git clone https://github.com/litzki-systems/sovp-python.git
cd sovp-python
pip install -e .

This installs the sovp CLI and the sovp.core library. Dependencies (cryptography, canonicaljson) are declared in pyproject.toml.


End-to-end example

The fastest way to see SOVP in action — generate a keypair, sign an identity document, verify it, and watch tamper detection fire:

from sovp.core import generate_keypair, generate_identity_document, verify_identity

# 1. Generate keys — publish public_key_b64 in your DNS TXT record
private_key_b64, public_key_b64 = generate_keypair()

# 2. Build and sign — serve this JSON at /.well-known/sovp-identity.json
document = generate_identity_document(
    private_key_b64=private_key_b64,
    entity_uid="urn:sovp:example-entity",
    canonical_url="https://example.com",
)

# 3. Verify (Psi_core)
signature = document["integrity_proof"]["signature"]
psi_core = verify_identity(document, signature, public_key_b64)
print("Psi_core =", 1 if psi_core else 0)   # → 1

# 4. Tamper detection
document["entity"]["canonical_url"] = "https://attacker.com"
psi_core = verify_identity(document, signature, public_key_b64)
print("Psi_core =", 1 if psi_core else 0)   # → 0  (blocked)

A runnable version with annotated output is in examples/end_to_end.py:

python examples/end_to_end.py

Usage

Python API

Generate a key pair

from sovp.core import generate_keypair

private_key_b64, public_key_b64 = generate_keypair()
print(public_key_b64)   # publish this in your DNS TXT record
print(private_key_b64)  # keep this secret

Sign an identity payload

from sovp.core import sign_identity
import json

# Non-proof fields only — integrity_proof is always excluded from the signed scope
# (draft Section 4 MUST). sign_identity() will strip it automatically if present.
metadata = {
    "@context": "https://litzki-systems.com/protocol/v1.4",
    "@type": "SovereignIdentity",
    "entity": {
        "uid": "urn:sovp:your-entity-id",
        "canonical_url": "https://yourdomain.com",
        "verification_method": "Ed25519"
    }
}

signature = sign_identity(private_key_b64, metadata)

signed_payload = {
    **metadata,
    "integrity_proof": {
        "signature": signature,
        "created": "2026-01-01T00:00:00Z",
        "public_key_ref": "dns:txt:_sovp.yourdomain.tld"
    }
}

with open("sovp-identity.json", "w") as f:
    json.dump(signed_payload, f, indent=2)

sign_identity() always strips integrity_proof before canonicalizing, so callers may pass the full document or only the non-proof fields — the result is identical. The signature cannot cover itself.

Verify (Psi_core)

from sovp.core import verify_identity

# Pass the full document or the non-proof subset — both work identically.
# Enable check_timestamp=True to enforce the 600-second validity window
# (draft Section 7.2 SHOULD).
psi_core = verify_identity(signed_payload, signature, public_key_b64, check_timestamp=True)

if psi_core:
    print("Psi_core = 1: Verified.")
else:
    print("Psi_core = 0: Ingestion blocked.")

CLI

sovp generate-keypair
sovp sign   --payload test_payload.json --privkey <base64-private-key>
sovp verify --payload test_payload.json --sig <base64-signature> --pubkey <base64-public-key>

Technical foundation

Primitive Specification
Signatures Ed25519 (RFC 8032)
Canonicalization JSON Canonicalization Scheme / JCS (RFC 8785)
Hashing Ed25519 pure mode (RFC 8032) — sign(JCS(M)), no external pre-hash applied
Key distribution DNS TXT at _sovp.yourdomain.tld
Replay protection created timestamp validation (600 s window, check_timestamp=True); nonce deduplication not yet implemented — see Roadmap

The sovp-identity.json schema

{
  "@context": "https://litzki-systems.com/protocol/v1.4",
  "@type": "SovereignIdentity",
  "entity": {
    "uid": "urn:sovp:your-entity-id",
    "canonical_url": "https://yourdomain.com",
    "verification_method": "Ed25519"
  },
  "integrity_proof": {
    "signature": "<Ed25519 signature, base64>",
    "created": "2026-03-19T10:00:00Z",
    "public_key_ref": "dns:txt:_sovp.yourdomain.tld",
    "nonce": "optional-unique-string"
  },
  "contentAddress": {
    "digest": "sha256:<hex-encoded SHA-256 over JCS-canonical bytes of the non-proof fields>"
  },
  "parameters": {
    "entropy_threshold": 0.12,
    "determinism_score": 0.98
  }
}

contentAddress (optional, draft Section 4): contentAddress.digest is a SHA-256 hash computed over the JCS-canonical representation of all non-proof, non-contentAddress fields. A verifier independently recomputes it as sha256(JCS(doc_without_proof_and_contentAddress)) and compares the hex string. This lets downstream consumers (e.g. an ai-catalog.json entry) bind a catalog record to the exact document bytes without re-running the Ed25519 signature check. contentAddress is excluded from the Ed25519 signed scope — it is computed after signing, from the same byte range the signature covers.

Note: parameters is non-normative and MUST NOT be used for trust decisions (draft Section 4). It is excluded from the signed scope.

Serve this file at https://yourdomain.com/.well-known/sovp-identity.json.


DNS setup

_sovp.yourdomain.tld  IN  TXT  "v=SOVP1; k=<your-Ed25519-public-key-base64>"

Recommended TTL: 300 seconds (per draft Section 6.1). DNSSEC recommended for the _sovp zone.

Automatic DNS resolution is not yet implemented. Keys must be supplied directly to verify_identity(). See Roadmap.


Live validation example

To validate a live production domain (requires DNS + network access):

python examples/validate_live.py

This runs the full pipeline against litzki-systems.com: DNS TXT resolution, HTTP fetch of /.well-known/sovp-identity.json, and Ed25519 verification.

Expected output:

SOVP Live Validation — litzki-systems.com
Domain:          litzki-systems.com
Psi_core:        1
Public key ref:  dns:txt:_sovp.litzki-systems.com
Entity UID:      urn:sovp:litzki-systems.com
Canonical URL:   https://litzki-systems.com
Result: VERIFIED — identity and integrity confirmed.

Roadmap

Feature Status
sovp.core primitives (generate_keypair, sign_identity, verify_identity) Implemented
sovp.core document builder (generate_identity_document) Implemented
CLI (generate-keypair, sign, verify) Implemented
Replay protection — timestamp validation (check_timestamp=True) Implemented
contentAddress digest (SHA-256 over JCS bytes) Implemented
DNS + HTTP resolution in SOVPValidator Implemented — see sovp.resolver
RFC conformance test vectors Implemented — see tests/test_vectors.py
Live validation (validate_live.py) Implemented
AgenTrust Marketplace integration Implemented — see sovp-agentrust-bridge
Reference identity-endpoint deployment (Cloudflare Worker) Implemented — see workers/sovp-identity, live at litzki-systems.com
Replay protection — nonce deduplication Planned
SOVPIdentity / SOVPSigner / SOVPValidator class API Planned
IETF Internet-Draft draft-litzki-sovp — active
ARD trustManifest type registration In progress — ards-project/ard-spec #41
U.S. Provisional Patent Filed — No. 64/005,737

Contributing

See CONTRIBUTING.md.


License

Apache 2.0 — see LICENSE.

The SOVP protocol specification is intellectual property of Litzki Systems LLC. Patent pending.


Litzki Systems LLC · St. Petersburg, FL · info@litzki-systems.com

Download files

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

Source Distribution

sovp-1.0.5.tar.gz (20.9 kB view details)

Uploaded Source

Built Distribution

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

sovp-1.0.5-py3-none-any.whl (15.5 kB view details)

Uploaded Python 3

File details

Details for the file sovp-1.0.5.tar.gz.

File metadata

  • Download URL: sovp-1.0.5.tar.gz
  • Upload date:
  • Size: 20.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for sovp-1.0.5.tar.gz
Algorithm Hash digest
SHA256 bfb97f89d17ce09c019857ab4fce76c101ad3a4662bca73ee6739443b5068174
MD5 bf0adaddb70555a390b0fc2d2512e8a7
BLAKE2b-256 7c16e9db278fcd6e05d45ec9c733c8991b12afbecdbf653f9915357c31b7b68b

See more details on using hashes here.

File details

Details for the file sovp-1.0.5-py3-none-any.whl.

File metadata

  • Download URL: sovp-1.0.5-py3-none-any.whl
  • Upload date:
  • Size: 15.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for sovp-1.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 94a16d712ac716392ec7e35b26e0b91fd93da259b3f4170324e0ea727cc2f88e
MD5 c261bd178a3bcdf32868151b8405ef49
BLAKE2b-256 cb7e6f34ec2389d9980e17c501a36aba4fa1cedb3a179cd70f16deee57627531

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.5 This release

2 files

1.0.4

2 files

1.0.3

2 files

1.0.2

2 files

1.0.1

2 files

1.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page