f5core

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 30, 2026 License: MIT Imports: 0 Imported by: 0

README

f5core

Core primitives and constants for the F5 steganography algorithm — matrix-encoding parameters, code-word lengths, and the shared types used across the F5 toolkit.

Install

go get github.com/0verkilll/f5core

Sponsor

If this project is useful to you, please consider supporting its development:

Sponsor @0verkilll on GitHub

License

MIT

Documentation

Overview

Package f5core provides core F5 steganography primitives shared across f5messageextract, f5messageembed, and f5imagerecover packages.

Index

Constants

View Source
const (
	// MaxMessageSize is the maximum message size in bytes that can be embedded.
	// This is limited by the 23-bit file size field in the F5 header (2^23 - 1).
	MaxMessageSize = (1 << 23) - 1 // 8,388,607 bytes

	// DefaultMaxFileSize is the default maximum allowed size for extracted data.
	// This prevents memory exhaustion attacks from malformed headers.
	// Default: 10MB (10,485,760 bytes)
	DefaultMaxFileSize = 10_485_760

	// CoefficientMin is the minimum valid JPEG quantized DCT coefficient value.
	CoefficientMin int16 = -2048

	// CoefficientMax is the maximum valid JPEG quantized DCT coefficient value.
	CoefficientMax int16 = 2047

	// HeaderSize is the number of bits in the F5 message header.
	// The header contains the k parameter (8 bits) and file size (23 bits).
	HeaderSize = 32

	// MaxKParameter is the maximum valid k parameter value for matrix encoding.
	// k=8 uses (1,255,8) codes: 255 coefficients to extract 8 bits.
	MaxKParameter = 8

	// MinKParameter is the minimum valid k parameter value for matrix encoding.
	// k=1 uses simple (1,1,1) codes: 1 coefficient per bit (no matrix encoding).
	MinKParameter = 1

	// BlockSize is the size of a JPEG DCT block (8x8 = 64 coefficients).
	BlockSize = 64

	// FileSizeMask extracts bits 0-22 for file size (23 bits = max ~8MB).
	FileSizeMask = 0x7FFFFF

	// KParameterShift is the bit position of the k parameter (bits 24-31).
	KParameterShift = 24

	// KParameterMask extracts the k parameter after shifting.
	KParameterMask = 0xFF

	// KModulus ensures k wraps within valid range (for Java compatibility).
	KModulus = 32
)

F5 Algorithm Constants define fixed values for the F5 steganography algorithm.

Variables

View Source
var CodeWordLengths = [MaxKParameter + 1]int{0, 1, 3, 7, 15, 31, 63, 127, 255}

CodeWordLengths maps the F5 matrix-encoding parameter k to the number of coefficients n in a single (1, n, k) codeword, where n = 2^k - 1.

The F5 (1, n, k) matrix code embeds k message bits into n coefficients by changing at most one coefficient. Index 0 is reserved (k=0 is not a valid parameter); the valid range is [MinKParameter, MaxKParameter].

k=1 ->   1 coefficient  per k=1 message bit   (no matrix encoding)
k=2 ->   3 coefficients per k=2 message bits
k=3 ->   7 coefficients per k=3 message bits
k=4 ->  15 coefficients per k=4 message bits
k=5 ->  31 coefficients per k=5 message bits
k=6 ->  63 coefficients per k=6 message bits
k=7 -> 127 coefficients per k=7 message bits
k=8 -> 255 coefficients per k=8 message bits

These values match Westfeld's original F5 specification (2001) and the reference Java implementation used by PixelKnot and F5.jar.

View Source
var DeZigZag = [64]int{
	0, 1, 5, 6, 14, 15, 27, 28,
	2, 4, 7, 13, 16, 26, 29, 42,
	3, 8, 12, 17, 25, 30, 41, 43,
	9, 11, 18, 24, 31, 40, 44, 53,
	10, 19, 23, 32, 39, 45, 52, 54,
	20, 22, 33, 38, 46, 51, 55, 60,
	21, 34, 37, 47, 50, 56, 59, 61,
	35, 36, 48, 49, 57, 58, 62, 63,
}

