Metadata-Version: 2.4
Name: secure-stegano
Version: 1.1.5
Summary: Bibliothèque Python unifiée de stéganographie d'images et de stéganalyse, du LSB au deep learning.
Author: TPI Steganograph-IA
License: MIT
Project-URL: Homepage, https://github.com/Master-2-MIAGE-MBDS/tpi-steganograph-ia
Project-URL: Repository, https://github.com/Master-2-MIAGE-MBDS/tpi-steganograph-ia
Project-URL: Issues, https://github.com/Master-2-MIAGE-MBDS/tpi-steganograph-ia/issues
Keywords: steganography,watermarking,image-processing,lsb,pvd,s-uniward,nsf5,j-uniward,uerd,qim,spread-spectrum,hidden,reed-solomon,deep-learning
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Graphics
Classifier: Topic :: Security :: Cryptography
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.26
Requires-Dist: Pillow>=10.0
Requires-Dist: scipy>=1.11
Requires-Dist: torch>=2.1
Requires-Dist: huggingface_hub>=0.20
Requires-Dist: transformers>=4.40
Requires-Dist: reedsolo>=1.7
Provides-Extra: dev
Requires-Dist: pytest>=7.4; extra == "dev"
Requires-Dist: hypothesis>=6.90; extra == "dev"
Requires-Dist: ruff>=0.1; extra == "dev"
Requires-Dist: mypy>=1.7; extra == "dev"
Provides-Extra: notebooks
Requires-Dist: jupyterlab>=4.0; extra == "notebooks"
Requires-Dist: matplotlib>=3.8; extra == "notebooks"
Requires-Dist: seaborn>=0.13; extra == "notebooks"

# secure-stegano

Bibliothèque Python de **stéganographie**, de **watermarking** et de **détection
d'images IA**, organisée par familles d'algorithmes, du LSB historique au deep
learning.

> Moteur algorithmique du projet TPI. Voir l'[état de l'art](../documentation/etat_de_l_art.md)
> pour le cadrage théorique (familles §4/§5, formats → famille §3.4) et le
> [cahier des charges](../documentation/cahier_de_charge.md) pour le périmètre.

## Vue d'ensemble

Trois familles stéganographiques + une famille watermarking + une partie IA. Tous
les codecs partagent la **même interface** : `encode(cover, payload, *, key=...)`
et `decode(stego, *, key=...)`, avec un **message borné à 8 octets**.

| Famille (dossier)      | Formats visés              | Algorithmes               | Robustesse        |
| ---------------------- | -------------------------- | ------------------------- | ----------------- |
| `codecs/spatial`       | lossless : PNG, BMP, TIFF  | **LSB, PVD, S-UNIWARD**   | Reed-Solomon      |
| `codecs/frequency`     | lossy/JPEG : JPEG, WebP    | **nsF5, J-UNIWARD, UERD** | Reed-Solomon      |
| `codecs/watermarking`  | robustesse / 100 %         | **QIM, Spread-Spectrum**  | intrinsèque (sans RS) |
| `codecs/ia`            | toutes (réseau appris)     | **HiDDeN** + `identify()` | Reed-Solomon      |

### Robustesse : Reed-Solomon (≤ 8 octets)

