DEV Community

Asahina-Aoi
Asahina-Aoi

Posted on

CryptPix – Steganography (AES-256-GCM + HMAC-SHA-256 + Argon2id + Synch-HILL + STC + Viterbi)

Try it (WebApp): https://sh3lly.byethost11.com/cryptpix
Technical Report: https://github.com/AoiAsahina/CryptPix/blob/main/CryptPix.pdf
 

// THE TOOL

CryptPix encrypts your messages with AES-256-GCM + HMAC-SHA-256 (keys derived via memory-hard Argon2id), then embeds the ciphertext through Synch-HILL distortion costs coupled with Syndrome-Trellis Codes (STC) and Viterbi decoding across all three color channels. Payload size is hard-capped at 5% of cover capacity to resist statistical steganalysis. The result looks identical to the original.
 

// SUPPORTED CARRIERS

CryptPix accepts virtually any image format as the carrier.
✓ Joint Photographic Experts Group .jpeg
✓ Portable Network Graphics .png
✓ Graphics Interchange Format .gif
✓ WebP .webp
✓ AV1 Image File Format .avif
✓ JPEG XL .jxl
✓ Tagged Image File Format .tiff
✓ Bitmap .bmp
✓ Raw / Digital Negative .raw/.dng
✓ HEIC / HEIF .heic/heif

Internally, the encrypted payload is embedded into the pixel raster and re-encoded as lossless PNG, guaranteeing bit-perfect survival of your hidden data.

  • Browser-native decoding for all common formats
  • Lossless PNG output preserves every hidden bit
  • Synch-HILL + STC embedding across R, G, B channels (cost-ordered)

 
// THE PIPELINE

Encrypt: Your message is encrypted with AES-256-GCM. A unique 256-bit key is derived from your password using Argon2id (memory-hard, 64 MB, 3 iterations) and a fresh random salt — GPU/ASIC resistant.

Package: The encrypted payload is bundled as salt || IV || HMAC tag || length || ciphertext. No magic bytes or version tag are written. A known magic byte would give an adversary a free distinguisher. Tamper detection is provided by the 256-bit HMAC-SHA-256 tag (verified before AES-GCM decryption), with the inner 128-bit AES-GCM tag as a second layer.

Embed: Synch-HILL computes per-pixel distortion costs (Laplacian high-pass + 3×3 averaging). STC with Viterbi decoding then selects minimum-cost LSB flips across R/G/B in cost-ascending order. Payload is capped at 5% of cover capacity to resist chi-square, sample-pairs, weighted-stego, and SRM-class attacks.

Deliver: The encoded image is exported as lossless PNG to preserve every hidden bit. The output looks identical to the original, but carries your secret.
 

// SECURITY MODEL

Threat model: Synch-HILL + STC minimizes detectable distortion. 5% capacity cap, content-adaptive costs, and 3-channel cost-ordered embedding resist chi-square, sample-pairs, weighted-stego, and SRM-class attacks.

✓ Confidentiality (AES-256-GCM)
✓ Integrity (256-bit HMAC-SHA-256)
✓ Brute-force resistance (Argon2id, 64 MB)
✓ Per-file key uniqueness (16-byte salt)
✓ Steganalysis resistance (STC, 5% cap)

Cryptography that holds up: Every layer of CryptPix uses well-studied primitives from the Web Crypto API. No custom cryptography, no third-party libraries, no telemetry. Everything runs locally in your browser.

AES-256-GCM + HMAC-SHA-256: AES-GCM provides confidentiality with a 128-bit embedded tag. A separate 256-bit HMAC-SHA-256 over iv‖ciphertext raises overall authentication strength to 256 bits and detects any tampering.

Argon2id: Modern key derivation function (PHC winner) resistant to GPU and ASIC brute-force. Each derivation requires 64 MB of memory, making parallel cracking economically impractical.

Unique salt per file: Two encryptions with the same password produce completely different keys. Pre-computed rainbow tables are useless.

96-bit random IV: Every encryption uses a unique initialization vector. Repeating the same message+password never yields the same ciphertext.

Local processing: Your images, messages, and passwords never leave the browser. No server, no upload, no telemetry, everything runs in your tab.

No third-party crypto: All cryptographic operations use the browser’s native, audited Web Crypto implementation. No custom or JavaScript-based crypto libraries.

Synch-HILL + STC: HILL distortion costs (Laplacian high-pass + 3×3 averaging) drive a Syndrome-Trellis-Code with Viterbi decoder, operating on cost-ordered LSBs across R, G, and B. A synchronizing pseudo-random pattern is shared implicitly via cover dimensions. Payload is hard-capped at 5% of cover capacity to resist chi-square, sample-pairs, weighted-stego, and SRM-class statistical attacks.
 

// OPERATIONAL GUIDANCE

Stay invisible. Use it right: Even the best steganography fails if the cover is compromised in transit. Follow these operational rules to keep your payload truly hidden from steganalysis and forensic inspection.

Defense in depth: Argon2id + AES-256-GCM + HMAC-SHA-256 protect confidentiality; HILL+STC raises the statistical-detection floor. Neither defends against provenance comparison, JPEG-cover forensics, or an adversary who reads the source and trains a matched detector.

Never re-encode as JPEG: WhatsApp, Telegram, Discord, social media, and most email clients re-compress images as JPEG by default. This destroys every LSB and your payload is gone. Only transmit the PNG via lossless channels: Signal "as document", email attachments sent as files, direct file transfer, or upload to a file host.

Use natively-lossless covers: JPEG-sourced covers (including picsum.photos samples) carry residual DCT block signatures exploitable by JPEG-compatibility steganalysis (JRM, J-UNIWARD-aware detectors). Prefer PNG screenshots, camera RAW exported to PNG, vector drawings rasterized to PNG, or images you generated locally.

Never reuse a cover: If an adversary obtains the original cover (from your camera roll, social media history, or by guessing the picsum seed), a pixel-diff comparison reveals every modified LSB, defeating all steganographic protection regardless of algorithm. Each cover image must be used exactly once and never published in its original form.

Use strong, unique passwords: Argon2id raises brute-force cost to ~64 MB of memory per attempt, but a dictionary password is still crackable. Use 20+ character random passwords (the Generate button creates 32-char ones). Never reuse a password across multiple stego images, if one is broken, all are.

Use private browsing: Browser cache, swap, and indexedDB may retain plaintext or intermediate buffers after use. For sensitive work, use private/incognito mode and close the tab when done. Clear browser cache periodically if you use CryptPix regularly.

Keep payloads small: The 5% capacity cap is a hard upper bound, but smaller is always better. A 1 KB text message in a 1 MP image is far harder to detect than a 50 KB file at the cap. Prefer text over binary files when possible, and split large payloads across multiple cover images.
 

// ALTERNATIVE METHODOLOGY

If you prefer an approach other than steganography (which involves hiding the very existence of a message), the primary and most secure alternative is cryptography, which instead aims to make the message completely unintelligible to anyone other than the authorized recipient.

Try it (WebApp): https://sh3lly.byethost11.com/0x8
Technical Report: https://github.com/AoiAsahina/0x8/blob/main/0x8.pdf

Top comments (0)