Metadata-Version: 2.4
Name: certisigma
Version: 1.2.2
Summary: Official Python SDK for the CertiSigma attestation & verification API
Author: CertiSigma
License: MIT
Project-URL: Homepage, https://developers.certisigma.ch/sdk
Project-URL: Documentation, https://developers.certisigma.ch/sdk
Project-URL: API Reference, https://developers.certisigma.ch
Project-URL: Repository, https://github.com/massimocavallin/CertiSigma
Project-URL: Changelog, https://developers.certisigma.ch/sdk#changelog
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security :: Cryptography
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.25.0
Provides-Extra: crypto
Requires-Dist: cryptography>=44.0.0; extra == "crypto"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: respx>=0.21; extra == "dev"
Requires-Dist: cryptography>=44.0.0; extra == "dev"

# CertiSigma Python SDK

Official Python client for the [CertiSigma](https://developers.certisigma.ch/sdk) cryptographic attestation [API](https://developers.certisigma.ch).

[![PyPI](https://img.shields.io/pypi/v/certisigma)](https://pypi.org/project/certisigma/)
[![npm](https://img.shields.io/npm/v/@certisigma/sdk)](https://www.npmjs.com/package/@certisigma/sdk)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)

## Installation

```bash
pip install certisigma
```

Or from source:

```bash
cd sdk/python
pip install -e .
```

## Quick Start

```python
from certisigma import CertiSigmaClient, hash_file, hash_bytes

client = CertiSigmaClient(api_key="cs_live_your_key_here")

# 1. Compute the SHA-256 hash of your file
file_hash = hash_file("contract.pdf")

# 2. Attest — creates a timestamped, signed proof of existence
result = client.attest(file_hash, source="my-app")
print(f"Attestation: {result.id} at {result.timestamp}")
print(f"ECDSA signature: {result.signature}")

# 3. Verify — confirm the hash was attested
check = client.verify(file_hash)
print(f"Exists: {check.exists}, Level: {check.level}")

# Or hash raw bytes
data_hash = hash_bytes(b"any raw content")
result = client.attest(data_hash)
```

## Hashing Utilities

Standalone SHA-256 hash functions -- compute hashes without attestation:

```python
from certisigma import hash_file, hash_bytes

# Hash a file (streamed, constant memory)
file_hash = hash_file("/path/to/document.pdf")
print(f"SHA-256: {file_hash}")

# Hash raw bytes
data_hash = hash_bytes(b"raw content")

# Verify a file against a known hash
assert hash_file("/path/to/document.pdf") == file_hash
```

Or hash + attest in one step:

```python
result = client.attest_file("/path/to/document.pdf")
print(f"Attested: {result.hash_hex}")
```

## Async Support

```python
import asyncio
from certisigma import AsyncCertiSigmaClient

async def main():
    async with AsyncCertiSigmaClient(api_key="cs_live_xxx") as client:
        result = await client.attest("abcdef..." * 4 + "0" * 16)
        print(result.id)

asyncio.run(main())
```

## Batch Operations

```python
# Attest up to 100 hashes in one call
batch = client.batch_attest(
    ["aabb..." * 4, "ccdd..." * 4],
    source="monthly-invoices"
)
print(f"Created: {batch.created}, Existing: {batch.existing}")

# Verify batch
results = client.batch_verify(["aabb..." * 4, "ccdd..." * 4])
print(f"Found: {results.found}/{results.count}")
```

## Metadata Management

```python
# Update claim metadata
result = client.update_metadata("att_1234", source="pipeline-v2", extra_data={"project": "alpha"})

# Soft-delete claim
client.delete_metadata("att_1234")

# Get evidence
evidence = client.get_evidence("att_1234")
print(evidence.level, evidence.t0)
```

## Client-Side Encryption (Zero Knowledge)

Requires: `pip install certisigma[crypto]`

```python
from certisigma.crypto import generate_key, encrypt_metadata, decrypt_metadata

# Generate a key (store securely — server never sees it)
key = generate_key()

# Encrypt before sending
encrypted = encrypt_metadata({"secret": "classified"}, key)
result = client.attest(hash_hex, extra_data=encrypted, client_encrypted=True)

# Decrypt after retrieving
plaintext = decrypt_metadata(result.extra_data, key)
```

## Error Handling

```python
from certisigma import (
    CertiSigmaError,
    AuthenticationError,
    RateLimitError,
    QuotaExceededError,
)

try:
    client.attest(hash_hex)
except AuthenticationError:
    print("Invalid API key")
except RateLimitError as e:
    print(f"Rate limited, retry after {e.retry_after}s")
except QuotaExceededError:
    print("Monthly quota reached")
except CertiSigmaError as e:
    print(f"API error {e.status_code}: {e}")
```

## Configuration

| Parameter | Default | Description |
|-----------|---------|-------------|
| `api_key` | (required) | Bearer token (`cs_live_...`) |
| `base_url` | `https://api.certisigma.ch` | API endpoint |
| `timeout` | `30.0` | Request timeout in seconds |

## Requirements

- Python 3.10+
- `httpx` >= 0.25.0
- `cryptography` >= 44.0.0 (optional, for `certisigma.crypto`)

## License

MIT — Ten Sigma Sagl, Lugano, Switzerland
