Zero-Knowledge Document Verification SDK for Python
Project description
ETH.id Python SDK
Zero-Knowledge Document Verification SDK for Python.
Installation
pip install ethid
Quick Start
from ethid import EthIdClient, LLMProvider
# Initialize client
client = EthIdClient(
provider=LLMProvider.OPENAI,
api_key="sk-your-key"
)
# Verify a document
result = client.verify(
document_path="passport.pdf",
claim="over 18 years old"
)
print(f"Answer: {result.answer}")
print(f"Confidence: {result.confidence}%")
print(f"Reasoning: {result.reasoning}")
Features
- Zero-Knowledge Verification: Documents never leave your machine
- Privacy-First: Only minimal, claim-relevant data is processed
- Multiple LLM Providers: OpenAI, Claude, Ollama
- Cryptographic Attestations: Tamper-evident proof bundles
- Audit Trail: Complete verification history
- Type-Safe: Full type hints and dataclasses
Usage
Basic Verification
from ethid import EthIdClient
client = EthIdClient()
# Age verification
result = client.verify(
document_path="id.pdf",
claim="maior de 18 anos"
)
if result.answer:
print("Person is over 18")
With Attestation
# Generate cryptographic proof
result = client.verify(
document_path="id.pdf",
claim="over 21 years old",
attest=True
)
# Get attestation bundle
bundle = client.get_attestation(result.session_id)
# Verify integrity
if bundle.verify_integrity():
print("Attestation is valid")
Offline Mode
# Complete privacy with local LLM
client = EthIdClient(
provider=LLMProvider.OLLAMA,
offline=True
)
result = client.verify(
document_path="document.pdf",
claim="document is signed"
)
Audit Log
# List all verifications
entries = client.list_audit_log(limit=10)
for entry in entries:
print(f"{entry.timestamp}: {entry.claim} -> {entry.answer}")
# Get specific entry
entry = client.get_audit_entry(session_id="...")
Privacy Guarantees
What is NEVER Sent
For age verification:
- ❌ Birth date
- ❌ Full name
- ❌ Address
- ✅ Only: "Age calculation result: true"
For CPF verification:
- ❌ Full CPF (123.456.789-00)
- ✅ Only: Masked (123..-00)
API Reference
EthIdClient
class EthIdClient:
def __init__(
self,
cli_path: Optional[str] = None,
provider: Optional[LLMProvider] = None,
api_key: Optional[str] = None,
offline: bool = False,
debug: bool = False,
)
Methods
verify()
def verify(
self,
document_path: str,
claim: str,
provider: Optional[LLMProvider] = None,
attest: bool = False,
zk_only: bool = False,
) -> VerificationResult
get_attestation()
def get_attestation(
self,
session_id: str,
) -> AttestationBundle
list_audit_log()
def list_audit_log(
self,
limit: Optional[int] = None,
filter_claim: Optional[str] = None,
) -> List[AuditEntry]
configure()
def configure(
self,
provider: Optional[LLMProvider] = None,
api_key: Optional[str] = None,
)
Types
VerificationResult
@dataclass
class VerificationResult:
session_id: str
answer: bool
confidence: float
reasoning: str
proof_type: ProofType
claim: str
privacy_metadata: PrivacyMetadata
timestamp: datetime
AttestationBundle
@dataclass
class AttestationBundle:
session_id: str
document_hash: str
claim: str
result: VerificationResult
proof_type: ProofType
bundle_hash: str
created_at: datetime
def verify_integrity(self) -> bool
Examples
Age Verification
result = client.verify(
document_path="passport.pdf",
claim="over 18 years old"
)
print(f"Over 18: {result.answer}")
CPF Verification
result = client.verify(
document_path="brazilian_id.pdf",
claim="CPF bate com 123.456.789-00"
)
# Only masked CPF is sent: 123.***.***-00
Income Verification
result = client.verify(
document_path="income_proof.pdf",
claim="renda acima de 5000"
)
# Only amount field is sent, no name/CPF
Multiple Providers
# OpenAI
client_openai = EthIdClient(provider=LLMProvider.OPENAI)
# Claude
client_claude = EthIdClient(provider=LLMProvider.CLAUDE)
# Ollama (offline)
client_ollama = EthIdClient(
provider=LLMProvider.OLLAMA,
offline=True
)
Error Handling
from ethid import (
DocumentParsingError,
ClaimParsingError,
VerificationError,
)
try:
result = client.verify(
document_path="document.pdf",
claim="over 18 years old"
)
except DocumentParsingError as e:
print(f"Failed to parse document: {e}")
except ClaimParsingError as e:
print(f"Failed to parse claim: {e}")
except VerificationError as e:
print(f"Verification failed: {e}")
Requirements
- Python 3.8+
- ETH.id CLI installed (
cargo install --path .)
Development
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Format code
black ethid/
# Type check
mypy ethid/
License
MIT
Links
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
ethid-0.1.0.tar.gz
(10.1 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
ethid-0.1.0-py3-none-any.whl
(8.4 kB
view details)
File details
Details for the file ethid-0.1.0.tar.gz.
File metadata
- Download URL: ethid-0.1.0.tar.gz
- Upload date:
- Size: 10.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
530206fb7777b2dbcc907ea15794235b576fc217dec04130abe4abf7add8570e
|
|
| MD5 |
96441d4001d08f88200e12f52aeed3a0
|
|
| BLAKE2b-256 |
d230254d6fcec27bca07886112ba78facc90582e9c35ce47b593d1f536d0f41d
|
File details
Details for the file ethid-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ethid-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a4117339a92a3912d73db90a90b77a19c50a70a76b764ded67812f49a4ad04a5
|
|
| MD5 |
75bb5eab5c5de525c7f678e6e4057155
|
|
| BLAKE2b-256 |
9155af6442712e76ba85d32acf2e534c80959680bafdf4af1528dc9c455b0a22
|