package main import ( "crypto/ed25519" "crypto/rand" "crypto/sha256" "encoding/base64" "encoding/hex" "encoding/json" "fmt" "os" ) type signedFirmware struct { PublicKeyBase64 string `json:"public_key_base64"` SignatureBase64 string `json:"signature_base64"` SHA256 string `json:"sha256"` Size int `json:"size"` Manifest string `json:"manifest"` } func main() { if len(os.Args) != 5 { fmt.Fprintln(os.Stderr, "usage: firmware-sign ") os.Exit(2) } content, err := os.ReadFile(os.Args[4]) if err != nil { panic(err) } result, err := signFirmware(os.Args[1], os.Args[2], os.Args[3], content) if err != nil { panic(err) } if err := json.NewEncoder(os.Stdout).Encode(result); err != nil { panic(err) } } func signFirmware(model, hardwareRevision, version string, content []byte) (signedFirmware, error) { publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader) if err != nil { return signedFirmware{}, err } digest := sha256.Sum256(content) digestText := hex.EncodeToString(digest[:]) manifest := fmt.Sprintf("firmware-manifest-v1\nmodel=%s\nhardware_revision=%s\nversion=%s\nsha256=%s\nsize=%d\n", model, hardwareRevision, version, digestText, len(content)) return signedFirmware{ PublicKeyBase64: base64.StdEncoding.EncodeToString(publicKey), SignatureBase64: base64.StdEncoding.EncodeToString(ed25519.Sign(privateKey, []byte(manifest))), SHA256: digestText, Size: len(content), Manifest: manifest, }, nil }