Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions pkg/plugin/implementation/vcvalidator/vcvalidator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,31 @@ func TestProofPresentButEmpty(t *testing.T) {
assertClassCode(t, err, failProof, codeAutSignatureMissing)
}

// TestDataIntegrityProofWithoutVerificationMethod asserts that a JSON-LD Data
// Integrity proof carrying no verificationMethod is rejected even when
// RequireProof is false. With requireProof disabled the signature itself is
// deliberately not checked, so the resolvable verificationMethod is the only
// remaining evidence about the credential; absent it there is nothing left to
// verify, which is the same situation as the no-proof and empty-proof cases
// and is classified with the same code.
func TestDataIntegrityProofWithoutVerificationMethod(t *testing.T) {
cfg := DefaultConfig()
cfg.Actions = []string{"confirm"}
cfg.RequireProof = false

vc := map[string]any{
"issuer": "did:web:issuer.example.org",
"credentialSubject": map[string]any{"id": "x"},
"proof": map[string]any{
"type": "Ed25519Signature2020",
"proofValue": "z58DAdFfa9Skq...",
},
}
v := testVerifier(cfg)
err := v.verify(context.Background(), vcBytes(t, vc))
assertClassCode(t, err, failProof, codeAutSignatureMissing)
}

// TestUnsupportedDIDMethodIsKeyNotFound asserts a resolution failure caused by
// a disallowed/unsupported DID method (not a network problem) is classified
// AUT_KEY_NOT_FOUND rather than a NET_* code.
Expand Down
18 changes: 12 additions & 6 deletions pkg/plugin/implementation/vcvalidator/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,12 +220,18 @@ func (v *verifier) verify(ctx context.Context, raw json.RawMessage) error {
"set requireProof=false to accept on expiry/revocation only",
cred.Proof.Type)
}
// Best-effort: confirm the verification method DID resolves.
if vm := cred.Proof.VerificationMethod; vm != "" {
if _, err := resolveDID(ctx, vm, "", v.cfg, v.fetch); err != nil {
if !v.cfg.FailOpen {
return failf(failResolution, resolutionCode(err), "verificationMethod %q did not resolve: %v", vm, err)
}
// Best-effort: confirm the verification method DID resolves. Without a
// verificationMethod there is nothing at all left to check — the same
// defect as the two cases above — so reject rather than accept a
// credential on which no verification was performed.
vm := cred.Proof.VerificationMethod
if vm == "" {
return failf(failProof, codeAutSignatureMissing,
"proof type %q has no verificationMethod to resolve", cred.Proof.Type)
}
if _, err := resolveDID(ctx, vm, "", v.cfg, v.fetch); err != nil {
if !v.cfg.FailOpen {
return failf(failResolution, resolutionCode(err), "verificationMethod %q did not resolve: %v", vm, err)
}
}
} else {
Expand Down