Skip to main content

Creduent Protocol SDK - open standard for cryptographic AI agent identity, Ed25519 signing, DNS verification, and attestation registry

Project description

Creduent Python SDK

PyPI version License Python Compatibility Downloads

The official Python SDK for the Creduent Protocol — a federated, open trust-verification layer and cryptographic identity infrastructure for autonomous AI agents.

Creduent enables autonomous agents to cryptographically sign metadata, verify identities across administrative domains via DNS bindings, and interact with the Creduent registry for secure, machine-to-machine trust checks.


Key Features

  • 🔑 Cryptographic Identity Management: Generate secure Ed25519 keypairs for AI agents.
  • ✍️ RFC 8785 Canonical Signatures: Compute cryptographic signatures over JSON agent documents using JCS and Ed25519.
  • 🛡️ SSRF Protection: Safe endpoint resolution blocking private/loopback network ranges.
  • 🔗 DNS Trust Binding: Verify cryptographic bindings between agent:// identifiers and web domains.
  • 🏛️ Registry Integration: Register agents and resolve signed attestations from the Creduent Registry.
  • 🛠️ CLI Utilities: Out-of-the-box CLI commands for signing, verification, and key generation.
  • ⚙️ Serverless-Safe Env Loader: Avoids .env interference in Vercel and other serverless environments.

Installation

pip install creduent

Architectural Flow

+------------------+             +----------------------+             +------------------+
|   Agent Domain   |             |   Creduent Registry  |             |   Agent Client   |
|   (agent.json)   |             | registry.idevsec.com |             |    (MCP Host)    |
+------------------+             +----------------------+             +------------------+
         |                                |                                |
         |---- 1. Serve agent.json ------>|                                |
         |                                |-- 2. Verify identity & DNS --->|
         |                                |      and sign attestation      |
         |<--- 3. Query agent endpoint ------------------------------------|
         |                                |                                |
         |                                |<--- 4. Fetch attestation ------|

Registering Your Agent

Registration is open — no admin key required. Any developer can register an agent. After registration, your agent gets level: "unverified". Contact the registry admin for verified or trusted upgrade.

The backend runs 6 verification steps — all must pass:

Step 1 → Fetch agent.json from your agent_json_url
Step 2 → Validate schema (7 required fields)
Step 3 → Confirm agent_id matches in both form and file
Step 4 → Verify Ed25519 self-signature
Step 5 → Check DNS TXT record: _creduent.yourdomain.com
Step 6 → Health check your agent endpoint (must be live HTTPS)

Step 1 — Generate Ed25519 Keypair

from creduent import generate_keys

private_key_pem, public_key_str = generate_keys()

with open("private_key.pem", "w") as f:
    f.write(private_key_pem)

print(public_key_str)  # ed25519:ABC123...  ← goes in agent.json

Or via CLI:

creduent-sign generate-keys
# Saves: private_key.pem  (KEEP SECRET)
# Prints: ed25519:...     (public key)

Step 2 — Create agent.json

Create a draft with these required fields:

{
  "version": "1.0",
  "agent_id": "agent://yourorg/youragent",
  "owner": "Your Name or Organization",
  "public_key": "ed25519:ABC123...",
  "endpoint": "https://yourdomain.com/agent",
  "capabilities": ["task_execution", "file_read"]
}
Field Requirement
version Must be exactly "1.0"
agent_id Format: agent://<namespace>/<name> — lowercase, alphanumeric, hyphens
owner Any string
public_key Must start with ed25519:
endpoint Live public HTTPS URL (no localhost, no private IPs)
capabilities Array of strings
signature Added in next step — do not add manually

Step 3 — Sign agent.json

from creduent import sign
import json

with open("draft_agent.json") as f:
    draft = json.load(f)

with open("private_key.pem") as f:
    private_key_pem = f.read()

signed_doc = sign(draft, private_key_pem)

with open("agent.json", "w") as f:
    json.dump(signed_doc, f, indent=2)

Or via CLI:

creduent-sign sign \
  --key private_key.pem \
  --input draft_agent.json \
  --output agent.json

Important: Re-sign every time you modify agent.json. Any change to the document invalidates the signature.


Step 4 — Host agent.json

Serve the signed file at a public HTTPS URL. Recommended path:

https://yourdomain.com/.well-known/agent.json

Requirements:

  • HTTP 200 response
  • Content-Type: application/json
  • No auth, no VPN, no private IPs — must be publicly reachable

Cloudflare Users — Required Configuration

If your domain is proxied through Cloudflare (orange cloud), you must add a WAF rule before registering. Without this, Cloudflare will block the Creduent registry server from fetching your agent.json and health-checking your endpoint, returning HTTP 403.

