import subprocess
import json
import os
import sys
from pathlib import Path
from typing import Dict, Optional, List
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class ProofModeDocker:
def __init__(self, docker_image: str = "registry.gitlab.com/guardianproject/proofmode/proofmode-rust:latest"):
self.docker_image = docker_image
self.check_docker()
def check_docker(self):
try:
subprocess.run(["docker", "--version"], check=True, capture_output=True)
except (subprocess.CalledProcessError, FileNotFoundError):
raise RuntimeError("Docker is not installed or not accessible")
def generate_proof(self, input_file: Path, output_dir: Path,
config_file: Optional[Path] = None) -> Dict:
if not input_file.exists():
raise FileNotFoundError(f"Input file not found: {input_file}")
output_dir.mkdir(parents=True, exist_ok=True)
cmd = [
"docker", "run", "--rm",
"-v", f"{input_file.parent.absolute()}:/input:ro",
"-v", f"{output_dir.absolute()}:/output"
]
if config_file and config_file.exists():
cmd.extend(["-v", f"{config_file.absolute()}:/config.toml:ro"])
cmd.extend([
self.docker_image,
"generate", f"/input/{input_file.name}", "--output", "/output"
])
if config_file:
cmd.extend(["--config", "/config.toml"])
logger.info(f"Generating proof for {input_file.name}")
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
raise RuntimeError(f"Failed to generate proof: {result.stderr}")
proof_files = list(output_dir.glob("*.proof.json"))
if not proof_files:
raise RuntimeError("No proof file generated")
with open(proof_files[0], 'r') as f:
proof_data = json.load(f)
logger.info(f"Proof generated successfully: {proof_files[0].name}")
return proof_data
def verify_proof(self, proof_file: Path, media_file: Optional[Path] = None) -> bool:
if not proof_file.exists():
raise FileNotFoundError(f"Proof file not found: {proof_file}")
cmd = [
"docker", "run", "--rm",
"-v", f"{proof_file.parent.absolute()}:/proofs:ro"
]
if media_file and media_file.exists():
cmd.extend(["-v", f"{media_file.parent.absolute()}:/media:ro"])
cmd.extend([
self.docker_image,
"check", f"/proofs/{proof_file.name}"
])
logger.info(f"Verifying proof: {proof_file.name}")
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
logger.info("Proof verification passed")
return True
else:
logger.error(f"Proof verification failed: {result.stderr}")
return False
def batch_generate(self, input_dir: Path, output_dir: Path,
pattern: str = "*.jpg") -> List[Dict]:
media_files = list(input_dir.glob(pattern))
if not media_files:
logger.warning(f"No files matching pattern '{pattern}' found in {input_dir}")
return []
logger.info(f"Processing {len(media_files)} files")
proofs = []
for media_file in media_files:
try:
proof = self.generate_proof(media_file, output_dir)
proofs.append(proof)
except Exception as e:
logger.error(f"Failed to process {media_file.name}: {e}")
return proofs
def main():
proofmode = ProofModeDocker()
print("\n=== Example 1: Generate Single Proof ===")
script_dir = Path(__file__).parent
input_dir = script_dir / "input"
output_dir = script_dir / "output"
input_dir.mkdir(exist_ok=True)
output_dir.mkdir(exist_ok=True)
test_image = input_dir / "test.jpg"
if not test_image.exists():
import base64
jpeg_data = base64.b64decode(
"/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB"
"AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEB"
"AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAABAAED"
"AREAAHEBAAIRAGMBRAA/8QAFQABAQAAAAAAAAAAAAAAAAAAAAX/xAAUEAEAAAAAAAAAAAAAAAAAAAAA"
"/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAX/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEA"
"APQATJAA4KAA/9k="
)
test_image.write_bytes(jpeg_data)
print(f"Created test image: {test_image}")
try:
proof = proofmode.generate_proof(test_image, output_dir)
print(f"Generated proof with hash: {proof['file_hash_sha256']}")
except Exception as e:
print(f"Error: {e}")
return 1
print("\n=== Example 2: Verify Proof ===")
proof_file = output_dir / f"{proof['file_hash_sha256']}.proof.json"
if proof_file.exists():
if proofmode.verify_proof(proof_file, test_image):
print("Proof verification passed!")
else:
print("Proof verification failed!")
print("\n=== Example 3: Batch Processing ===")
for i in range(1, 4):
test_file = input_dir / f"test_{i}.jpg"
if not test_file.exists():
test_file.write_bytes(test_image.read_bytes())
proofs = proofmode.batch_generate(input_dir, output_dir)
print(f"Generated {len(proofs)} proofs")
print("\n=== Example 4: Custom Parameters ===")
cmd = [
"docker", "run", "--rm",
"-v", f"{input_dir.absolute()}:/input:ro",
"-v", f"{output_dir.absolute()}:/output",
proofmode.docker_image,
"generate", "/input/test.jpg", "--output", "/output",
"--email", "test@example.com",
"--passphrase", "secure-passphrase"
]
try:
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
print("Generated proof with custom parameters")
else:
print(f"Error: {result.stderr}")
except Exception as e:
print(f"Error: {e}")
print("\n=== All examples completed ===")
return 0
if __name__ == "__main__":
sys.exit(main())