54 lines
1.5 KiB
Go
54 lines
1.5 KiB
Go
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 <model> <hardware-revision> <version> <file>")
|
||
|
|
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
|
||
|
|
}
|