Files
bible/rules/patterns/release-signing/README.md
2026-04-02 13:48:36 +03:00

85 lines
1.8 KiB
Markdown

# Release Signing Pattern Notes
This file keeps examples and rationale. The normative rules live in `contract.md`.
## Keys Repository Shape
```text
keys/
developers/
<name>.pub
scripts/
keygen.sh
sign-release.sh
verify-signature.sh
```
## Runtime Trust Loader
```go
// trustedKeysRaw is injected via -ldflags.
// Format: base64(key1):base64(key2):...
var trustedKeysRaw string
```
Typical parsing pattern:
```go
func trustedKeys() ([]ed25519.PublicKey, error) {
if trustedKeysRaw == "" {
return nil, fmt.Errorf("dev build: trusted keys not embedded, updates disabled")
}
var keys []ed25519.PublicKey
for _, enc := range strings.Split(trustedKeysRaw, ":") {
b, err := base64.StdEncoding.DecodeString(strings.TrimSpace(enc))
if err != nil || len(b) != ed25519.PublicKeySize {
return nil, fmt.Errorf("invalid trusted key: %w", err)
}
keys = append(keys, ed25519.PublicKey(b))
}
return keys, nil
}
```
## Build Example
```sh
KEYS=$(paste -sd: /path/to/keys/developers/*.pub)
go build \
-ldflags "-s -w -X <module>/internal/updater.trustedKeysRaw=${KEYS}" \
-o dist/<binary>-linux-amd64 \
./cmd/<binary>
```
## Verification Sketch
```go
func verifySignature(binaryPath, sigPath string) error {
keys, err := trustedKeys()
if err != nil {
return err
}
data, err := os.ReadFile(binaryPath)
if err != nil {
return fmt.Errorf("read binary: %w", err)
}
sig, err := os.ReadFile(sigPath)
if err != nil {
return fmt.Errorf("read signature: %w", err)
}
for _, key := range keys {
if ed25519.Verify(key, data, sig) {
return nil
}
}
return fmt.Errorf("signature verification failed: no trusted key matched")
}
```
## Release Assets
```text
<binary>-linux-amd64
<binary>-linux-amd64.sig
```