Verify SignedShot media authenticity proofs. Available as a Rust CLI and Python library.
SignedShot is an open protocol for proving photos and videos haven't been altered since capture. This validator verifies the cryptographic proofs (sidecars) generated by the SignedShot iOS SDK.
pip install signedshotcargo install signedshot-validatorimport signedshot
# Validate from files
result = signedshot.validate_files("photo.sidecar.json", "photo.jpg")
print(result.valid) # True/False
print(result.version) # Sidecar format version
print(result.error) # Error message if validation failed
# Capture trust (JWT verification)
trust = result.capture_trust
print(trust["signature_valid"]) # JWT signature verified
print(trust["issuer"]) # API that issued the token
print(trust["publisher_id"]) # Publisher ID
print(trust["device_id"]) # Device ID
print(trust["capture_id"]) # Capture session ID
print(trust["method"]) # Attestation: "sandbox", "app_check", or "app_attest"
print(trust["app_id"]) # App bundle ID (if attested)
print(trust["issued_at"]) # Unix timestamp
# Media integrity (content verification)
integrity = result.media_integrity
print(integrity["content_hash_valid"]) # SHA-256 hash matches
print(integrity["signature_valid"]) # ECDSA signature verified
print(integrity["capture_id_match"]) # Capture IDs match
print(integrity["content_hash"]) # SHA-256 of media
print(integrity["captured_at"]) # ISO8601 timestamp# Validate from in-memory data
with open("photo.sidecar.json") as f:
sidecar_json = f.read()
with open("photo.jpg", "rb") as f:
media_bytes = f.read()
result = signedshot.validate(sidecar_json, media_bytes)# Avoid HTTP call by providing JWKS directly
import requests
jwks = requests.get("https://api.signedshot.io/.well-known/jwks.json").text
result = signedshot.validate_with_jwks(sidecar_json, media_bytes, jwks)# Get result as dictionary
data = result.to_dict()
# Get result as JSON string
json_str = result.to_json()# Basic validation
signedshot validate photo.sidecar.json photo.jpg
# Output as JSON
signedshot validate photo.sidecar.json photo.jpg --jsonsignedshot parse photo.sidecar.jsonValidating sidecar: photo.sidecar.json
Media file: photo.jpg
[OK] Sidecar parsed
[OK] JWT decoded
Issuer: https://api.signedshot.io
Publisher: 9a5b1062-a8fe-4871-bdc1-fe54e96cbf1c
Device: ea5c9bfe-6bbc-4ee2-b82d-0bcfcc185ef1
Capture: ac85dbd2-d8a8-4d0b-9e39-2feef5f7b19f
Method: app_check
App ID: io.signedshot.capture
[OK] JWT signature verified
[OK] Content hash matches
[OK] Media signature verified
[OK] Capture IDs match
✓ VALID - Media authenticity verified
- Fetches JWKS from issuer (or uses provided keys)
- Verifies ES256 (P-256 ECDSA) signature
- Extracts claims: publisher, device, capture ID, attestation method
- Computes SHA-256 hash of media file
- Compares with
content_hashin sidecar - Verifies ECDSA signature over integrity data
- Confirms
capture_idmatches JWT
- Ensures capture_id in JWT matches capture_id in media_integrity
- Validates all timestamps and formats
git clone https://github.com/SignedShot/signedshot-validator.git
cd signedshot-validator
cargo build --release
./target/release/signedshot --help# Install maturin
pip install maturin
# Build wheel
cd python
maturin build --release
# Install locally
pip install ../target/wheels/signedshot-*.whl# Format
cargo fmt
# Lint
cargo clippy -- -D warnings
# Test
cargo test
# Build
cargo build --release- signedshot-api - Backend API
- signedshot-ios - iOS SDK
MIT License - see LICENSE for details.