From 2ed108f3a022defcf196aa963641498275257227 Mon Sep 17 00:00:00 2001 From: "Aaron D. Lee" Date: Fri, 9 Jan 2026 23:14:10 -0500 Subject: [PATCH] Fix decode progress - add Argon2 phase tracking - decode.py now writes 20% "initializing" before Argon2 - decode.py writes 25% "extracting" after Argon2 completes - DCT extraction scales from 25-70% (was 5-70%) - Removed duplicate "loading" writes that caused backwards jumps Progress flow: 15% reading -> 20% initializing (Argon2) -> 25-70% extracting -> 75-95% decoding -> 100% complete Co-Authored-By: Claude Opus 4.5 --- src/stegasoo/dct_steganography.py | 11 ++++++----- src/stegasoo/decode.py | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/stegasoo/dct_steganography.py b/src/stegasoo/dct_steganography.py index fff417a..4ecdfbc 100644 --- a/src/stegasoo/dct_steganography.py +++ b/src/stegasoo/dct_steganography.py @@ -1198,7 +1198,7 @@ def _extract_scipy_dct_safe( progress_file: str | None = None, ) -> bytes: """Extract using safe DCT operations with vectorized processing.""" - _write_progress(progress_file, 0, 100, "loading") + # Progress starts at 25% (decode.py writes 20% for Argon2, 25% before extraction) img = Image.open(io.BytesIO(stego_image)) width, height = img.size @@ -1264,9 +1264,10 @@ def _extract_scipy_dct_safe( del blocks, dct_blocks, coeffs, quantized block_idx = batch_end - # Report progress (scale to 5-70% range, RS decode gets 70-100%) + # Report progress (scale to 25-70% range, RS decode gets 70-100%) + # Starts at 25% because decode.py writes 25% before calling extraction if progress_file and block_idx % PROGRESS_INTERVAL < BATCH_SIZE: - extract_pct = 5 + int(65 * block_idx / num_blocks) + extract_pct = 25 + int(45 * block_idx / num_blocks) _write_progress(progress_file, extract_pct, 100, "extracting") # Check if we have enough bits (early exit) @@ -1382,7 +1383,7 @@ def _extract_jpegio( """Extract using jpegio for JPEG images.""" import os - _write_progress(progress_file, 0, 100, "loading") + # Progress starts at 25% (decode.py writes 20% for Argon2, 25% before extraction) # Normalize JPEG to avoid crashes with quality=100 images # (shouldn't happen with stego images, but be defensive) @@ -1397,7 +1398,7 @@ def _extract_jpegio( all_positions = _jpegio_get_usable_positions(coef_array) order = _jpegio_generate_order(len(all_positions), seed) - _write_progress(progress_file, 20, 100, "extracting") + _write_progress(progress_file, 30, 100, "extracting") # Try RS-protected format first (has 24-byte length prefix: 3 copies for majority voting) if HAS_REEDSOLO and len(all_positions) >= RS_LENGTH_PREFIX_SIZE * 8: diff --git a/src/stegasoo/decode.py b/src/stegasoo/decode.py index c0c76f0..0664bc9 100644 --- a/src/stegasoo/decode.py +++ b/src/stegasoo/decode.py @@ -8,6 +8,7 @@ Changes in v4.0.0: - Improved error messages for channel key mismatches """ +import json from pathlib import Path from .constants import EMBED_MODE_AUTO @@ -24,6 +25,22 @@ from .validation import ( ) +def _write_progress(progress_file: str | None, current: int, total: int, phase: str) -> None: + """Write progress to file for UI polling.""" + if progress_file is None: + return + try: + with open(progress_file, "w") as f: + json.dump({ + "current": current, + "total": total, + "percent": (current / total * 100) if total > 0 else 0, + "phase": phase, + }, f) + except OSError: + pass + + def decode( stego_image: bytes, reference_photo: bytes, @@ -93,11 +110,17 @@ def decode( if rsa_key_data: require_valid_rsa_key(rsa_key_data, rsa_password) + # Progress: starting key derivation (Argon2 - slow on Pi) + _write_progress(progress_file, 20, 100, "initializing") + # Derive pixel/coefficient selection key (with channel key) from .crypto import derive_pixel_key pixel_key = derive_pixel_key(reference_photo, passphrase, pin, rsa_key_data, channel_key) + # Progress: key derivation done, starting extraction + _write_progress(progress_file, 25, 100, "extracting") + # Extract encrypted data encrypted = extract_from_image( stego_image,