Integration Guide¶
How to integrate Diogenes into your applications and workflows.
Overview¶
Diogenes can be integrated in several ways:
- REST API -- Direct HTTP calls to the Diogenes server.
- Python SDK -- Import Diogenes core modules directly.
- Browser signing -- Use the Web Crypto API for client-side signing in web applications.
Python SDK Integration¶
Diogenes core modules can be imported directly into Python applications.
Key Generation¶
from diogenes.core.keys import generate_key_pair, compute_fingerprint
from diogenes.core.schemas import KeyAlgorithm
# Generate an Ed25519 key pair
private_key, public_key = generate_key_pair(KeyAlgorithm.ED25519)
# Compute the fingerprint
fingerprint = compute_fingerprint(public_key)
print(f"Fingerprint: {fingerprint}")
Signing a Document¶
from diogenes.core.signing import create_attestation, verify_attestation_signature
from diogenes.core.schemas import Manifest, Document, Attestation, AttestationType
# Create a manifest
manifest = Manifest(
document=Document(
title="My Document",
content_hash="sha256:abc123...",
),
attestations=[],
)
# Create and sign an attestation
attestation = create_attestation(
manifest=manifest,
attestation_type=AttestationType.AUTHORSHIP,
private_key=private_key,
fingerprint=fingerprint,
)
# Verify the signature
is_valid = verify_attestation_signature(attestation, public_key)
assert is_valid
Verification¶
from diogenes.core.verification import VerificationService
service = VerificationService(transparency_log)
result = service.verify(manifest, source_hash)
print(f"Layer 1 (crypto): {result.layer1.status}")
print(f"Layer 2 (key status): {result.layer2.status}")
print(f"Overall: {result.overall_status}")
Transparency Log¶
from diogenes.core.transparency_log import TransparencyLogService
log = TransparencyLogService()
# Append an entry
entry = log.append_entry(
event_type="key_registration",
payload={
"fingerprint": fingerprint,
"pseudonym": "Alice",
"public_key": public_key_pem,
"key_algorithm": "ed25519",
},
)
# Verify chain integrity
is_valid = log.verify_chain()
REST API Integration¶
For applications that communicate with a Diogenes server over HTTP.
Authentication Flow¶
import httpx
base_url = "http://localhost:8000/api/v1"
# Step 1: Request a login challenge
challenge = httpx.post(f"{base_url}/auth/challenge", json={
"fingerprint": "sha256:...",
"purpose": "login",
}).json()
# Step 2: Sign the challenge nonce with your private key
nonce = challenge["nonce"]
signature = sign_with_private_key(nonce.encode())
# Step 3: Login and receive JWT
token_response = httpx.post(f"{base_url}/auth/login", json={
"challenge_id": challenge["challenge_id"],
"challenge_signature": base64_encode(signature),
}).json()
jwt = token_response["token"]
# Step 4: Use the JWT for authenticated requests
headers = {"Authorization": f"Bearer {jwt}"}
Webhook Integration¶
Register a webhook to receive notifications about events:
httpx.post(f"{base_url}/webhooks", json={
"url": "https://your-app.example.com/hooks/diogenes",
"events": ["key_registration", "attestation"],
})
Browser-Based Signing¶
Diogenes supports signing directly in the browser using the Web Crypto API. The private key is generated and used entirely within the browser; it is never transmitted to the server.
Key Generation in JavaScript¶
// Generate an ECDSA P-256 key pair
const keyPair = await crypto.subtle.generateKey(
{ name: "ECDSA", namedCurve: "P-256" },
true, // extractable (for public key export)
["sign", "verify"]
);
// Export the public key in SPKI/PEM format
const publicKeyBuffer = await crypto.subtle.exportKey("spki", keyPair.publicKey);
const publicKeyPem = toPem(publicKeyBuffer, "PUBLIC KEY");
Signing in the Browser¶
// Compute the signing payload
const manifest = { document: { title: "...", content_hash: "..." }, attestations: [] };
const payload = JSON.stringify(manifest, Object.keys(manifest).sort());
// Sign with the private key
const encoder = new TextEncoder();
const signatureBuffer = await crypto.subtle.sign(
{ name: "ECDSA", hash: "SHA-256" },
keyPair.privateKey,
encoder.encode(payload)
);
const signature = btoa(String.fromCharCode(...new Uint8Array(signatureBuffer)));
// Submit to the server
const response = await fetch("/api/v1/attestations", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
manifest: manifest,
public_key_pem: publicKeyPem,
signature: signature,
attestation_type: "authorship",
}),
});
Security Considerations¶
When integrating Diogenes, keep these principles in mind:
- Private keys stay local. Never transmit private keys to the server. All signing happens on the client.
- Hash, do not upload. Document content is never sent to the server. Only the SHA-256 hash is transmitted for verification.
- Verify server-side. Always verify attestation signatures server-side after receiving them, even though they were created client-side.
- Protect passwords. If a key has a password registered, it must be provided with each attestation. Transmit passwords only over TLS.
- Rotate keys. Use key succession to rotate keys periodically. Do not reuse keys indefinitely.
Error Handling¶
All API endpoints return standard HTTP status codes:
| Code | Meaning |
|---|---|
200 |
Success |
201 |
Created |
400 |
Bad request (invalid input) |
401 |
Authentication required |
403 |
Forbidden (invalid credentials, insufficient permissions) |
404 |
Resource not found |
409 |
Conflict (e.g., challenge already used) |
410 |
Gone (e.g., challenge expired) |
422 |
Validation error (invalid manifest, signature, etc.) |
503 |
Service unavailable (e.g., log unreachable) |
Error responses include a detail field with a human-readable message: