I am working on a Go application that encrypts sensitive files using a public key. The goal of my project is to create a customizable encryption tool that allows users to generate an executable tailored to their needs. The idea is that the user will input their own public key, and the tool will produce a unique executable, which they can then use to securely encrypt their files.
The challenge is that I cannot assume the target machine has Go installed for me to compile the code locally. Additionally, I would like to ensure the solution is portable, meaning the executable should be able to run on any machine without requiring Go setup.
How can I inject a user-specific public key into a pre-built Go binary after it’s been compiled? Or are there better solutions that I could not think of?
You can use objcopy
for this with the --add-section
flag, there might be other better ways to do this but this is the first one I thought of.
You can parse it by either using the elf.h C API or Go's debug/elf directly if you're only worried about ELF executables or you can use something like BFD (I think there's no Go bindings for this) if you want to support other executable formats.
objcopy
itself uses BFD so you can use it for all the formats it supports.
Here's the debug/elf approach:
package main
import (
"debug/elf"
"os"
"fmt"
"log"
)
func main() {
exePath, err := os.Executable()
if err != nil {
log.Fatal(err)
}
exeFile, err := os.Open(exePath)
if err != nil {
log.Fatal(err)
}
defer exeFile.Close()
exeELF, err := elf.NewFile(exeFile)
if err != nil {
log.Fatal(err)
}
myData := exeELF.Section("my_data")
if myData == nil {
log.Fatal("my_data section missing")
}
data, err := myData.Data()
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data)) // "lorem ipsum"
}
compile it and add the section.
objcopy
takes the section data from a file, I called it "data", it contains "lorem ipsum" and my go binary is "goembed", so I'd do objcopy --add-section my_data=data goembed goembed
which will overwrite the goembed binary with a new one but with the new section and when you run the program it prints "lorem ipsum". That section can also be edited with --update-section
in a similar way.
You could even get rid of the objcopy
dependency and just do this section adding/editing yourself in Go.