first commit

This commit is contained in:
2025-05-22 17:22:27 +02:00
commit c3fcbb6616
11 changed files with 563 additions and 0 deletions

3
stego-client/config.yaml Normal file
View File

@ -0,0 +1,3 @@
security:
# Generate with: openssl rand -base64 32
aes_key: "mBH9cMfhD939xPiQz1mnDvECeUu8ydrVEg1YptjTzH4="

129
stego-client/decode.go Normal file
View File

@ -0,0 +1,129 @@
package main
import (
"bufio"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
"image"
"log"
"os"
"github.com/auyer/steganography"
"github.com/chai2010/webp"
"gopkg.in/yaml.v3"
)
type DecodeConfig struct {
Security struct {
AESKey string `yaml:"aes_key"` // Base64 encoded 32-byte key
} `yaml:"security"`
}
var (
aesKey []byte
cfg DecodeConfig
)
func loadDecodeConfig(filename string) error {
data, err := os.ReadFile(filename)
if err != nil {
return fmt.Errorf("config file read error: %w", err)
}
if err := yaml.Unmarshal(data, &cfg); err != nil {
return fmt.Errorf("config parse error: %w", err)
}
return nil
}
func decryptData(ciphertext []byte) ([]byte, error) {
block, err := aes.NewCipher(aesKey)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonceSize := gcm.NonceSize()
if len(ciphertext) < nonceSize {
return nil, fmt.Errorf("ciphertext too short")
}
nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
return gcm.Open(nil, nonce, ciphertext, nil)
}
func decodeImage(file *os.File) (image.Image, error) {
reader := bufio.NewReader(file)
// Try to decode with image.Decode first
img, _, err := image.Decode(reader)
if err == nil {
return img, nil
}
// Try fallback: WebP
// Reset file offset to 0
_, _ = file.Seek(0, 0)
img, err = webp.Decode(file)
if err != nil {
return nil, fmt.Errorf("unsupported image format or decode failure: %w", err)
}
return img, nil
}
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go run decode.go <encoded_image>")
return
}
if err := loadDecodeConfig("config.yaml"); err != nil {
log.Fatalf("Failed to load config: %v", err)
}
filePath := os.Args[1]
inFile, err := os.Open(filePath)
if err != nil {
fmt.Printf("Failed to open file: %v\n", err)
return
}
defer inFile.Close()
// Initialize AES key
if cfg.Security.AESKey != "" {
aesKey, err = base64.StdEncoding.DecodeString(cfg.Security.AESKey)
if err != nil {
log.Fatalf("Invalid AES key in config: %v", err)
}
} else {
log.Fatal("AES key not provided in config.")
}
img, err := decodeImage(inFile)
if err != nil {
fmt.Printf("Failed to decode image: %v\n", err)
return
}
size := steganography.GetMessageSizeFromImage(img)
message := steganography.Decode(size, img)
if message == nil {
fmt.Println("No message found in the image.")
return
}
decryptedMessage, err := decryptData(message)
if err != nil {
fmt.Printf("Failed to decrypt message: %v\n", err)
return
}
fmt.Printf("Decrypted message: %s\n", decryptedMessage)
}

9
stego-client/go.mod Normal file
View File

@ -0,0 +1,9 @@
module stego-client
go 1.21.9
require (
github.com/auyer/steganography v1.0.3
github.com/chai2010/webp v1.4.0
gopkg.in/yaml.v3 v3.0.1
)

8
stego-client/go.sum Normal file
View File

@ -0,0 +1,8 @@
github.com/auyer/steganography v1.0.3 h1:NAFie4xVYY/LbYLkYCr0CJyyG/7yIXwC+yEC6H2jiSA=
github.com/auyer/steganography v1.0.3/go.mod h1:Q2qN+f1ixaXnKTCT4xkSDCZ/5NiOpUeTgOCLwQdJD+A=
github.com/chai2010/webp v1.4.0 h1:6DA2pkkRUPnbOHvvsmGI3He1hBKf/bkRlniAiSGuEko=
github.com/chai2010/webp v1.4.0/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

BIN
stego-client/stego-client Executable file

Binary file not shown.