FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

batmanpriv/ByteVeil: Steganography CLI tool written in Go. Hide secret files, folders, or messages inside cover files like images, audio, video, and documents. Supports 10+ formats including JPEG, PNG, MP4, and ZIP. Optional password protection with AES-256-GCM. · GitHub

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

ByteVeil

Hide data in plain sight.

A lightweight, file-based steganography CLI written in Go. Hide files, folders, or text inside ordinary files with optional AES-256-GCM encryption.


Overview

ByteVeil is a command-line tool for file-based steganography.

It allows you to hide:

  • Individual files
  • Entire directories
  • Text messages

inside a cover file.

Payloads are compressed with gzip before being stored. If a password is provided, ByteVeil additionally encrypts the compressed payload using AES-256-GCM with a key derived through PBKDF2-HMAC-SHA256.

ByteVeil detects the cover file format and uses a format-specific embedding strategy when supported. For unrecognized formats, it falls back to a generic append strategy.

The result is a single file that can later be decoded by ByteVeil to recover the original payload.

                  ENCODE

 File / Folder / Text
          │
          ▼
   ┌──────────────┐
   │    gzip      │
   │ compression  │
   └──────┬───────┘
          │
          ▼
   ┌──────────────┐
   │ Optional     │
   │ AES-256-GCM  │
   │ encryption   │
   └──────┬───────┘
          │
          ▼
   ┌──────────────┐
   │  ByteVeil    │
   │   payload    │
   └──────┬───────┘
          │
          ▼
     Cover File
          │
          ▼
      Stego File

Features

  • Hide files inside other files
  • Hide entire directories
  • Hide plain-text messages
  • Optional AES-256-GCM encryption
  • PBKDF2-HMAC-SHA256 password-based key derivation
  • 200,000 PBKDF2 iterations
  • Random cryptographic salt
  • Random AES-GCM nonce
  • gzip compression before encryption
  • CRC32 payload integrity checking
  • Original filename preservation
  • Automatic file/directory detection during extraction
  • Format-aware embedding for multiple common formats
  • Generic fallback for unsupported formats
  • Single Go binary
  • Uses only the Go standard library
  • Works on Windows, Linux, and macOS when built for the target platform

Supported Formats

ByteVeil recognizes the following file formats:

Format Detection Embedding Method
JPEG Yes Appended after JPEG data
PNG Yes Custom stEg chunk before IEND
MP4 / ISO-BMFF Yes Appended free box
MP3 Yes PRIV frame in ID3v2
GIF Yes Appended after file data
BMP Yes Appended after bitmap data
RIFF Yes Generic append
WAV Yes Generic append
AVI Yes Generic append
WEBP Yes Generic append
OGG Yes Generic append
PDF Yes Appended after %%EOF
ZIP Yes ZIP EOCD comment
DOCX Yes ZIP EOCD comment
XLSX Yes ZIP EOCD comment
PPTX Yes ZIP EOCD comment
JAR Yes ZIP EOCD comment
APK Yes ZIP EOCD comment
Other files Fallback Generic append

Format detection is performed using file signatures rather than filename extensions.

For example, a file named:

photo.dat

can still be recognized as PNG if its binary signature is a valid PNG signature.


Installation

Build from Source

Clone the repository:

git clone https://github.com/batmanpriv/ByteVeil.git

Enter the project directory:

cd ByteVeil

Build ByteVeil:

go build -o ByteVeil .

On Windows:

go build -o ByteVeil.exe .

You can then run the binary directly.

Linux/macOS:

./ByteVeil

Windows:

.\ByteVeil.exe

Install with Go

You can also install ByteVeil directly using go install:

go install github.com/batmanpriv/ByteVeil@v1.0.0

Make sure your Go binary directory is included in your system PATH.

Then run:

ByteVeil

Quick Start

Hide a File

Hide secret.pdf inside cover.png:

ByteVeil encode -in cover.png -out secret.png -data secret.pdf