Les familles stéganographiques (spatial, fréquentiel, IA) protègent le message par
un code correcteur **Reed-Solomon** avant insertion (voir `common/payload.py`). Le
plafond de **8 octets** maximise la redondance par octet utile et rend les métriques
comparables entre familles. Le conteneur — `algo_id | length | data(8) + parité` —
porte l'`algo_id` *dans* le bloc protégé, ce qui permet le **décodage aveugle** des
codecs spatiaux LSB (l'algorithme est relu après correction RS).

> **Pourquoi pas de RS pour le watermarking ?** QIM et Spread-Spectrum portent leur
> robustesse nativement (marge de quantification, gain d'étalement) et visent une
> **récupération à 100 %** sur canal propre. Y ajouter RS serait redondant.

## Installation

Prérequis : **Python 3.11+**.

```bash
cd algorithms/secure-stegano
pip install -e ".[dev]"            # + ".[dev,notebooks]" pour les notebooks
```

## Utilisation — CLI (`--famille --algo`)

```bash
python -m secure_stegano --help

# Cacher / extraire (spatial, frequency, watermarking)
python -m secure_stegano encode --famille spatial --algo pvd \
    --cover cover.png --payload "hi" --out stego.png
python -m secure_stegano decode --famille spatial --algo pvd --stego stego.png

# decode sans --algo : décodage aveugle (spatial LSB, algo lu dans l'en-tête RS)
python -m secure_stegano decode --stego stego.png

# Codecs JPEG : --quality doit être identique à l'encode et au decode
python -m secure_stegano encode --famille frequency --algo j-uniward \
    --cover photo.png --payload "secret" --out stego.png --quality 80
python -m secure_stegano decode --famille frequency --algo j-uniward \
    --stego stego.png --quality 80

# Watermarking : récupération 100 %
python -m secure_stegano encode --famille watermarking --algo qim \
    --cover cover.png --payload "owner123" --out wm.png
python -m secure_stegano decode --famille watermarking --algo qim --stego wm.png

# Détecteur d'image IA (booléen : "ai" / "real")
python -m secure_stegano identify --input photo.png
```

## Utilisation — façade Python

```python
from secure_stegano import embed, extract, api
from secure_stegano.common import load_image, save_image

res = embed(load_image("cover.png"), b"hi", "pvd")   # ≤ 8 octets
save_image(res.stego, "stego.png")
print(res.algorithm, res.metrics)                    # psnr, ssim, capacity_bpp

assert extract(load_image("stego.png"), algorithm="pvd") == b"hi"
assert extract(load_image("stego.png")) == b"hi"     # décodage aveugle (spatial LSB)

api.list_algorithms()          # algos groupés par famille
api.algorithms_in_family("frequency")   # ['nsf5', 'j-uniward', 'uerd']

# Détecteur d'image IA
from secure_stegano.codecs.ia.detector import identify
identify(load_image("photo.png"))        # True si générée par IA
```

## Partie IA

- **HiDDeN** (`codecs/ia/hidden.py`) — stéganographie apprise robuste à la
  recompression. Poids TorchScript téléchargés depuis le Hugging Face Hub
  (`Cr2do/secure-stegano-hidden`) à la première utilisation. Message ≤ 7 octets
  (budget réseau 96 bits), protégé Reed-Solomon. Entraîné dans
  `notebooks/ai_strong_codec`.
- **Détecteur** (`codecs/ia/detector.py`) — `identify(image) -> bool` : Vision
  Transformer fine-tuné (`delpot/steganograph-ia-detector`, classes `real`/`ai`),
  entraîné dans `notebooks/ai_detection`. Renvoie `True` si l'image est jugée IA.

## Structure

```
src/                 (mappé sur le paquet « secure_stegano » par setuptools)
├── api.py           FAÇADE : embed / extract / familles
├── __main__.py      CLI (--famille --algo, identify)
├── common/          types, io, payload (conteneur Reed-Solomon + permutation)
├── codecs/
│   ├── spatial/     lsb, pvd, s_uniward
│   ├── frequency/   nsf5, j_uniward, uerd (+ _dct_cost : moteur commun)
│   ├── watermarking/ qim, spread_spectrum (+ _frame : cadre sans RS)
│   └── ia/          hidden (stégano apprise) + detector (identify)
└── metrics/         psnr, ssim, ber, capacity
```

Chaque codec suit le **même squelette** (constantes → helpers → classe `Codec` →
`INSTANCE` → wrappers module) pour qu'un algo lu = tous les autres lisibles.

### Notes d'implémentation (choix assumés)

- **Codes adaptatifs (S-UNIWARD, J-UNIWARD, UERD).** La fonction de coût ρ(x) est
  implémentée fidèlement, mais couplée à un **placement par coût** décodable plutôt
  qu'un STC complet : à 8 octets (~0,0005 bpp) le gain de codage d'un STC est
  négligeable. Côté JPEG, ρ ne dépend que de la fréquence (table de quantification)
  pour garantir la convergence déterministe de l'aller-retour DCT ; l'adaptativité
  de contenu vient des porteurs (coefficients AC non nuls = zones texturées).
- **Stabilisation JPEG.** nsF5 / J-UNIWARD / UERD insèrent dans le domaine DCT puis
  reconstruisent une image spatiale ; un aller-retour itératif garantit un
  round-trip exact. Pour de **rares** couples (cover, qualité) il n'atteint pas de
  point fixe et lève une erreur claire — changer de `--quality` résout le cas.

## Tests et qualité

```bash
ruff check src      # lint (barrière bloquante) — passe
```

> La suite `tests/` est en cours de réécriture (roundtrips, métriques par famille) ;
> elle sera réintroduite dans une passe dédiée.
