package hostevidence import ( "crypto/ed25519" "crypto/rand" "testing" ) func TestReceiptSignatureBindsProducerKeyAndExactBytes(t *testing.T) { pub, private, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Fatal(err) } key := "control/hosts/x.example/evidence/op/box/receipt.json" body := []byte(`{"evidence_at":"2026-10-07T00:00:00Z"}`) wire, err := message(key, body) if err != nil { t.Fatal(err) } signature := ed25519.Sign(private, wire) if err = Verify(pub, key, body, signature); err != nil { t.Fatal(err) } other, _, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Fatal(err) } for _, test := range []struct { pub ed25519.PublicKey key string body []byte }{ {other, key, body}, {pub, key + "changed", body}, {pub, key, []byte(`{"evidence_at":"2026-10-08T00:00:00Z"}`)}, } { if Verify(test.pub, test.key, test.body, signature) == nil { t.Fatal("accepted forged receipt") } } } func TestReceiptSignatureSeparatesServingAndOperationEvidence(t *testing.T) { pub, private, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Fatal(err) } body := []byte(`{"region":"ie","claim_etag":"etag","observed_boot_id":"boot","request_limit_ns":120000000000}`) keys := []string{ "control/hosts/x.example/serving-evidence/box/receipt.json", "control/hosts/x.example/evidence/op/box/receipt.json", } for _, key := range keys { wire, err := message(key, body) if err != nil { t.Fatal(err) } sig := ed25519.Sign(private, wire) if err := Verify(pub, key, body, sig); err != nil { t.Fatal(err) } for _, other := range keys { if other != key && Verify(pub, other, body, sig) == nil { t.Fatal("receipt signature crossed evidence namespaces") } } } for _, key := range []string{ "control/hosts/x.example/serving-evidence/op/box/receipt.json", "control/hosts/x.example/evidence/box/receipt.json", "control/hosts/x.example/serving-evidence/../receipt.json", "control/hosts/x.example/serving-evidence//receipt.json", "control/hosts/x.example/serving-evidence/box/receipt.json.sig", } { if _, err := message(key, body); err == nil { t.Fatalf("accepted invalid evidence key %q", key) } } }