Extract it:

ByteVeil decode -in secret.png -out extracted.pdf

Hide a Text Message

Hide a text message inside a JPEG:

ByteVeil encode -in cover.jpg -out message.jpg -text "Meet me at 9pm."

Extract it:

ByteVeil decode -in message.jpg

If no output path is specified, ByteVeil uses the filename stored inside the payload.

Text messages are stored with:

message.txt

as their default filename.


Hide an Encrypted File

Provide a password to enable encryption:

ByteVeil encode -in cover.png -out secret.png -data secret.pdf -password "your-strong-password"

Extract it using the same password:

ByteVeil decode -in secret.png -out secret.pdf -password "your-strong-password"

Without the correct password, the encrypted payload cannot be successfully decrypted.


Hide an Entire Directory

ByteVeil can hide an entire directory:

ByteVeil encode -in cover.png -out backup.png -data ./my-folder -password "your-strong-password"

The directory is packed into a TAR stream before compression and optional encryption.

Extract it:

ByteVeil decode -in backup.png -out ./restored-folder -password "your-strong-password"

ByteVeil automatically detects that the payload represents a directory and extracts it into the specified output directory.


Command Reference

ByteVeil provides two commands:

encode
decode

encode

Creates a new file containing a hidden ByteVeil payload.

Syntax

ByteVeil encode -in <cover> -out <output> (-data <file-or-folder> | -text <message>) [-password <password>]

Options

Flag Required Description
-in Yes Path to the cover file
-out Yes Path to the resulting stego file
-data Conditional File or directory to hide
-text Conditional Text message to hide
-password No Password used to enable AES-256-GCM encryption

Exactly one of -data or -text must be provided.

File Example

ByteVeil encode -in cover.png -out output.png -data secret.pdf

Text Example

ByteVeil encode -in cover.jpg -out output.jpg -text "This is a hidden message."

Encrypted Example

ByteVeil encode -in cover.png -out output.png -data secret.pdf -password "strong-password"

Directory Example

ByteVeil encode -in cover.png -out output.png -data ./my-folder -password "strong-password"

decode

Extracts a hidden ByteVeil payload.

Syntax

ByteVeil decode -in <stego-file> [-out <output>] [-password <password>]

Options

Flag Required Description
-in Yes Stego file containing the hidden payload
-out No Output file or directory
-password No Password for encrypted payloads

Basic Example

ByteVeil decode -in output.png

Specify Output

ByteVeil decode -in output.png -out restored.pdf

Encrypted Payload

ByteVeil decode -in output.png -out restored.pdf -password "strong-password"

Directory Payload

ByteVeil decode -in output.png -out ./restored -password "strong-password"

How It Works

ByteVeil uses a custom binary payload container.

The encoding pipeline is:

Original Payload
      │
      ├── File
      ├── Folder
      └── Text
      │
      ▼
 Directory → TAR
      │
      ▼
    gzip
      │
      ▼
 Optional AES-256-GCM
      │
      ▼
 ByteVeil Inner Payload
      │
      ▼
 ByteVeil Outer Blob
      │
      ▼
 Format-Specific Embedding
      │
      ▼
 Stego File

The decoding pipeline reverses these operations:

Stego File
    │
    ▼
Locate ByteVeil Blob
    │
    ▼
Validate Payload
    │
    ▼
Decrypt if Required
    │
    ▼
gzip Decompression
    │
    ▼
TAR Extraction if Directory
    │
    ▼
Original Payload

ByteVeil Payload Format

The outer ByteVeil blob begins with the following magic marker:

STEGOv1\x00

The outer structure is:

+-------------------+
| STEGOv1\x00       |
+-------------------+
| Payload Length    |
| 8 bytes, BE       |
+-------------------+
| Inner Payload     |
+-------------------+

The inner payload begins with:

STG1

The current payload version is:

1

The inner payload contains metadata describing the stored data.

Conceptually:

