Experiment: 003
Steganography Tool
ConceptLSB (Least Significant Bit) image steganography in Go. Embeds a length-prefixed payload into the red channel of PNG pixels.
Objective
Implement a covert channel by modifying the least significant bits of image pixel data, then verify extraction round-trips cleanly.
Constraints
Payload size limited to (width × height) / 8 bytes minus the 4-byte length header. Not robust against JPEG re-encoding or image resizing.
- Go
- Cryptography
- Image Processing
Source code · original languagesrc/main.go
1package main23import (4 "encoding/binary"5 "fmt"6 "image"7 "image/color"8 "image/png"9 "os"10)1112func embed(img *image.NRGBA, payload []byte) error {13 header := make([]byte, 4)14 binary.BigEndian.PutUint32(header, uint32(len(payload)))15 bits := append(header, payload...)1617 idx := 018 for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {19 for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {20 if idx >= len(bits)*8 {21 return nil22 }23 c := img.NRGBAAt(x, y)24 bytePos, bitPos := idx/8, uint(7-idx%8)25 bit := (bits[bytePos] >> bitPos) & 126 c.R = (c.R & 0xFE) | bit27 img.SetNRGBA(x, y, color.NRGBA{R: c.R, G: c.G, B: c.B, A: c.A})28 idx++29 }30 }31 if idx == len(bits)*8 {32 return nil // The payload filled the image exactly.33 }34 return fmt.Errorf("image too small for payload")35}3637func main() {38 f, _ := os.Open("cover.png")39 defer f.Close()40 src, _ := png.Decode(f)4142 dst := image.NewNRGBA(src.Bounds())43 for y := dst.Bounds().Min.Y; y < dst.Bounds().Max.Y; y++ {44 for x := dst.Bounds().Min.X; x < dst.Bounds().Max.X; x++ {45 dst.Set(x, y, src.At(x, y))46 }47 }4849 _ = embed(dst, []byte("HIDDEN_MESSAGE"))5051 out, _ := os.Create("stego.png")52 defer out.Close()53 png.Encode(out, dst)54 fmt.Println("Done — payload embedded into stego.png")55}Read-only codeUTF-8