SchemaPin Python Implementation
A Python implementation of the SchemaPin protocol for cryptographic schema integrity verification of AI tools.
Overview
SchemaPin provides cryptographic verification of AI tool schemas using ECDSA P-256 signatures and Trust-On-First-Use (TOFU) key pinning. This Python implementation serves as the reference implementation for the protocol.
Features
- ECDSA P-256 Cryptography: Industry-standard elliptic curve signatures
- Schema Canonicalization: Deterministic JSON serialization for consistent hashing
- Public Key Discovery: Automatic retrieval from
.well-known/schemapin.jsonendpoints - Key Pinning: Trust-On-First-Use security model with SQLite storage
- High-Level Workflows: Simple APIs for both developers and clients
- Comprehensive Testing: Full test suite with security validation
Installation
From PyPI (Recommended)
# Install latest stable version
pip install schemapin
# Install with development dependencies
pip install schemapin[dev]
# Install with testing dependencies only
pip install schemapin[test]
From Source (Development)
# Clone repository and install in development mode
git clone https://github.com/thirdkey/schemapin.git
cd schemapin/python
pip install -e .[dev]
After installation, the following CLI tools will be available:
schemapin-keygen- Generate cryptographic key pairsschemapin-sign- Sign JSON schemasschemapin-verify- Verify signed schemas
CLI Tools
SchemaPin provides three command-line tools for common operations:
Key Generation (schemapin-keygen)
Generate ECDSA or RSA key pairs with optional .well-known template:
# Generate ECDSA key pair with .well-known template
schemapin-keygen --type ecdsa --developer "Your Company" --well-known
# Generate RSA 4096-bit key pair
schemapin-keygen --type rsa --key-size 4096 --output-dir ./keys
# Generate keys in DER format
schemapin-keygen --type ecdsa --format der --prefix mykeys
Schema Signing (schemapin-sign)
Sign JSON schema files with private keys:
# Sign a single schema
schemapin-sign --key private.pem --schema schema.json --output signed.json
# Sign with metadata
schemapin-sign --key private.pem --schema schema.json --developer "Your Company" --version "1.0"
# Batch sign multiple schemas
schemapin-sign --key private.pem --batch ./schemas/ --output-dir ./signed/
# Sign from stdin
echo '{"type": "object"}' | schemapin-sign --key private.pem --stdin
Schema Verification (schemapin-verify)
Verify signed schemas with public keys or discovery:
# Verify with public key
schemapin-verify --schema signed.json --public-key public.pem
# Verify with domain discovery and interactive pinning
schemapin-verify --schema signed.json --domain example.com --tool-id my-tool --interactive
# Batch verify with auto-pinning
schemapin-verify --batch ./signed/ --domain example.com --auto-pin
# Verify from stdin with JSON output
echo '{"schema": {...}, "signature": "..."}' | schemapin-verify --stdin --public-key public.pem --json
CLI Examples
Run the CLI examples script to see detailed usage patterns:
cd python/examples
python cli_usage_examples.py
Quick Start
Tool Developer Workflow
from schemapin.utils import SchemaSigningWorkflow, create_well_known_response
from schemapin.crypto import KeyManager
# 1. Generate key pair
private_key, public_key = KeyManager.generate_keypair()
private_key_pem = KeyManager.export_private_key_pem(private_key)
public_key_pem = KeyManager.export_public_key_pem(public_key)
# 2. Sign your tool schema
schema = {
"name": "calculate_sum",
"description": "Calculates the sum of two numbers",
"parameters": {
"type": "object",
"properties": {
"a": {"type": "number", "description": "First number"},
"b": {"type": "number", "description": "Second number"}
},
"required": ["a", "b"]
}
}
signing_workflow = SchemaSigningWorkflow(private_key_pem)
signature = signing_workflow.sign_schema(schema)
# 3. Create .well-known response
well_known_response = create_well_known_response(
public_key_pem,
"Your Organization",
"contact@yourorg.com"
)
# Host well_known_response at https://yourdomain.com/.well-known/schemapin.json
Client Verification Workflow
from schemapin.utils import SchemaVerificationWorkflow
verification_workflow = SchemaVerificationWorkflow()
# Verify schema with automatic key pinning
result = verification_workflow.verify_schema(
schema,
signature,
"yourdomain.com/calculate_sum",
"yourdomain.com",
auto_pin=True
)
if result['valid']:
print("✅ Schema signature is valid")
if result['first_use']:
print("🔑 Key pinned for future use")
else:
print("❌ Schema signature is invalid")
print("Error:", result['error'])
API Reference
Core Classes
SchemaPinCore
canonicalize_schema(schema)- Convert schema to canonical string formathash_canonical(canonical)- SHA-256 hash of canonical stringcanonicalize_and_hash(schema)- Combined canonicalization and hashing
KeyManager
generate_keypair()- Generate new ECDSA P-256 key pairexport_private_key_pem(private_key)- Export private key to PEM formatexport_public_key_pem(public_key)- Export public key to PEM formatload_private_key_pem(pem_data)- Load private key from PEMload_public_key_pem(pem_data)- Load public key from PEM
SignatureManager
sign_hash(hash_bytes, private_key)- Sign hash with private keyverify_signature(hash_bytes, signature, public_key)- Verify signaturesign_schema_hash(schema_hash, private_key)- Sign schema hashverify_schema_signature(schema_hash, signature, public_key)- Verify schema signature
PublicKeyDiscovery
fetch_well_known(domain)- Fetch .well-known/schemapin.jsonget_public_key_pem(domain)- Get public key from domainget_developer_info(domain)- Get developer information
KeyPinning
pin_key(tool_id, public_key_pem, domain, developer_name)- Pin public keyget_pinned_key(tool_id)- Get pinned key for toolis_key_pinned(tool_id)- Check if key is pinnedlist_pinned_keys()- List all pinned keysremove_pinned_key(tool_id)- Remove pinned key
High-Level Workflows
SchemaSigningWorkflow
workflow = SchemaSigningWorkflow(private_key_pem)
signature = workflow.sign_schema(schema)
SchemaVerificationWorkflow
workflow = SchemaVerificationWorkflow()
result = workflow.verify_schema(schema, signature, tool_id, domain, auto_pin)
Examples
Run the included examples:
# Tool developer workflow
cd python/examples
python tool_developer.py
# Client verification workflow
python client_verification.py
Testing
cd python
python -m pytest tests/ -v
# Run code quality checks
ruff check .
bandit -r . --exclude tests/
Requirements
- Python 3.8 or higher
- cryptography library for ECDSA operations
- requests library for HTTP operations
- sqlite3 (built-in) for key storage
Security Considerations
- Private Key Security: Store private keys securely and never expose them
- HTTPS Required: Always use HTTPS for .well-known endpoint discovery
- Key Pinning: Review pinned keys periodically and verify authenticity
- Signature Verification: Always verify signatures before using tool schemas
Cross-Language Compatibility
This Python implementation is designed to be fully compatible with the JavaScript implementation:
- Identical schema canonicalization results
- Compatible ECDSA P-256 signatures
- Same .well-known endpoint format
- Interoperable key formats (PEM)
License
MIT License - see LICENSE file for details.
Contributing
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
Support
For issues and questions:
- GitHub Issues: SchemaPin Repository
- Documentation: See TECHNICAL_SPECIFICATION.md
- Examples: Check the
examples/directory
Metadata
Release files for schemapin 1.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| schemapin-1.3.0.tar.gz | 58.0 kB | Without provenance | Details for schemapin-1.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| schemapin-1.3.0-py3-none-any.whl | Python 3 | none | any | Details for schemapin-1.3.0-py3-none-any.whl |
Total release size: 94.5 kB
Release files / schemapin-1.3.0.tar.gz
| Download URL | schemapin-1.3.0.tar.gz |
|---|---|
| Size | 58.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fbce160bce53ea9931f007accae80877aeca89a27ffb36ae64c0979e65c93b38
|
|
BLAKE2b-256 checksum How to use checksums |
65d10af258d660e064f199b0bfc850d283c86ec12888b79a4fbb1e290e570a95
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|
Release files / schemapin-1.3.0-py3-none-any.whl
| Download URL | schemapin-1.3.0-py3-none-any.whl |
|---|---|
| Size | 36.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1221757683a9dac688a0cb0107717b7fbb035873bd8c5878bc1449745a04aae6
|
|
BLAKE2b-256 checksum How to use checksums |
1125f7c17171cc12293072f133ba9cc6245956621abc6a960c353f3a01ac212c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|
Security for schemapin 1.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.