+-----------------------+
| STG1                  |
+-----------------------+
| Version               |
+-----------------------+
| Flags                 |
+-----------------------+
| Filename (optional)   |
+-----------------------+
| Salt (optional)       |
+-----------------------+
| Nonce (optional)      |
+-----------------------+
| Data Length           |
+-----------------------+
| Compressed/Encrypted |
| Payload               |
+-----------------------+
| CRC32                 |
+-----------------------+

The payload format is versioned so that future versions can introduce compatible format changes.


Compression

ByteVeil compresses payload data using gzip before storing it.

For normal files and text:

Original Data
     ↓
   gzip
     ↓
Compressed Data

For directories:

Directory
    ↓
   TAR
    ↓
TAR Stream
    ↓
  gzip
    ↓
Compressed TAR

Compression happens before encryption.

This is important because encrypted data generally does not compress effectively.


Encryption

Encryption is optional.

When -password is provided, ByteVeil derives a 256-bit encryption key using:

PBKDF2-HMAC-SHA256

with:

Iterations: 200,000
Key length: 32 bytes
Salt length: 16 bytes

The resulting key is used with:

AES-256-GCM

A fresh random salt and nonce are generated for every encoded payload.

The encryption flow is:

Password
   │
   ▼
PBKDF2-HMAC-SHA256
   │
   ├── 200,000 iterations
   ├── 16-byte random salt
   └── 32-byte derived key
   │
   ▼
AES-256-GCM
   │
   └── 12-byte random nonce

The salt and nonce are stored alongside the encrypted payload because they are not secrets.

The password itself is never stored in the ByteVeil payload.


Integrity Protection

ByteVeil stores a CRC32 checksum for the inner payload.

During decoding, the checksum is verified before the payload is processed.

This allows ByteVeil to detect accidental corruption or truncation.

For encrypted payloads, AES-GCM additionally provides authenticated encryption.

Therefore:

CRC32
  → detects payload corruption/truncation

AES-GCM authentication
  → detects invalid/tampered encrypted data

CRC32 is not a cryptographic security mechanism.


Directory Handling

When -data points to a directory, ByteVeil creates a TAR archive in memory.

The TAR archive can contain:

  • Regular files
  • Directories
  • Symbolic links

The original directory name is stored in the payload metadata.

For example:

my-project/
├── main.go
├── README.md
├── src/
│   └── app.go
└── assets/
    └── config.json

is packed into a TAR stream before compression.

When decoded, ByteVeil recognizes the directory flag and extracts the archive.


Format-Specific Embedding

JPEG

JPEG payloads are appended after the original JPEG data.

Conceptually:

[JPEG DATA][ByteVeil BLOB]

The JPEG content itself is not modified by the embedding operation.


PNG

PNG payloads are stored in a custom ancillary chunk:

stEg

The chunk is inserted before the PNG IEND chunk.

Conceptually:

PNG Signature
     │
     ├── IHDR
     ├── ...
     ├── stEg
     │     └── ByteVeil Blob
     └── IEND

The custom chunk also has its own CRC.


MP4 / ISO-BMFF

For MP4-family files, ByteVeil adds a free box containing the ByteVeil payload.

Conceptually:

[Existing MP4 Boxes][free][ByteVeil Blob]

MP3

For MP3 files with a compatible ID3v2 tag, ByteVeil stores the payload inside a PRIV frame.

The private owner identifier used by the implementation is:

stego-tool

If a suitable ID3v2 tag is not present, ByteVeil creates an ID3v2.3 tag containing the private frame.


GIF

GIF payloads are appended after the existing file data.


BMP

BMP payloads are appended after the existing bitmap data.


RIFF / WAV / AVI / WEBP

These formats are recognized as RIFF-family files.

The current implementation uses a generic append strategy for these formats.


OGG

OGG files are recognized and use the generic append strategy.


PDF

PDF payloads are appended after the existing %%EOF marker.