DeZigZag is the JPEG de-zigzag transformation table.

JPEG stores DCT coefficients in zigzag order to improve compression by grouping low-frequency coefficients (which tend to have larger values) at the beginning of the sequence. This table maps zigzag indices to natural 2D block positions (row-major order).

The F5 algorithm applies this transformation to access coefficients in their original block positions during extraction.

Transformation formula for coefficient access:

zigzag := shuffled - shuffled%64 + DeZigZag[shuffled%64]

Where 'shuffled' is the permuted index and zigzag is the actual coefficient index in the original array.

The table maps positions 0-63 within each 8x8 block:

Position 0  (DC) -> 0  (top-left corner, always skipped in F5)
Position 1       -> 1  (horizontal neighbor)
Position 2       -> 5  (diagonal)
...etc

These values are copied exactly from the Java F5 reference implementation to ensure bit-perfect compatibility with PixelKnot and F5.jar.

Functions

func ApplyDeZigZag

func ApplyDeZigZag(shuffled int) int

ApplyDeZigZag converts a shuffled coefficient index to its de-zigzagged position.

The F5 algorithm applies permutation (Fisher-Yates shuffle) first to determine which coefficient to process, then applies de-zigzag transformation to locate the actual coefficient in the DCT coefficient array.

The transformation preserves the 8x8 block structure:

  • shuffled / 64 determines which block
  • shuffled % 64 determines position within the block
  • DeZigZag[shuffled % 64] gives the de-zigzagged position within the block

Parameters:

shuffled - The permuted coefficient index from Fisher-Yates shuffle.
           Must be non-negative; negative values will panic to surface
           caller bugs before they silently corrupt memory (Go's `%`
           operator preserves sign, which would yield a negative
           positionInBlock and an out-of-bounds DeZigZag lookup).

Returns:

The de-zigzagged index suitable for accessing the coefficient array

Panics:

If shuffled is negative. The package has no error-return convention,
and negative indices always indicate a programmer error rather than
malformed user input.

Example:

// Shuffled index 66 is in block 1 (64-127), position 2 within block
// DeZigZag[2] = 5, so de-zigzagged index is 64 + 5 = 69
zigzag := ApplyDeZigZag(66) // returns 69

func CodeWordLength

func CodeWordLength(k int) int

CodeWordLength returns the number of coefficients in a single (1, n, k) F5 codeword for the given k parameter, i.e. n = 2^k - 1.

Parameters:

  • k: matrix-encoding parameter in [MinKParameter, MaxKParameter]

Returns:

  • The codeword length n = 2^k - 1 for valid k

Panics:

If k is outside [MinKParameter, MaxKParameter]. The package has no
error-return convention, and an invalid k always indicates a caller
bug (header validation should reject invalid k before reaching this
function).

Example:

CodeWordLength(1) // returns 1
CodeWordLength(3) // returns 7
CodeWordLength(8) // returns 255

func RequiredCapacityBits

func RequiredCapacityBits(messageBits, k int) int

RequiredCapacityBits returns the number of DCT coefficients required to embed messageBits bits under the F5 (1, n, k) matrix code.

With matrix encoding each codeword carries k message bits and consumes n = 2^k - 1 coefficients. The caller must provide enough usable coefficients (non-DC, non-zero after permutation) to cover this capacity; shrinkage during embedding may require additional coefficients in practice, so callers doing sizing estimates should include a margin.

Formula:

codewords      = ceil(messageBits / k)
requiredCoeffs = codewords * (2^k - 1)

Parameters:

  • messageBits: total number of message bits to embed (must be >= 0)
  • k: matrix-encoding parameter in [MinKParameter, MaxKParameter]

Returns:

  • The number of coefficients required. Returns 0 when messageBits == 0.

Panics:

If k is outside [MinKParameter, MaxKParameter] or messageBits is
negative. Both indicate caller bugs.

Example:

// k=1: 24 message bits -> 24 codewords of length 1 -> 24 coefficients.
RequiredCapacityBits(24, 1) // returns 24

// k=3: 21 message bits -> 7 codewords of length 7 -> 49 coefficients.
RequiredCapacityBits(21, 3) // returns 49

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL