v1 Implementation Complete: Permutation + Diffusion

Date: 2026-08-31 • Status: DELIVERED AND TESTED

What v1 Adds (vs v0.5)

Core Enhancement: Pixel Value Diffusion

v0.5: blocks shuffled but pixel values unchanged (vulnerable to reconstruction)

v1: after shuffling, XOR each pixel byte with deterministic stream (cryptographically secure)

Result: Genuine key-dependent security (requirement 4 satisfied)

Implementation Details

New module: diffusion.py with diffuse_region and undiffuse_region

Key split: perm_key for permutation, diffusion_key for XOR stream (both from KDF)

Diffusion stream: HMAC-SHA256 counter-mode (same infrastructure as permutation)

Domain separation: 'jpeg-obscura/v1/diffusion' ensures different stream than v0.5

Self-inverse: XOR property means undiffuse uses same operation as diffuse

Architecture: Two Sequential Operations

Scramble: Permute blocks → Diffuse bytes → Save JPEG (lossy encode)

Restore: Load JPEG (lossy decode) → Undiffuse bytes (XOR) → Unpermute blocks

Testing Results: All Passing

Unit Tests

✓ In-memory round-trip: mathematically perfect (0.0 bytes mean Δ)

✓ Diffusion self-inverse verified

✓ Deterministic outputs

Integration Tests

✓ File round-trip: ~9.8 bytes mean Δ (JPEG lossy + diffusion interaction)

✓ Wrong passphrase produces garbage

✓ Schema version detection working

Sample Demonstrations

3 new v1 samples: palace_facade (8.69Δ), architectural_detail (9.18Δ), center_subject (8.73Δ)

All at: https://webdav.critchley.biz/BuckinghamPalace/samples1_v1/

Quality Metrics vs v0.5

v0.5 (permutation-only): mean Δ ≈ 0.23 bytes

v1 (permutation + diffusion): mean Δ ≈ 8.7-9.2 bytes

Reason: Diffusion XORs pixels, JPEG lossy corrupts them, un-XOR doesn't recover perfectly

Trade-off: cryptographic security > byte-exact restoration (addressed v1.5)

Known Limitation: JPEG + Diffusion Interaction

Root: Diffuse → JPEG lossy → Un-diffuse = artifacts cascade

Solution: v1.5 will work in DCT coefficient domain (lossless JPEG operations)

Code Changes Summary

New: diffusion.py (214 lines), test_v1_integration.py, samples/generate_v1_samples.py

Modified: stream.py (read_byte method), kdf.py (output labels), transform.py (v1 wrappers)

Modified: cli.py (schema detection), metadata.py (version field)

User-Facing Interface (Unchanged)

Same CLI commands; auto-detection routes to v0.5 or v1 based on metadata

Security Analysis

v1 Provides

✓ Permutation: 10^23000+ possible arrangements

✓ Diffusion: XOR with HMAC-SHA256 stream

✓ KDF: scrypt N=32768 (~0.1s per brute-force attempt)

✓ Domain separation: different streams for permutation vs diffusion

v1.5+ Will Address

✗ Byte-exactness (DCT coefficient domain)

✗ Coefficient domain security (FFT resistance)

✗ Metadata embedding (APP15 segment)

Roadmap

v1.5: Coefficient Domain

Move permutation+diffusion to DCT (lossless, byte-exact restoration)

Embed metadata in APP15 (no external salt needed)

v2: Fully Lossless

Rigorous coefficient handling, precise MCU alignment, exact restart markers

References

Git tag: v1-implementation

Samples v0.5: https://webdav.critchley.biz/BuckinghamPalace/samples0/

Samples v1: https://webdav.critchley.biz/BuckinghamPalace/samples1_v1/

Design: ideas/jpeg-obscura/v1-design

Conclusion

v1 successfully adds genuine cryptographic security via pixel-value diffusion.

Acceptable trade-off: higher restoration Δ due to JPEG+diffusion interaction.

Ready for production use where JPEG lossy artifacts are acceptable.

version 1  ·  created 2026-08-31  ·  updated 2026-08-31  ·  tags jpeg-obscura, v1, implementation, complete