This means strict PDF readers or processors may not always accept a modified PDF containing an appended ByteVeil payload.


ZIP

ZIP-based files use the ZIP End of Central Directory comment field.

This applies to:

.zip
.docx
.xlsx
.pptx
.jar
.apk

and other ZIP-based formats.

The ZIP comment field has a maximum size of:

65,535 bytes

Therefore ZIP-based cover files have a hard payload-size limitation.


Generic Fallback

If ByteVeil does not recognize the cover file format, it falls back to generic append embedding.

Conceptually:

[Original File][ByteVeil Blob]

This allows ByteVeil to work with arbitrary binary files, but compatibility with third-party applications is not guaranteed.


File Transfer vs. Re-Encoding

ByteVeil operates at the file-byte level.

As a result, it can survive operations that preserve the original bytes, but it generally cannot survive operations that decode and re-encode the media.

Usually Safe

Examples of operations that normally preserve the payload:

  • Copying the file
  • Moving the file
  • Renaming the file
  • Storing it on a filesystem
  • Sending it as an unmodified file
  • Copying it through a normal file-transfer mechanism
  • Putting it into an archive without rewriting its contents

For example:

ByteVeil File
     │
     ▼
"Send as File"
     │
     ▼
Same Bytes
     │
     ▼
Payload Still Present

Usually Not Safe

Media transcoding or recompression can destroy the payload.

For example:

ByteVeil JPEG
     │
     ▼
Platform decodes JPEG
     │
     ▼
Platform recompresses JPEG
     │
     ▼
New JPEG
     │
     ▼
ByteVeil payload may be gone

The same applies to video and audio transcoding.

This is a fundamental limitation of file-level embedding.


Security Considerations

Steganography Is Not Encryption

Steganography and encryption provide different protections.

Steganography attempts to hide the presence or location of information.

Encryption protects the contents of the information.

Without a password:

Hidden + Compressed

With a password:

Hidden + Compressed + Encrypted

For sensitive payloads, use a strong password.


Use Strong Passwords

Avoid weak passwords such as:

password
123456
qwerty
hunter2

Prefer a long, unique passphrase.

For example:

correct-horse-battery-staple-7f3a91

Do not commit passwords to Git repositories.

Do not place passwords in shell scripts that may be committed to source control.


Password Recovery

ByteVeil does not provide password recovery.

If an encrypted payload is created with a lost password, there is no recovery mechanism built into the tool.


Steganalysis

ByteVeil does not claim to provide undetectable steganography.

It uses file-level embedding rather than modifying pixel values or audio samples, but the presence of a ByteVeil payload may still be detectable by someone inspecting the file structure or searching for the ByteVeil magic marker.

The goal is practical data hiding, not provable invisibility.


Limitations

Media Re-Encoding

ByteVeil does not guarantee survival through:

  • JPEG recompression
  • PNG rewriting
  • Video transcoding
  • Audio re-encoding
  • Image optimization
  • File conversion
  • Any operation that creates a new representation of the original media

ZIP Payload Limit

ZIP-based covers are limited by the maximum ZIP comment size:

65,535 bytes

This includes:

  • ZIP
  • DOCX
  • XLSX
  • PPTX
  • JAR
  • APK

For larger payloads, use another supported cover format.


Memory Usage

The current implementation reads and constructs payload data in memory.

For very large files or directories, memory usage can therefore become significant.

The current implementation is not a streaming steganography pipeline.


Generic Embedding

Unknown formats use generic append embedding.

Although this makes ByteVeil flexible, applications that strictly validate file length or reject trailing data may refuse to open such files.


External Application Compatibility

ByteVeil guarantees that its own decoder can recover a valid payload from an appropriately preserved ByteVeil file.

It does not guarantee that every third-party application will accept every modified cover file.


Error Handling

ByteVeil validates its payload before extraction.

Typical errors include:

No payload

no hidden payload marker found in this file

This means ByteVeil could not find the STEGOv1 marker.

