Merge stegasoo (v4.3.0, steganography) and verisoo (v0.1.0, attestation) as subpackages under soosef.stegasoo and soosef.verisoo. This eliminates cross-repo coordination and enables atomic changes across the full stack. - Copy stegasoo (34 modules) and verisoo (15 modules) into src/soosef/ - Convert all verisoo absolute imports to relative imports - Rewire ~50 import sites across soosef code (cli, web, keystore, tests) - Replace stegasoo/verisoo pip deps with inlined code + pip extras (stego-dct, stego-audio, attest, web, api, cli, fieldkit, all, dev) - Add _availability.py for runtime feature detection - Add unified FastAPI mount point at soosef.api - Copy and adapt tests from both repos (155 pass, 1 skip) - Drop standalone CLI/web frontends; keep FastAPI as optional modules - Both source repos tagged pre-monorepo-consolidation on GitHub Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
92 lines
2.5 KiB
Python
92 lines
2.5 KiB
Python
"""
|
|
Embedding backend protocol definition.
|
|
|
|
All embedding backends (LSB, DCT, audio, video, etc.) implement this protocol,
|
|
enabling registry-based dispatch instead of if/elif chains.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Protocol, runtime_checkable
|
|
|
|
|
|
@runtime_checkable
|
|
class EmbeddingBackend(Protocol):
|
|
"""Protocol that all embedding backends must satisfy.
|
|
|
|
Each backend handles a specific embedding mode (e.g. 'lsb', 'dct',
|
|
'audio_lsb', 'audio_spread') for a specific carrier type ('image',
|
|
'audio', 'video').
|
|
"""
|
|
|
|
@property
|
|
def mode(self) -> str:
|
|
"""The embedding mode identifier (e.g. 'lsb', 'dct')."""
|
|
...
|
|
|
|
@property
|
|
def carrier_type(self) -> str:
|
|
"""The carrier media type: 'image', 'audio', or 'video'."""
|
|
...
|
|
|
|
def is_available(self) -> bool:
|
|
"""Whether this backend's dependencies are installed."""
|
|
...
|
|
|
|
def embed(
|
|
self,
|
|
data: bytes,
|
|
carrier: bytes,
|
|
key: bytes,
|
|
*,
|
|
progress_file: str | None = None,
|
|
**options: Any,
|
|
) -> tuple[bytes, Any]:
|
|
"""Embed data into a carrier.
|
|
|
|
Args:
|
|
data: Encrypted payload bytes.
|
|
carrier: Raw carrier file bytes (image, audio, etc.).
|
|
key: Derived key for pixel/sample selection.
|
|
progress_file: Optional progress file path.
|
|
**options: Backend-specific options (bits_per_channel,
|
|
output_format, color_mode, chip_tier, etc.).
|
|
|
|
Returns:
|
|
Tuple of (stego carrier bytes, embed stats).
|
|
"""
|
|
...
|
|
|
|
def extract(
|
|
self,
|
|
carrier: bytes,
|
|
key: bytes,
|
|
*,
|
|
progress_file: str | None = None,
|
|
**options: Any,
|
|
) -> bytes | None:
|
|
"""Extract data from a carrier.
|
|
|
|
Args:
|
|
carrier: Stego carrier file bytes.
|
|
key: Derived key for pixel/sample selection.
|
|
progress_file: Optional progress file path.
|
|
**options: Backend-specific options.
|
|
|
|
Returns:
|
|
Extracted payload bytes, or None if no payload found.
|
|
"""
|
|
...
|
|
|
|
def calculate_capacity(self, carrier: bytes, **options: Any) -> int:
|
|
"""Calculate maximum embeddable payload size in bytes.
|
|
|
|
Args:
|
|
carrier: Raw carrier file bytes.
|
|
**options: Backend-specific options (e.g. bits_per_channel).
|
|
|
|
Returns:
|
|
Maximum payload capacity in bytes.
|
|
"""
|
|
...
|