Rule 1 — Allow Registry Fetch and Endpoint Health Check

Cloudflare Dashboard → Security → Security Rules → Custom Rules → Create Rule

Name: Allow Creduent Manifest and Endpoint Field: URI Path Operator: is in Value:

  • /.well-known/agent.json
  • /<your-agent-endpoint-path> (e.g. /agent or /api/agent) Action: Skip Skip: All remaining custom rules + All rate limiting rules + All managed rules Place at: First

DNS TXT Record (Cloudflare)

When adding the _creduent TXT record in Cloudflare DNS:

  • Make sure the orange cloud (proxy) is OFF for the TXT record
  • TXT records do not need to be proxied
  • TTL: Auto

Common Cloudflare Errors

Error Cause Fix
Failed to fetch agent.json: HTTP 403 Cloudflare WAF blocking registry server Add the WAF rule above
Failed to fetch agent.json: HTTP 403 (after adding rules) Bot Fight Mode JS challenge Disable JS Detections under Security → Bots
Registration succeeds but resolver shows 403 CSP blocking registry.idevsec.com Add registry.idevsec.com to connect-src in your site's CSP headers

Step 5 — Add DNS TXT Record

Proves domain ownership. Add this to your domain's DNS:

Type Name Value
TXT _creduent agent://yourorg/youragent

Full record name: _creduent.yourdomain.com

Verify propagation (~5 min):

# Windows
nslookup -type=TXT _creduent.yourdomain.com

# Linux / Mac
dig TXT _creduent.yourdomain.com
# Expected: "agent://yourorg/youragent"

Step 6 — Register

from creduent import register

result = register(
    agent_id="agent://yourorg/youragent",
    domain="yourdomain.com",
    agent_json_url="https://yourdomain.com/.well-known/agent.json"
)

if result.success:
    print(f"Registered! Level: {result.attestation['level']}")
    # → Registered! Level: unverified
else:
    print(f"Failed: {result.error}")

Or via curl:

curl -X POST https://registry.idevsec.com/registry/register \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agent://yourorg/youragent",
    "domain": "yourdomain.com",
    "agent_json_url": "https://yourdomain.com/.well-known/agent.json"
  }'

Success response:

{
  "agent_id": "agent://yourorg/youragent",
  "issuer": "agent://creduent/registry",
  "level": "unverified",
  "issued_at": "2026-05-31T00:00:00Z",
  "expires_at": "2027-05-31T00:00:00Z",
  "public_key": "ed25519:...",
  "domain": "yourdomain.com",
  "signature": "...",
  "status": "registered"
}

Common Registration Errors

Error Cause Fix
Failed to fetch agent.json: HTTP 404 File not at URL Check URL is public and returns 200
Missing required field 'signature' Draft not signed Run creduent-sign sign first
agent_id in agent.json does not match Mismatch in form vs file Use exact same string in both
Cryptographic signature is INVALID File modified after signing Re-sign with creduent-sign sign
DNS TXT record not found (NXDOMAIN) TXT record missing Add _creduent TXT to your DNS
does not contain agent_id Wrong TXT value Value must be exactly agent://yourorg/youragent
Endpoint healthcheck failed Endpoint unreachable Is your server live? Public HTTPS?
429 Too many requests 5/hour rate limit Wait 1 hour and retry

Registration Checklist

[ ] Ed25519 keypair generated (private_key.pem + public key)
[ ] draft_agent.json created with all required fields
[ ] agent.json signed (signature field present)
[ ] agent.json hosted at a public HTTPS URL
[ ] DNS TXT record added: _creduent.yourdomain.com = agent://yourorg/youragent
[ ] DNS propagated (verified with nslookup or dig)
[ ] register() called → status: "registered" received

Quickstart (Full Example)

from creduent import generate_keys, sign, verify, register, attest, CreduentError

try:
    # 1. Generate keypair
    private_key_pem, public_key_str = generate_keys()

    # 2. Sign a draft agent.json
    draft = {
        "version": "1.0",
        "agent_id": "agent://creduent/reconbot",
        "owner": "IDevSec",
        "public_key": public_key_str,
        "endpoint": "https://registry.idevsec.com/recon",
        "capabilities": ["osint", "dns_lookup"]
    }
    signed_doc = sign(draft, private_key_pem)

    # 3. Verify self-signed document
    result = verify(signed_doc)
    print(f"Self-verify: {result.valid}")

    # 4. Register with registry (requires DNS + hosted agent.json)
    reg = register(
        agent_id="agent://creduent/reconbot",
        domain="registry.idevsec.com",
        agent_json_url="https://registry.idevsec.com/.well-known/agent.json"
    )
    print(f"Registered: {reg.success}, Level: {reg.attestation['level']}")

    # 5. Query attestation
    att = attest("agent://creduent/reconbot")
    print(f"Attested: {att.attested}, Level: {att.level}")

