secrets-engine/verifier/main.go
tegwick 4dd004a225
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Verify normalized task approval facts and preserve signed source types
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
2026-10-16 17:28:03 +02:00

48 lines
1.2 KiB
Go

// Decision verification uses the unchanged Access Engine producer implementation.
package main
import (
"crypto/ed25519"
"encoding/base64"
"encoding/json"
"fmt"
"github.com/netkingdom/access-engine/internal/sign"
"io"
"os"
)
type input struct {
Envelope json.RawMessage `json:"envelope"`
Keys map[string]string `json:"keys"`
}
func run() error {
var in input
if err := json.NewDecoder(io.LimitReader(os.Stdin, 1048577)).Decode(&in); err != nil {
return err
}
envelope, err := sign.DecodeEnvelope(in.Envelope)
if err != nil {
return err
}
keys := map[string]ed25519.PublicKey{}
for kid, encoded := range in.Keys {
raw, err := base64.RawURLEncoding.Strict().DecodeString(encoded)
if err != nil || len(raw) != ed25519.PublicKeySize || kid == "" {
return fmt.Errorf("invalid admitted key")
}
keys[kid] = ed25519.PublicKey(raw)
}
if err := sign.Verify(envelope, keys); err != nil {
return err
}
// Return the exact typed interpretation authenticated by the producer; Python
// must never act on a second interpretation of unverified response fields.
return json.NewEncoder(os.Stdout).Encode(envelope)
}
func main() {
if run() != nil {
fmt.Fprintln(os.Stderr, "decision signature verification refused")
os.Exit(1)
}
}