Corrupted payload

checksum mismatch: payload is corrupted or truncated

The CRC32 check failed.

Missing password

this payload is encrypted; a password is required

The payload is encrypted but no password was supplied.

Wrong password or corrupted ciphertext

decryption failed: wrong password or corrupted data

AES-GCM authentication failed.

Truncated payload

declared payload length exceeds file size (truncated file?)

The file is shorter than the length declared by the ByteVeil container.


Examples

File → PNG

ByteVeil encode -in photo.png -out hidden.png -data secret.pdf

Extract:

ByteVeil decode -in hidden.png -out secret.pdf

Encrypted File → PNG

ByteVeil encode -in photo.png -out hidden.png -data secret.pdf -password "strong-password"

Extract:

ByteVeil decode -in hidden.png -out secret.pdf -password "strong-password"

Text → JPEG

ByteVeil encode -in photo.jpg -out hidden.jpg -text "This message is hidden."

Extract:

ByteVeil decode -in hidden.jpg

Folder → PNG

ByteVeil encode -in cover.png -out backup.png -data ./project -password "strong-password"

Extract:

ByteVeil decode -in backup.png -out ./restored-project -password "strong-password"

MP3

ByteVeil encode -in music.mp3 -out hidden.mp3 -data secret.txt -password "strong-password"

Extract:

ByteVeil decode -in hidden.mp3 -out secret.txt -password "strong-password"

ZIP

Because ZIP comments have a hard size limit, keep the payload small:

ByteVeil encode -in archive.zip -out hidden.zip -text "Hidden ZIP message"

Extract:

ByteVeil decode -in hidden.zip

Usage Summary

Encode a file:
ByteVeil encode -in <cover> -out <output> -data <file>

Encode a folder:
ByteVeil encode -in <cover> -out <output> -data <folder>

Encode text:
ByteVeil encode -in <cover> -out <output> -text "<message>"

Encrypt:
ByteVeil encode -in <cover> -out <output> -data <file> -password "<password>"

Decode:
ByteVeil decode -in <stego-file>

Decode to a specific file:
ByteVeil decode -in <stego-file> -out <output>

Decode encrypted payload:
ByteVeil decode -in <stego-file> -out <output> -password "<password>"

Build and Development

Clone the repository:

git clone https://github.com/batmanpriv/ByteVeil.git

Enter the directory:

cd ByteVeil

Build:

go build .

Run:

go run . encode -in cover.png -out output.png -text "Hello from ByteVeil"

Build a named binary:

Linux/macOS:

go build -o ByteVeil .

Windows:

go build -o ByteVeil.exe .

Project Structure

The current implementation is intentionally compact.

ByteVeil/
└── main.go

The main source file contains the following logical components:

Payload
├── buildInner
├── parseInner
├── wrapBlob
└── findBlob

Cryptography
└── pbkdf2

Format Detection
└── sniffFormat

Embedding
├── embedJPEG
├── embedPNG
├── embedMP4
├── embedMP3
├── embedGeneric
└── embedZIP

Directory Handling
├── tarDir
└── untarToDir

CLI
├── encode
├── decode
├── usage
└── main

Dependencies

ByteVeil currently uses the Go standard library only.

Important packages include:

archive/tar
bytes
compress/gzip
crypto/aes
crypto/cipher
crypto/hmac
crypto/rand
crypto/sha256
encoding/binary
errors
flag
fmt
hash/crc32
io
os
path/filepath
strings

No external runtime dependency is required.


Version

Current release:

v1.0.0

Payload format:

STEGOv1
STG1
version 1

Versioning is included in the payload format to allow future versions of ByteVeil to evolve the container format.

About

Steganography CLI tool written in Go. Hide secret files, folders, or messages inside cover files like images, audio, video, and documents. Supports 10+ formats including JPEG, PNG, MP4, and ZIP. Optional password protection with AES-256-GCM.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages


Back | FazBrowse Home | New Git URL