except CreduentError as e:
    print(f"Error: {e}")

Challenge-Response Authentication

Allows agents to prove their cryptographically registered identity to other agents.

# Agent proving its identity to another agent
from creduent import challenge

# Agent side — prove identity
proof = challenge.create_proof(
    agent_id="agent://cyberhavox/havox-ai",
    private_key_pem=open("private_key.pem").read()
)
# proof = {"verified": True, "level": "trusted", "proof_token": "...", "valid_until": "..."}

# Receiver side — verify the proof
is_valid = challenge.verify_proof(
    proof_token=proof["proof_token"],
    agent_id="agent://cyberhavox/havox-ai"
)
print(is_valid)  # True

Command Line Interface

creduent-sign

# Generate Ed25519 keypair
creduent-sign generate-keys

# Sign a draft agent.json
creduent-sign sign --key private_key.pem --input draft_agent.json --output agent.json

creduent-verify

# Verify a local file
creduent-verify agent.json

# Verify by URL
creduent-verify https://yourdomain.com/.well-known/agent.json

# Verify by domain
creduent-verify yourdomain.com

# Verify by agent:// URI
creduent-verify agent://creduent/reconbot

API Reference

generate_keys() → (private_key_pem: str, public_key_str: str)

Generates a new Ed25519 keypair. Returns PEM private key and ed25519:-prefixed public key.

sign(draft: dict, private_key_pem: str) → dict

Signs a draft agent.json using JCS canonicalization (RFC 8785) + Ed25519. Returns signed document with signature field.

verify(target: str | dict) → VerifyResult

Verifies a self-signed agent.json. Accepts dict, HTTPS URL, domain, local path, or agent:// URI.

  • result.valid — bool
  • result.agent_id, result.public_key, result.endpoint, result.capabilities
  • result.error — str or None

register(agent_id, domain, agent_json_url, registry_url?) → RegisterResult

Registers an agent with the Creduent registry.

  • result.success — bool
  • result.attestation — dict (level, issued_at, expires_at, ...)
  • result.error — str or None

attest(agent_id, registry_url?) → AttestResult

Fetches attestation status for an agent from the registry.

  • result.attested — bool
  • result.level"unverified" | "verified" | "trusted"
  • result.issued_at, result.expires_at
  • result.error — str or None

challenge.create_proof(agent_id, private_key_pem, registry_url?) → dict

Initiates a cryptographic challenge-response authentication flow to generate an identity verification proof.

  • Returns dict containing proof_token, verified status, level, valid_until timestamp, and issuer.

challenge.verify_proof(proof_token, agent_id, registry_url?) → bool

Decodes the proof token and verifies its authenticity using the registry's public key. Returns True if valid and not expired, False otherwise.


Advanced Utilities

SSRF Protection

from creduent.utils import safe_requests_get

response = safe_requests_get("https://example.com/.well-known/agent.json", timeout=5)

Blocks private IPs (RFC 1918), loopback, and link-local addresses before connecting.

Serverless Environment Loader

from creduent.utils import load_dotenv

load_dotenv()  # Skips loading in Vercel (VERCEL=1) to avoid clobbering prod env vars

Contributing

Bugs, feature requests, and pull requests welcome via GitHub Issues.


License

Dual Licensed under Apache License 2.0 (Open Source) and Commercial License — see LICENSE.

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

creduent-0.5.0.tar.gz (38.9 kB view details)

Uploaded Source

Built Distribution

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

creduent-0.5.0-py3-none-any.whl (34.3 kB view details)

Uploaded Python 3

File details

Details for the file creduent-0.5.0.tar.gz.

File metadata

  • Download URL: creduent-0.5.0.tar.gz
  • Upload date:
  • Size: 38.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.14

File hashes

Hashes for creduent-0.5.0.tar.gz
Algorithm Hash digest
SHA256 72097277ac042c6d0b6aa54b0176cd70e61555da811dd7df4f6da6e9e6b958c5
MD5 cd05e0ff6441b7f493f85e85b2ff506d
BLAKE2b-256 cf0ad9c901a007508d6d96e13473839b6b10c35b56ab671387b7951e42de53d7

See more details on using hashes here.

File details

Details for the file creduent-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: creduent-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 34.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.14

File hashes

Hashes for creduent-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b0760295f69e02d3841b7f637b24ca75b710bc36a77b9f8ed1b0e8f70a964e63
MD5 d750ad1832ec74f036ca3e12cc2724b9
BLAKE2b-256 d9c861885283db09e5686e72524a977318ea4182949b0f18a5b010de175f81f5

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