package attesto // Go parity against the Rust-normative provenance corpus. // // Rust (edge/) produced golden-vectors/provenance-v0.1-dev/. Go conforms iff it // reproduces every "valid" vector byte-for-byte and refuses every "invalid" one. // A corpus of only positive cases would prove the implementations can agree, // not that either can refuse. import ( "encoding/json" "os" "path/filepath" "testing" ) func provenanceVectorDir(t *testing.T) string { t.Helper() dir := filepath.Join("..", "..", "golden-vectors", "provenance-v0.1-dev") if _, err := os.Stat(dir); err != nil { t.Fatalf("provenance vectors missing at %s: %v", dir, err) } return dir } func loadProvenanceVector(t *testing.T, name string) map[string]any { t.Helper() path := filepath.Join(provenanceVectorDir(t), name+".json") raw, err := os.ReadFile(path) if err != nil { t.Fatalf("read %s: %v", path, err) } var vector map[string]any if err := json.Unmarshal(raw, &vector); err != nil { t.Fatalf("parse %s: %v", path, err) } return vector } func TestProvenanceCorpusIsPresentAndTyped(t *testing.T) { entries, err := filepath.Glob(filepath.Join(provenanceVectorDir(t), "*.json")) if err != nil || len(entries) == 0 { t.Fatalf("no provenance vectors: %v", err) } invalid := 0 for _, entry := range entries { raw, err := os.ReadFile(entry) if err != nil { t.Fatalf("read %s: %v", entry, err) } var vector map[string]any if err := json.Unmarshal(raw, &vector); err != nil { t.Fatalf("parse %s: %v", entry, err) } if vector["protocol"] != ProvenanceProtocol { t.Fatalf("%s: wrong protocol %v", entry, vector["protocol"]) } switch vector["expectation"] { case "valid": case "invalid": invalid++ default: t.Fatalf("%s: bad expectation %v", entry, vector["expectation"]) } } if invalid < 5 { t.Fatalf("corpus carries only %d negative vectors", invalid) } } func TestProvenancePinnedRandomizerReproducesRustDigest(t *testing.T) { vector := loadProvenanceVector(t, "provenance-commitment-valid") digest, err := ProvenanceCommitmentDigest( vector["domain"].(string), vector["value"], vector["randomizer"].(string), ) if err != nil { t.Fatalf("commit: %v", err) } if digest != vector["expected_digest"].(string) { t.Fatalf("digest mismatch:\n got %s\nwant %s", digest, vector["expected_digest"]) } ok, err := VerifyProvenanceCommitment( vector["domain"].(string), vector["value"], vector["randomizer"].(string), vector["expected_digest"].(string), ) if err != nil || !ok { t.Fatalf("verify failed: ok=%v err=%v", ok, err) } } func TestProvenanceSameValueDifferentRandomizerIsUnlinkable(t *testing.T) { vector := loadProvenanceVector(t, "provenance-commitment-randomizer-diff") seen := map[string]bool{} for _, entry := range vector["cases"].([]any) { testCase := entry.(map[string]any) digest, err := ProvenanceCommitmentDigest( vector["domain"].(string), vector["value"], testCase["randomizer"].(string), ) if err != nil { t.Fatalf("commit: %v", err) } if digest != testCase["expected_digest"].(string) { t.Fatalf("digest mismatch: got %s want %s", digest, testCase["expected_digest"]) } if seen[digest] { t.Fatal("two randomizers produced the same commitment") } seen[digest] = true } } func TestProvenanceSameValueAcrossDomainsDoesNotCollide(t *testing.T) { vector := loadProvenanceVector(t, "provenance-commitment-cross-domain") seen := map[string]bool{} for _, entry := range vector["cases"].([]any) { testCase := entry.(map[string]any) digest, err := ProvenanceCommitmentDigest( testCase["domain"].(string), vector["value"], vector["randomizer"].(string), ) if err != nil { t.Fatalf("commit: %v", err) } if digest != testCase["expected_digest"].(string) { t.Fatalf("digest mismatch: got %s want %s", digest, testCase["expected_digest"]) } if seen[digest] { t.Fatal("two domains produced the same commitment") } seen[digest] = true } } func TestProvenanceUnknownDomainIsRefused(t *testing.T) { vector := loadProvenanceVector(t, "provenance-commitment-invalid-domain") if _, err := ProvenanceCommitmentDigest( vector["domain"].(string), vector["value"], vector["randomizer"].(string), ); err == nil { t.Fatal("an unknown domain must not resolve to a fallback") } } func TestProvenanceMalformedRandomizersAreRefused(t *testing.T) { vector := loadProvenanceVector(t, "provenance-commitment-invalid-randomizer") for _, entry := range vector["cases"].([]any) { testCase := entry.(map[string]any) if _, err := ProvenanceCommitmentDigest( vector["domain"].(string), vector["value"], testCase["randomizer"].(string), ); err == nil { t.Fatalf("randomizer %q must be refused", testCase["randomizer"]) } } } func TestProvenanceDomainRegistryMatchesRust(t *testing.T) { vector := loadProvenanceVector(t, "provenance-domain-registry") domains := vector["domains"].([]any) // Eighteen provenance domains plus the three REVIEW-02 protocols that own // their own preimage spaces: disclosure v2 and the ZK range statement and // transcript. const expected = 21 if len(domains) != len(ProvenanceDomains) || len(domains) != expected { t.Fatalf( "registry size mismatch: vector=%d go=%d expected=%d", len(domains), len(ProvenanceDomains), expected, ) } for _, domain := range domains { if _, ok := ProvenanceDomains[domain.(string)]; !ok { t.Fatalf("missing domain %s", domain) } } for _, rejected := range vector["rejected"].([]any) { if _, ok := ProvenanceDomains[rejected.(string)]; ok { t.Fatalf("domain %s must not be in the registry", rejected) } } } func leafInputs(t *testing.T, raw any) []SubtreeLeafInput { t.Helper() encoded, err := json.Marshal(raw) if err != nil { t.Fatalf("marshal leaves: %v", err) } var leaves []SubtreeLeafInput if err := json.Unmarshal(encoded, &leaves); err != nil { t.Fatalf("unmarshal leaves: %v", err) } return leaves } func buildSubtree(t *testing.T, subtree string, raw any) (string, []string) { t.Helper() ordered, err := OrderSubtreeLeaves(leafInputs(t, raw)) if err != nil { t.Fatalf("order %s: %v", subtree, err) } merkle, err := SubtreeMerkleRoot(subtree, ordered) if err != nil { t.Fatalf("merkle %s: %v", subtree, err) } root, err := SubtreeRoot(subtree, merkle, len(ordered)) if err != nil { t.Fatalf("root %s: %v", subtree, err) } return root, ordered } func TestProvenanceCapsuleRootReproducesRustForest(t *testing.T) { vector := loadProvenanceVector(t, "provenance-capsule-root-valid") expected := vector["expected"].(map[string]any) claimsRoot, claimsOrdered := buildSubtree(t, "claims", vector["claims"]) for index, want := range expected["claims_ordered_leaves"].([]any) { if claimsOrdered[index] != want.(string) { t.Fatalf("claims leaf %d mismatch", index) } } if claimsRoot != expected["claims_root"].(string) { t.Fatalf("claims_root mismatch:\n got %s\nwant %s", claimsRoot, expected["claims_root"]) } evidenceRoot, _ := buildSubtree(t, "evidence", vector["evidence"]) if evidenceRoot != expected["evidence_root"].(string) { t.Fatalf("evidence_root mismatch") } policyRoot, _ := buildSubtree(t, "policy_results", vector["policy_results"]) if policyRoot != expected["policy_results_root"].(string) { t.Fatalf("policy_results_root mismatch") } randomizers := vector["top_randomizers"].(map[string]any) commitments := map[string]string{ "subject_commitment": vector["subject_commitment"].(string), "claims_root": claimsRoot, "evidence_root": evidenceRoot, "policy_results_root": policyRoot, "attestation_commitment": vector["attestation_commitment"].(string), "vault_identity_commitment": vector["vault_identity_commitment"].(string), } digests := make([]string, 0, len(TopLeafRoles)) for _, role := range TopLeafRoles { digest, err := TopLeafDigest(role, commitments[role], randomizers[role].(string)) if err != nil { t.Fatalf("top leaf %s: %v", role, err) } digests = append(digests, digest) } for index, want := range expected["top_leaf_digests"].([]any) { if digests[index] != want.(string) { t.Fatalf("top leaf digest %d mismatch", index) } } root, err := CapsuleRoot(digests) if err != nil { t.Fatalf("capsule root: %v", err) } if root != expected["capsule_root"].(string) { t.Fatalf("capsule_root mismatch:\n got %s\nwant %s", root, expected["capsule_root"]) } } func TestProvenanceOddNodesArePromotedNotDuplicated(t *testing.T) { vector := loadProvenanceVector(t, "provenance-capsule-root-promoted-odd-node") if vector["rule"] != "promote-odd-node" { t.Fatalf("unexpected rule %v", vector["rule"]) } seen := map[string]bool{} for _, entry := range vector["cases"].([]any) { testCase := entry.(map[string]any) ordered, err := OrderSubtreeLeaves(leafInputs(t, testCase["leaves"])) if err != nil { t.Fatalf("order: %v", err) } merkle, err := SubtreeMerkleRoot("claims", ordered) if err != nil { t.Fatalf("merkle: %v", err) } if merkle != testCase["expected_merkle_root"].(string) { t.Fatalf("merkle mismatch for %v leaves", testCase["leaf_count"]) } if seen[merkle] { t.Fatal("two tree sizes shared a root — odd node was duplicated") } seen[merkle] = true } } func TestProvenanceLeafOrderIsIndependentOfCallerOrder(t *testing.T) { vector := loadProvenanceVector(t, "provenance-capsule-root-valid") leaves := leafInputs(t, vector["claims"]) reversed := make([]SubtreeLeafInput, len(leaves)) for index, leaf := range leaves { reversed[len(leaves)-1-index] = leaf } forward, err := OrderSubtreeLeaves(leaves) if err != nil { t.Fatalf("order forward: %v", err) } backward, err := OrderSubtreeLeaves(reversed) if err != nil { t.Fatalf("order reversed: %v", err) } for index := range forward { if forward[index] != backward[index] { t.Fatal("leaf ordering depended on caller order") } } } func loadProof(t *testing.T, name string) (TwoHopProof, bool) { t.Helper() vector := loadProvenanceVector(t, name) encoded, err := json.Marshal(vector["proof"]) if err != nil { t.Fatalf("marshal proof: %v", err) } var proof TwoHopProof if err := json.Unmarshal(encoded, &proof); err != nil { t.Fatalf("unmarshal proof: %v", err) } return proof, vector["expected_verified"].(bool) } func TestProvenanceValidDisclosureVerifies(t *testing.T) { proof, expected := loadProof(t, "provenance-disclosure-valid") ok, err := VerifyTwoHop(proof) if err != nil { t.Fatalf("verify: %v", err) } if ok != expected { t.Fatalf("verification mismatch: got %v want %v", ok, expected) } } func TestProvenanceInvalidDisclosuresAreRefused(t *testing.T) { for _, name := range []string{ "provenance-disclosure-cross-tree-leaf", "provenance-disclosure-invalid-inclusion", "provenance-disclosure-foreign-leaf", } { proof, expected := loadProof(t, name) if expected { t.Fatalf("%s should be a negative vector", name) } ok, err := VerifyTwoHop(proof) if err != nil { t.Fatalf("%s: %v", name, err) } if ok { t.Fatalf("%s verified but must not", name) } } } func TestProvenanceClaimLeafCannotBeReaimedAtEvidenceRoot(t *testing.T) { valid, _ := loadProof(t, "provenance-disclosure-valid") cross, _ := loadProof(t, "provenance-disclosure-cross-tree-leaf") if cross.Leaf != valid.Leaf { t.Fatal("the vector must reuse the same claim leaf") } if cross.Subtree != "evidence" { t.Fatalf("expected the evidence side, got %s", cross.Subtree) } ok, err := VerifyTwoHop(cross) if err != nil { t.Fatalf("verify: %v", err) } if ok { t.Fatal("a claim leaf verified against the evidence root") } } func TestProvenanceCanonicalJSONMatchesRust(t *testing.T) { vector := loadProvenanceVector(t, "provenance-canonical-json") for _, entry := range vector["accepted"].([]any) { testCase := entry.(map[string]any) rendered, err := CanonicalJSON(testCase["value"]) if err != nil { t.Fatalf("canonical: %v", err) } if string(rendered) != testCase["canonical_json"].(string) { t.Fatalf("canonical mismatch:\n got %s\nwant %s", rendered, testCase["canonical_json"]) } } }