// Packer MVP: encrypts an input binary with AES-256-GCM and writes a // Go source file containing the encrypted payload as a byte array, plus // a stub that decrypts and writes to stdout at runtime. // // Usage: go run ./cmd/packer -in BINARY -out PACKED.go -key HEXKEY // // MVP: output is a .go file, not a native binary. Production packer // would generate a native stub. package main import ( "crypto/aes" "crypto/cipher" "crypto/rand" "encoding/hex" "flag" "fmt" "io" "os" "text/template" ) const stubTemplate = `// Code generated by cmd/packer. DO NOT EDIT. //go:build ignore package main import ( "crypto/aes" "crypto/cipher" "encoding/hex" "os" ) var payload = []byte{ {{.Payload}} } var keyHex = "{{.KeyHex}}" func main() { key, err := hex.DecodeString(keyHex) if err != nil || len(key) != 32 { os.Exit(1) } block, err := aes.NewCipher(key) if err != nil { os.Exit(1) } gcm, err := cipher.NewGCM(block) if err != nil { os.Exit(1) } plaintext, err := gcm.Open(nil, payload[:12], payload[12:], nil) if err != nil { os.Exit(1) } os.Stdout.Write(plaintext) } ` func main() { in := flag.String("in", "", "input binary path") out := flag.String("out", "", "output .go file path") keyHex := flag.String("key", "", "hex-encoded 32-byte key (random if empty)") flag.Parse() if *in == "" || *out == "" { fmt.Fprintln(os.Stderr, "usage: packer -in BINARY -out PACKED.go [-key HEXKEY]") os.Exit(2) } plaintext, err := os.ReadFile(*in) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } var key []byte if *keyHex != "" { key, err = hex.DecodeString(*keyHex) if err != nil || len(key) != 32 { fmt.Fprintln(os.Stderr, "invalid key: must be 32-byte hex") os.Exit(1) } } else { key = make([]byte, 32) if _, err := io.ReadFull(rand.Reader, key); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } block, err := aes.NewCipher(key) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } gcm, err := cipher.NewGCM(block) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } nonce := make([]byte, 12) if _, err := io.ReadFull(rand.Reader, nonce); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } ciphertext := gcm.Seal(nonce, nonce, plaintext, nil) payloadLit := "" for i, b := range ciphertext { if i > 0 { payloadLit += "," } payloadLit += fmt.Sprintf("%d", b) } f, err := os.Create(*out) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } defer f.Close() t := template.Must(template.New("stub").Parse(stubTemplate)) if err := t.Execute(f, map[string]string{ "Payload": payloadLit, "KeyHex": hex.EncodeToString(key), }); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } fmt.Printf("Packed: %s (%d bytes -> %d bytes)\n", *out, len(plaintext), len(ciphertext)) }