Documentation
¶
Overview ¶
Package f5core provides core F5 steganography primitives shared across f5messageextract, f5messageembed, and f5imagerecover packages.
Index ¶
Constants ¶
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 ¶
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.
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 ¶
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 ¶
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 ¶
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.