encapsula
v2.0.0
Published
Terminal-based steganography tool with a Rust secure core for encrypted PNG payloads
Maintainers
Readme
Encapsula
Encapsula is a terminal-based steganography tool for hiding encrypted messages inside PNG images.
The current secure path uses a Rust core for the cryptography and embedding work. The TypeScript app is now only the terminal UI and process bridge.
Secure Core V2
The active encode/decode path is:
- User selects a PNG carrier in the TUI.
- User enters the secret message and password.
- TypeScript sends password and message to the Rust binary over stdin using length-prefixed frames.
- Rust derives keys with Argon2id.
- Rust encrypts with XChaCha20-Poly1305.
- Rust embeds encrypted metadata and ciphertext into PNG pixel data without visible text markers.
- Decode repeats the same password-derived extraction path and only returns plaintext when authentication succeeds.
Secrets are not passed through command-line arguments or environment variables.
Security Design
- Key derivation: Argon2id
- Authenticated encryption: XChaCha20-Poly1305
- Runtime boundary: Rust subprocess
- Carrier support in secure mode: PNG
- Payload markers: no
ECAP,ECAPTR, or<<ENCAPSULA_HIDDEN>>marker in Rust-generated PNGs - Wrong password behavior: decode fails before returning any message
This is much stronger than the old marker/trailer design, but it is not magic. A determined analyst can still inspect image statistics or reverse the binary. Treat it as a hardened CTF-style steganography tool, not as an impossible-to-detect system.
Requirements
- Node.js 20+
- npm
- Rust toolchain with Cargo, only for local development or building native binaries
Install
npm installRun with npx
After publishing, users can run the TUI without cloning the repo:
npx encapsulaThe npm package loads the Rust core from dist/native/<platform>-<arch>/ at runtime. Supported package folders are:
win32-x64/encapsula-core.exewin32-arm64/encapsula-core.exelinux-x64/encapsula-corelinux-arm64/encapsula-coredarwin-x64/encapsula-coredarwin-arm64/encapsula-core
Build
npm run buildBuild does three things:
- Compiles TypeScript into
dist/. - Builds
rust-corein release mode. - Copies the current platform Rust binary into
dist/native/<platform>-<arch>/anddist/.
To stage a native binary for the current platform into prebuilds/:
npm run build:nativeTo build all publish targets from this Windows machine, Docker Desktop must be running. Linux and macOS targets are built through the ghcr.io/rust-cross/cargo-zigbuild Docker image; Windows targets are built through the messense/cargo-xwin Docker image:
npm run build:native:allThis writes:
prebuilds/linux-x64/encapsula-core
prebuilds/linux-arm64/encapsula-core
prebuilds/darwin-x64/encapsula-core
prebuilds/darwin-arm64/encapsula-core
prebuilds/win32-x64/encapsula-core.exe
prebuilds/win32-arm64/encapsula-core.exeIf you explicitly want to use local Rust/MSVC for Windows targets instead of Docker:
node scripts/build_native.js --local win32-x64 win32-arm64Then assemble the npm package:
npm run build
npm run pack:check
npm publishRun
npm startFor development:
npm run devWhen running with ts-node, the bridge will use an existing Rust binary if present. If no binary exists, it falls back to cargo run --manifest-path rust-core/Cargo.toml.
Test
cargo test --manifest-path rust-core/Cargo.toml
npm testThe Node test performs a full encode/decode round trip against assets/demo.png, checks that a wrong password fails, and verifies the output does not contain the old visible marker strings.
Project Layout
src/
core/rustCore.ts TypeScript bridge to the Rust binary
sections/encode.ts Encode TUI flow
sections/decode.ts Decode TUI flow
rust-core/
src/main.rs Argon2id, XChaCha20-Poly1305, markerless PNG embedding
scripts/
copy_core.js Copies the Rust release binary into dist
test_encode_decode.js End-to-end secure-core testCurrent Limitations
- Secure mode is PNG-only.
- JPEG/WebP/PDF legacy container paths are not part of the active secure flow.
- Very small or flat PNGs may not have enough usable capacity.
- The next major upgrade would be a JPEG DCT-domain secure mode.
