diff --git a/component/models/dataintegrity/integration_test.go b/component/models/dataintegrity/integration_test.go index a5cf5ca96..fc200b1a2 100644 --- a/component/models/dataintegrity/integration_test.go +++ b/component/models/dataintegrity/integration_test.go @@ -77,10 +77,10 @@ func TestIntegration(t *testing.T) { p384JWK, err := jwkkid.BuildJWK(p384Bytes, kmsapi.ECDSAP384IEEEP1363) require.NoError(t, err) - p256VM, err := did.NewVerificationMethodFromJWK(mockVMID, "JsonWebKey2020", mockDID, p256JWK) + p256VM, err := did.NewVerificationMethodFromJWK(mockKID, "JsonWebKey2020", mockDID, p256JWK) require.NoError(t, err) - p384VM, err := did.NewVerificationMethodFromJWK(mockVMID2, "JsonWebKey2020", mockDID2, p384JWK) + p384VM, err := did.NewVerificationMethodFromJWK(mockKID2, "JsonWebKey2020", mockDID2, p384JWK) require.NoError(t, err) resolver := resolveFunc(func(id string) (*did.DocResolution, error) { @@ -105,14 +105,13 @@ func TestIntegration(t *testing.T) { t.Run("success", func(t *testing.T) { t.Run("P-256 key", func(t *testing.T) { signOpts := &models.ProofOptions{ - VerificationMethod: p256VM, - VerificationMethodID: p256VM.ID, - SuiteType: ecdsa2019.SuiteType, - Purpose: "assertionMethod", - VerificationRelationship: "assertionMethod", - ProofType: models.DataIntegrityProof, - Created: time.Now(), - MaxAge: 100, + VerificationMethod: p256VM, + VerificationMethodID: p256VM.ID, + SuiteType: ecdsa2019.SuiteType, + Purpose: AssertionMethod, + ProofType: models.DataIntegrityProof, + Created: time.Now(), + MaxAge: 100, } signedCred, err := signer.AddProof(validCredential, signOpts) @@ -121,7 +120,7 @@ func TestIntegration(t *testing.T) { verifyOpts := &models.ProofOptions{ VerificationMethodID: mockKID, SuiteType: ecdsa2019.SuiteType, - Purpose: "assertionMethod", + Purpose: AssertionMethod, ProofType: models.DataIntegrityProof, Created: time.Now(), MaxAge: 100, @@ -133,14 +132,13 @@ func TestIntegration(t *testing.T) { t.Run("P-384 key", func(t *testing.T) { signOpts := &models.ProofOptions{ - VerificationMethod: p384VM, - VerificationMethodID: mockKID2, - SuiteType: ecdsa2019.SuiteType, - Purpose: "assertionMethod", - VerificationRelationship: "assertionMethod", - ProofType: models.DataIntegrityProof, - Created: time.Now(), - MaxAge: 100, + VerificationMethod: p384VM, + VerificationMethodID: mockKID2, + SuiteType: ecdsa2019.SuiteType, + Purpose: AssertionMethod, + ProofType: models.DataIntegrityProof, + Created: time.Now(), + MaxAge: 100, } signedCred, err := signer.AddProof(validCredential, signOpts) @@ -149,7 +147,7 @@ func TestIntegration(t *testing.T) { verifyOpts := &models.ProofOptions{ VerificationMethodID: mockKID2, SuiteType: ecdsa2019.SuiteType, - Purpose: "assertionMethod", + Purpose: AssertionMethod, ProofType: models.DataIntegrityProof, Created: time.Now(), MaxAge: 100, @@ -163,23 +161,21 @@ func TestIntegration(t *testing.T) { t.Run("failure", func(t *testing.T) { t.Run("wrong key", func(t *testing.T) { signOpts := &models.ProofOptions{ - VerificationMethod: p256VM, - VerificationMethodID: p256VM.ID, - SuiteType: ecdsa2019.SuiteType, - Purpose: "assertionMethod", - VerificationRelationship: "assertionMethod", - ProofType: models.DataIntegrityProof, - Created: time.Now(), + VerificationMethod: p256VM, + VerificationMethodID: p256VM.ID, + SuiteType: ecdsa2019.SuiteType, + Purpose: AssertionMethod, + ProofType: models.DataIntegrityProof, + Created: time.Now(), } verifyOpts := &models.ProofOptions{ - VerificationMethod: p384VM, - VerificationMethodID: p384VM.ID, - SuiteType: ecdsa2019.SuiteType, - Purpose: "assertionMethod", - VerificationRelationship: "assertionMethod", - ProofType: models.DataIntegrityProof, - MaxAge: 100, + VerificationMethod: p384VM, + VerificationMethodID: p384VM.ID, + SuiteType: ecdsa2019.SuiteType, + Purpose: AssertionMethod, + ProofType: models.DataIntegrityProof, + MaxAge: 100, } signedCred, err := signer.AddProof(validCredential, signOpts) @@ -191,24 +187,22 @@ func TestIntegration(t *testing.T) { }) t.Run("malformed proof created", func(t *testing.T) { signOpts := &models.ProofOptions{ - VerificationMethod: p256VM, - VerificationMethodID: p256VM.ID, - SuiteType: ecdsa2019.SuiteType, - Purpose: "assertionMethod", - VerificationRelationship: "assertionMethod", - ProofType: models.DataIntegrityProof, - Created: time.Now(), + VerificationMethod: p256VM, + VerificationMethodID: p256VM.ID, + SuiteType: ecdsa2019.SuiteType, + Purpose: "assertionMethod", + ProofType: models.DataIntegrityProof, + Created: time.Now(), } verifyOpts := &models.ProofOptions{ - VerificationMethod: p384VM, - VerificationMethodID: p384VM.ID, - SuiteType: ecdsa2019.SuiteType, - Purpose: "assertionMethod", - VerificationRelationship: "assertionMethod", - ProofType: models.DataIntegrityProof, - MaxAge: 100, - Created: time.Time{}, + VerificationMethod: p384VM, + VerificationMethodID: p384VM.ID, + SuiteType: ecdsa2019.SuiteType, + Purpose: "assertionMethod", + ProofType: models.DataIntegrityProof, + MaxAge: 100, + Created: time.Time{}, } signedCred, err := signer.AddProof(validCredential, signOpts) diff --git a/component/models/dataintegrity/models/models.go b/component/models/dataintegrity/models/models.go index 55550ad84..c224c503e 100644 --- a/component/models/dataintegrity/models/models.go +++ b/component/models/dataintegrity/models/models.go @@ -48,17 +48,16 @@ type Proof struct { // ProofOptions provides options for signing or verifying a data integrity proof. type ProofOptions struct { - Purpose string - VerificationMethodID string - VerificationMethod *VerificationMethod - VerificationRelationship string - ProofType string - SuiteType string - Domain string - Challenge string - Created time.Time - MaxAge int64 - CustomFields map[string]interface{} + Purpose string + VerificationMethodID string + VerificationMethod *VerificationMethod + ProofType string + SuiteType string + Domain string + Challenge string + Created time.Time + MaxAge int64 + CustomFields map[string]interface{} } // DateTimeFormat is the date-time format used by the data integrity diff --git a/component/models/dataintegrity/signer.go b/component/models/dataintegrity/signer.go index f3500850b..5d7dd9bfc 100644 --- a/component/models/dataintegrity/signer.go +++ b/component/models/dataintegrity/signer.go @@ -9,13 +9,31 @@ package dataintegrity import ( "encoding/json" "errors" + "fmt" + "strings" "github.com/tidwall/sjson" - "github.com/hyperledger/aries-framework-go/component/models/jwt/didsignjwt" - "github.com/hyperledger/aries-framework-go/component/models/dataintegrity/models" "github.com/hyperledger/aries-framework-go/component/models/dataintegrity/suite" + "github.com/hyperledger/aries-framework-go/component/models/did" +) + +const ( + // AssertionMethod assertionMethod. + AssertionMethod = "assertionMethod" + + // Authentication authentication. + Authentication = "authentication" + + // CapabilityDelegation capabilityDelegation. + CapabilityDelegation = "capabilityDelegation" + + // CapabilityInvocation capabilityInvocation. + CapabilityInvocation = "capabilityInvocation" + + creatorParts = 2 + invalidFormatErrMsgFmt = "verificationMethod value %s should be in did#keyID format" ) // Signer implements the Add Proof algorithm of the verifiable credential data @@ -117,7 +135,7 @@ func (s *Signer) AddProof(doc []byte, opts *models.ProofOptions) ([]byte, error) } func resolveVM(opts *models.ProofOptions, resolver didResolver, vmID string) error { - if opts.VerificationMethod == nil || opts.VerificationRelationship == "" { + if opts.VerificationMethod == nil { if opts.VerificationMethodID == "" { opts.VerificationMethodID = vmID } @@ -126,22 +144,103 @@ func resolveVM(opts *models.ProofOptions, resolver didResolver, vmID string) err return ErrNoResolver } - vm, vmID, rel, err := didsignjwt.ResolveSigningVMWithRelationship(opts.VerificationMethodID, resolver) + didDoc, err := getDIDDocFromVerificationMethod(opts.VerificationMethodID, resolver) + if err != nil { + // TODO update linter to use go 1.20: https://github.com/hyperledger/aries-framework-go/issues/3613 + return errors.Join(ErrVMResolution, err) // nolint:typecheck + } + + vm, err := getVMByPurpose(opts.Purpose, opts.VerificationMethodID, didDoc) if err != nil { // TODO update linter to use go 1.20: https://github.com/hyperledger/aries-framework-go/issues/3613 return errors.Join(ErrVMResolution, err) // nolint:typecheck } - opts.VerificationMethodID = vmID opts.VerificationMethod = vm + } + + return nil +} + +func getVMByPurpose(purpose, vmID string, didDoc *did.Doc) (*did.VerificationMethod, error) { + var verificationMethod *did.VerificationMethod + + vmIDFragment := vmIDFragmentOnly(vmID) - // A VM with general relationship is allowed for assertion - if rel == "" { - rel = "assertionMethod" + switch purpose { + case AssertionMethod: + assertionMethods := didDoc.VerificationMethods(did.AssertionMethod)[did.AssertionMethod] + + verificationMethod = getVM(vmIDFragment, assertionMethods) + if verificationMethod == nil { + // A VM with general relationship is allowed for assertion + generalMethods := + didDoc.VerificationMethods(did.VerificationRelationshipGeneral)[did.VerificationRelationshipGeneral] + + verificationMethod = getVM(vmIDFragment, generalMethods) } + case Authentication: + authMethods := didDoc.VerificationMethods(did.Authentication)[did.Authentication] + + verificationMethod = getVM(vmIDFragment, authMethods) + case CapabilityDelegation: + capabilityDelegationMethods := didDoc.VerificationMethods(did.CapabilityDelegation)[did.CapabilityDelegation] + + verificationMethod = getVM(vmIDFragment, capabilityDelegationMethods) + case CapabilityInvocation: + capabilityInvocationMethods := didDoc.VerificationMethods(did.CapabilityInvocation)[did.CapabilityInvocation] + + verificationMethod = getVM(vmIDFragment, capabilityInvocationMethods) + default: + return nil, fmt.Errorf("purpose %s not supported", purpose) + } - opts.VerificationRelationship = rel + if verificationMethod == nil { + return nil, fmt.Errorf("unable to find matching %s key IDs for given verification method ID %s", + purpose, vmID) + } + + return verificationMethod, nil +} + +func getVM(vmID string, vms []did.Verification) *did.VerificationMethod { + for _, verification := range vms { + if vmID == vmIDFragmentOnly(verification.VerificationMethod.ID) { + return &verification.VerificationMethod + } } return nil } + +func vmIDFragmentOnly(vmID string) string { + vmSplit := strings.Split(vmID, "#") + if len(vmSplit) == 1 { + return vmSplit[0] + } + + return vmSplit[1] +} + +func getDIDDocFromVerificationMethod(verificationMethod string, didResolver didResolver) (*did.Doc, error) { + didID, err := getDIDFromVerificationMethod(verificationMethod) + if err != nil { + return nil, err + } + + docResolution, err := didResolver.Resolve(didID) + if err != nil { + return nil, err + } + + return docResolution.DIDDocument, nil +} + +func getDIDFromVerificationMethod(creator string) (string, error) { + idSplit := strings.Split(creator, "#") + if len(idSplit) != creatorParts { + return "", fmt.Errorf(fmt.Sprintf(invalidFormatErrMsgFmt, creator)) + } + + return idSplit[0], nil +} diff --git a/component/models/dataintegrity/signer_test.go b/component/models/dataintegrity/signer_test.go index bbeac3cec..ae3bd4fce 100644 --- a/component/models/dataintegrity/signer_test.go +++ b/component/models/dataintegrity/signer_test.go @@ -64,16 +64,16 @@ func TestSigner_AddProof(t *testing.T) { &Options{ DIDResolver: &mockResolver{ vm: &did.VerificationMethod{ - ID: "#key-1", + ID: "did:foo:bar#key-1", }, - vr: did.AssertionMethod, + vr: did.Authentication, }, }, &mockSuiteInitializer{ mockSuite: &mockSuite{ CreateProofVal: &models.Proof{ Type: mockSuiteType, - ProofPurpose: "mock-purpose", + ProofPurpose: Authentication, VerificationMethod: "mock-vm", Domain: "mock-domain", Challenge: "mock-challenge", @@ -91,18 +91,19 @@ func TestSigner_AddProof(t *testing.T) { Domain: "mock-domain", Challenge: "mock-challenge", MaxAge: 1000, + Purpose: Authentication, }) require.NoError(t, err) expectProof := []byte(fmt.Sprintf(`{ "type": "mock-suite-2023", - "proofPurpose": "mock-purpose", + "proofPurpose": "%s", "verificationMethod":"mock-vm", "proofValue":"", "created": "%s", "domain": "mock-domain", "challenge":"mock-challenge" - }`, createdTime)) + }`, Authentication, createdTime)) proofBytes, unsignedDoc := extractProof(t, signedDoc) @@ -154,11 +155,10 @@ func TestSigner_AddProof(t *testing.T) { require.NoError(t, err) _, err = s.AddProof(mockDoc, &models.ProofOptions{ - SuiteType: mockSuiteType, - VerificationRelationship: "assertionMethod", - Domain: "mock-domain", - Challenge: "mock-challenge", - MaxAge: 1000, + SuiteType: mockSuiteType, + Domain: "mock-domain", + Challenge: "mock-challenge", + MaxAge: 1000, }) require.ErrorIs(t, err, ErrNoResolver) }) @@ -176,7 +176,7 @@ func TestSigner_AddProof(t *testing.T) { mockSuite: &mockSuite{ CreateProofVal: &models.Proof{ Type: mockSuiteType, - ProofPurpose: "mock-purpose", + ProofPurpose: CapabilityDelegation, VerificationMethod: "mock-vm", Domain: "mock-domain", Challenge: "mock-challenge", @@ -189,11 +189,12 @@ func TestSigner_AddProof(t *testing.T) { require.NoError(t, err) _, err = s.AddProof(mockDoc, &models.ProofOptions{ - SuiteType: mockSuiteType, - VerificationRelationship: "assertionMethod", - Domain: "mock-domain", - Challenge: "mock-challenge", - MaxAge: 1000, + SuiteType: mockSuiteType, + VerificationMethodID: "did:foo:bar#key-1", + Purpose: CapabilityDelegation, + Domain: "mock-domain", + Challenge: "mock-challenge", + MaxAge: 1000, }) require.ErrorIs(t, err, errExpected) require.ErrorIs(t, err, ErrVMResolution) @@ -212,9 +213,8 @@ func TestSigner_AddProof(t *testing.T) { require.NoError(t, err) signedDoc, err := s.AddProof(mockDoc, &models.ProofOptions{ - VerificationMethod: &did.VerificationMethod{}, - VerificationRelationship: "assertionMethod", - SuiteType: mockSuiteType, + VerificationMethod: &did.VerificationMethod{}, + SuiteType: mockSuiteType, }) require.ErrorIs(t, err, ErrProofGeneration) require.Nil(t, signedDoc) @@ -238,9 +238,8 @@ func TestSigner_AddProof(t *testing.T) { require.NoError(t, err) signedDoc, err := s.AddProof(mockDoc, &models.ProofOptions{ - SuiteType: mockSuiteType, - VerificationMethod: &did.VerificationMethod{}, - VerificationRelationship: "assertionMethod", + SuiteType: mockSuiteType, + VerificationMethod: &did.VerificationMethod{}, }) require.ErrorIs(t, err, ErrProofGeneration) require.Nil(t, signedDoc) @@ -252,8 +251,7 @@ func TestSigner_AddProof(t *testing.T) { &mockSuiteInitializer{ mockSuite: &mockSuite{ CreateProofVal: &models.Proof{ - Type: mockSuiteType, - // ProofPurpose: "mock-purpose", + Type: mockSuiteType, VerificationMethod: "mock-vm", }, }, @@ -263,9 +261,8 @@ func TestSigner_AddProof(t *testing.T) { require.NoError(t, err) signedDoc, err := s.AddProof(mockDoc, &models.ProofOptions{ - SuiteType: mockSuiteType, - VerificationMethod: &did.VerificationMethod{}, - VerificationRelationship: "assertionMethod", + SuiteType: mockSuiteType, + VerificationMethod: &did.VerificationMethod{}, }) require.ErrorIs(t, err, ErrProofGeneration) require.Nil(t, signedDoc) @@ -279,7 +276,6 @@ func TestSigner_AddProof(t *testing.T) { CreateProofVal: &models.Proof{ Type: mockSuiteType, ProofPurpose: "mock-purpose", - // VerificationMethod: "mock-vm", }, }, typeStr: mockSuiteType, @@ -288,9 +284,8 @@ func TestSigner_AddProof(t *testing.T) { require.NoError(t, err) signedDoc, err := s.AddProof(mockDoc, &models.ProofOptions{ - SuiteType: mockSuiteType, - VerificationMethod: &did.VerificationMethod{}, - VerificationRelationship: "assertionMethod", + SuiteType: mockSuiteType, + VerificationMethod: &did.VerificationMethod{}, }) require.ErrorIs(t, err, ErrProofGeneration) require.Nil(t, signedDoc) @@ -314,9 +309,8 @@ func TestSigner_AddProof(t *testing.T) { require.NoError(t, err) signedDoc, err := s.AddProof(mockDoc, &models.ProofOptions{ - SuiteType: mockSuiteType, - VerificationMethod: &did.VerificationMethod{}, - VerificationRelationship: "assertionMethod", + SuiteType: mockSuiteType, + VerificationMethod: &did.VerificationMethod{}, }) require.ErrorIs(t, err, ErrProofGeneration) require.Nil(t, signedDoc) @@ -341,10 +335,9 @@ func TestSigner_AddProof(t *testing.T) { require.NoError(t, err) signedDoc, err := s.AddProof(mockDoc, &models.ProofOptions{ - VerificationMethod: &did.VerificationMethod{}, - VerificationRelationship: "assertionMethod", - SuiteType: mockSuiteType, - Domain: "expected-domain", + VerificationMethod: &did.VerificationMethod{}, + SuiteType: mockSuiteType, + Domain: "expected-domain", }) require.ErrorIs(t, err, ErrProofGeneration) require.Nil(t, signedDoc) @@ -369,11 +362,10 @@ func TestSigner_AddProof(t *testing.T) { require.NoError(t, err) signedDoc, err := s.AddProof(mockDoc, &models.ProofOptions{ - SuiteType: mockSuiteType, - Domain: "expected-domain", - Challenge: "expected-challenge", - VerificationMethod: &did.VerificationMethod{}, - VerificationRelationship: "assertionMethod", + SuiteType: mockSuiteType, + Domain: "expected-domain", + Challenge: "expected-challenge", + VerificationMethod: &did.VerificationMethod{}, }) require.ErrorIs(t, err, ErrProofGeneration) require.Nil(t, signedDoc) diff --git a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go index 4ad1fce8b..bd6093b39 100644 --- a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go +++ b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019.go @@ -250,10 +250,7 @@ func (s *Suite) transformAndHash(doc []byte, opts *models.ProofOptions) ([]byte, return nil, nil, nil, errors.New("unsupported ECDSA curve") } - confData, err := proofConfig(docData[ldCtxKey], opts) - if err != nil { - return nil, nil, nil, err - } + confData := proofConfig(docData[ldCtxKey], opts) if opts.ProofType != "DataIntegrityProof" || opts.SuiteType != SuiteType { return nil, nil, nil, suite.ErrProofTransformation @@ -321,24 +318,15 @@ func hashData(transformedDoc, confData []byte, h hash.Hash) []byte { return result } -func proofConfig(docCtx interface{}, opts *models.ProofOptions) (map[string]interface{}, error) { - if opts.Purpose != opts.VerificationRelationship { - return nil, fmt.Errorf( - "verification method %s is not suitable for purpose %s", opts.VerificationRelationship, opts.Purpose) - } - - timeStr := opts.Created.Format(models.DateTimeFormat) - - conf := map[string]interface{}{ +func proofConfig(docCtx interface{}, opts *models.ProofOptions) map[string]interface{} { + return map[string]interface{}{ ldCtxKey: docCtx, "type": models.DataIntegrityProof, "cryptosuite": SuiteType, "verificationMethod": opts.VerificationMethodID, - "created": timeStr, + "created": opts.Created.Format(models.DateTimeFormat), "proofPurpose": opts.Purpose, } - - return conf, nil } // TODO copied from kid_creator.go, should move there: https://github.com/hyperledger/aries-framework-go/issues/3614 diff --git a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go index 6e2225480..d97e9ad91 100644 --- a/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go +++ b/component/models/dataintegrity/suite/ecdsa2019/ecdsa2019_test.go @@ -102,14 +102,13 @@ func successCase(t *testing.T) *testCase { proofCreated := time.Now() proofOpts := &models.ProofOptions{ - VerificationMethod: mockVM, - VerificationMethodID: mockVM.ID, - SuiteType: SuiteType, - Purpose: "assertionMethod", - VerificationRelationship: "assertionMethod", - ProofType: models.DataIntegrityProof, - Created: proofCreated, - MaxAge: 100, + VerificationMethod: mockVM, + VerificationMethodID: mockVM.ID, + SuiteType: SuiteType, + Purpose: "assertionMethod", + ProofType: models.DataIntegrityProof, + Created: proofCreated, + MaxAge: 100, } mockSig, err := multibase.Encode(multibase.Base58BTC, []byte("mock signature")) @@ -334,15 +333,6 @@ func TestSharedFailures(t *testing.T) { testVerify(t, tc) }) - t.Run("wrong purpose", func(t *testing.T) { - tc := successCase(t) - - tc.proofOpts.Purpose = fooBar - tc.errStr = "verification method assertionMethod is not suitable for purpose foo bar" - - testSign(t, tc) - }) - t.Run("invalid proof/suite type", func(t *testing.T) { tc := successCase(t) diff --git a/component/models/dataintegrity/suite/ecdsa2019/integration_test.go b/component/models/dataintegrity/suite/ecdsa2019/integration_test.go index 392006c8d..3cf840b4f 100644 --- a/component/models/dataintegrity/suite/ecdsa2019/integration_test.go +++ b/component/models/dataintegrity/suite/ecdsa2019/integration_test.go @@ -75,14 +75,13 @@ func TestIntegration(t *testing.T) { t.Run("success", func(t *testing.T) { t.Run("P-256 key", func(t *testing.T) { proofOpts := &models.ProofOptions{ - VerificationMethod: p256VM, - VerificationMethodID: p256VM.ID, - SuiteType: SuiteType, - Purpose: "assertionMethod", - VerificationRelationship: "assertionMethod", - ProofType: models.DataIntegrityProof, - Created: time.Now(), - MaxAge: 100, + VerificationMethod: p256VM, + VerificationMethodID: p256VM.ID, + SuiteType: SuiteType, + Purpose: "assertionMethod", + ProofType: models.DataIntegrityProof, + Created: time.Now(), + MaxAge: 100, } proof, err := signer.CreateProof(validCredential, proofOpts) @@ -94,14 +93,13 @@ func TestIntegration(t *testing.T) { t.Run("P-384 key", func(t *testing.T) { proofOpts := &models.ProofOptions{ - VerificationMethod: p384VM, - VerificationMethodID: p384VM.ID, - SuiteType: SuiteType, - Purpose: "assertionMethod", - VerificationRelationship: "assertionMethod", - ProofType: models.DataIntegrityProof, - Created: time.Now(), - MaxAge: 100, + VerificationMethod: p384VM, + VerificationMethodID: p384VM.ID, + SuiteType: SuiteType, + Purpose: "assertionMethod", + ProofType: models.DataIntegrityProof, + Created: time.Now(), + MaxAge: 100, } proof, err := signer.CreateProof(validCredential, proofOpts) @@ -115,23 +113,21 @@ func TestIntegration(t *testing.T) { t.Run("failure", func(t *testing.T) { t.Run("wrong key", func(t *testing.T) { signOpts := &models.ProofOptions{ - VerificationMethod: p256VM, - VerificationMethodID: p256VM.ID, - SuiteType: SuiteType, - Purpose: "assertionMethod", - VerificationRelationship: "assertionMethod", - ProofType: models.DataIntegrityProof, - Created: time.Now(), + VerificationMethod: p256VM, + VerificationMethodID: p256VM.ID, + SuiteType: SuiteType, + Purpose: "assertionMethod", + ProofType: models.DataIntegrityProof, + Created: time.Now(), } verifyOpts := &models.ProofOptions{ - VerificationMethod: p384VM, - VerificationMethodID: p384VM.ID, - SuiteType: SuiteType, - Purpose: "assertionMethod", - VerificationRelationship: "assertionMethod", - ProofType: models.DataIntegrityProof, - MaxAge: 100, + VerificationMethod: p384VM, + VerificationMethodID: p384VM.ID, + SuiteType: SuiteType, + Purpose: "assertionMethod", + ProofType: models.DataIntegrityProof, + MaxAge: 100, } proof, err := signer.CreateProof(validCredential, signOpts) diff --git a/component/models/dataintegrity/support_test.go b/component/models/dataintegrity/support_test.go index 6e96863d1..588e15a6b 100644 --- a/component/models/dataintegrity/support_test.go +++ b/component/models/dataintegrity/support_test.go @@ -178,6 +178,10 @@ func makeMockDIDResolution(id string, vm *did.VerificationMethod, vr did.Verific doc.Authentication = ver case did.AssertionMethod: doc.AssertionMethod = ver + case did.CapabilityDelegation: + doc.CapabilityDelegation = ver + case did.CapabilityInvocation: + doc.CapabilityInvocation = ver } return &did.DocResolution{ diff --git a/component/models/dataintegrity/verifier_test.go b/component/models/dataintegrity/verifier_test.go index 08478f5e7..c98b3c9d6 100644 --- a/component/models/dataintegrity/verifier_test.go +++ b/component/models/dataintegrity/verifier_test.go @@ -69,7 +69,7 @@ func TestVerifier_VerifyProof(t *testing.T) { &Options{ DIDResolver: &mockResolver{ vm: &did.VerificationMethod{ - ID: mockVMID, + ID: mockKID, }, vr: did.AssertionMethod, }, @@ -87,7 +87,7 @@ func TestVerifier_VerifyProof(t *testing.T) { Type: models.DataIntegrityProof, CryptoSuite: mockSuiteType, VerificationMethod: mockKID, - ProofPurpose: "mock-purpose", + ProofPurpose: AssertionMethod, Created: createdTime, Domain: "mock-domain", Challenge: "mock-challenge", @@ -97,7 +97,50 @@ func TestVerifier_VerifyProof(t *testing.T) { require.NoError(t, err) err = v.VerifyProof(signedDoc, &models.ProofOptions{ - Purpose: "mock-purpose", + Purpose: AssertionMethod, + MaxAge: 1000, + Domain: "mock-domain", + Challenge: "mock-challenge", + }) + require.NoError(t, err) + }) + + t.Run("success general purpose", func(t *testing.T) { + createdTime := time.Now().Format(models.DateTimeFormat) + + v, err := NewVerifier( + &Options{ + DIDResolver: &mockResolver{ + vm: &did.VerificationMethod{ + ID: mockKID, + }, + vr: did.VerificationRelationshipGeneral, + }, + }, + &mockSuiteInitializer{ + mockSuite: &mockSuite{ + ReqCreatedVal: true, + }, + typeStr: mockSuiteType, + }) + + require.NoError(t, err) + + mockProof := &models.Proof{ + Type: models.DataIntegrityProof, + CryptoSuite: mockSuiteType, + VerificationMethod: mockKID, + ProofPurpose: AssertionMethod, + Created: createdTime, + Domain: "mock-domain", + Challenge: "mock-challenge", + } + + signedDoc, err := mockAddProof(mockDoc, mockProof) + require.NoError(t, err) + + err = v.VerifyProof(signedDoc, &models.ProofOptions{ + Purpose: AssertionMethod, MaxAge: 1000, Domain: "mock-domain", Challenge: "mock-challenge", @@ -289,12 +332,56 @@ func TestVerifier_VerifyProof(t *testing.T) { require.NoError(t, err) err = v.VerifyProof(signedDoc, &models.ProofOptions{ - Created: time.Now(), Purpose: "different-purpose", + Created: time.Now(), }) require.ErrorIs(t, err, ErrMismatchedPurpose) }) + t.Run("unsupported purpose", func(t *testing.T) { + createdTime := time.Now().Format(models.DateTimeFormat) + + v, err := NewVerifier( + &Options{ + DIDResolver: &mockResolver{ + vm: &did.VerificationMethod{ + ID: mockKID, + }, + vr: did.VerificationRelationshipGeneral, + }, + }, + &mockSuiteInitializer{ + mockSuite: &mockSuite{ + ReqCreatedVal: true, + }, + typeStr: mockSuiteType, + }) + + require.NoError(t, err) + + mockProof := &models.Proof{ + Type: models.DataIntegrityProof, + CryptoSuite: mockSuiteType, + VerificationMethod: mockKID, + ProofPurpose: "mock-purpose", + Created: createdTime, + Domain: "mock-domain", + Challenge: "mock-challenge", + } + + signedDoc, err := mockAddProof(mockDoc, mockProof) + require.NoError(t, err) + + err = v.VerifyProof(signedDoc, &models.ProofOptions{ + Purpose: "mock-purpose", + MaxAge: 1000, + Domain: "mock-domain", + Challenge: "mock-challenge", + }) + require.ErrorIs(t, err, ErrVMResolution) + require.ErrorContains(t, err, "purpose mock-purpose not supported") + }) + t.Run("no resolver", func(t *testing.T) { v, err := NewVerifier( &Options{}, @@ -310,6 +397,7 @@ func TestVerifier_VerifyProof(t *testing.T) { CryptoSuite: mockSuiteType, VerificationMethod: mockKID, ProofPurpose: "mock-purpose", + Created: time.Now().Format(models.DateTimeFormat), } signedDoc, err := mockAddProof(mockDoc, mockProof) @@ -317,7 +405,6 @@ func TestVerifier_VerifyProof(t *testing.T) { err = v.VerifyProof(signedDoc, &models.ProofOptions{ Purpose: "mock-purpose", - Created: time.Now(), MaxAge: 1000, }) require.Error(t, err) @@ -343,6 +430,7 @@ func TestVerifier_VerifyProof(t *testing.T) { CryptoSuite: mockSuiteType, VerificationMethod: mockKID, ProofPurpose: "mock-purpose", + Created: time.Now().Format(models.DateTimeFormat), } signedDoc, err := mockAddProof(mockDoc, mockProof) @@ -350,7 +438,6 @@ func TestVerifier_VerifyProof(t *testing.T) { err = v.VerifyProof(signedDoc, &models.ProofOptions{ Purpose: "mock-purpose", - Created: time.Now(), MaxAge: 1000, }) require.Error(t, err) @@ -365,7 +452,7 @@ func TestVerifier_VerifyProof(t *testing.T) { vm: &did.VerificationMethod{ ID: mockVMID, }, - vr: did.AssertionMethod, + vr: did.CapabilityInvocation, }, }, &mockSuiteInitializer{ @@ -381,15 +468,15 @@ func TestVerifier_VerifyProof(t *testing.T) { Type: models.DataIntegrityProof, CryptoSuite: mockSuiteType, VerificationMethod: mockKID, - ProofPurpose: "mock-purpose", + ProofPurpose: CapabilityInvocation, + Created: time.Now().Format(models.DateTimeFormat), } signedDoc, err := mockAddProof(mockDoc, mockProof) require.NoError(t, err) err = v.VerifyProof(signedDoc, &models.ProofOptions{ - Purpose: "mock-purpose", - Created: time.Now(), + Purpose: CapabilityInvocation, }) require.ErrorIs(t, err, errExpected) }) @@ -415,7 +502,7 @@ func TestVerifier_VerifyProof(t *testing.T) { Type: models.DataIntegrityProof, CryptoSuite: mockSuiteType, VerificationMethod: mockKID, - ProofPurpose: "mock-purpose", + ProofPurpose: AssertionMethod, Created: "Id. Mar. DCCX AUC", } @@ -423,7 +510,7 @@ func TestVerifier_VerifyProof(t *testing.T) { require.NoError(t, err) err = v.VerifyProof(signedDoc, &models.ProofOptions{ - Purpose: "mock-purpose", + Purpose: AssertionMethod, }) require.ErrorIs(t, err, ErrMalformedProof) }) @@ -451,7 +538,7 @@ func TestVerifier_VerifyProof(t *testing.T) { Type: models.DataIntegrityProof, CryptoSuite: mockSuiteType, VerificationMethod: mockKID, - ProofPurpose: "mock-purpose", + ProofPurpose: AssertionMethod, Created: createdTime, } @@ -459,7 +546,7 @@ func TestVerifier_VerifyProof(t *testing.T) { require.NoError(t, err) err = v.VerifyProof(signedDoc, &models.ProofOptions{ - Purpose: "mock-purpose", + Purpose: AssertionMethod, MaxAge: 5, }) require.ErrorIs(t, err, ErrOutOfDate) @@ -486,17 +573,17 @@ func TestVerifier_VerifyProof(t *testing.T) { Type: models.DataIntegrityProof, CryptoSuite: mockSuiteType, VerificationMethod: mockKID, - ProofPurpose: "mock-purpose", + ProofPurpose: AssertionMethod, Domain: "wrong-domain", + Created: time.Now().Format(models.DateTimeFormat), } signedDoc, err := mockAddProof(mockDoc, mockProof) require.NoError(t, err) err = v.VerifyProof(signedDoc, &models.ProofOptions{ - Purpose: "mock-purpose", + Purpose: AssertionMethod, Domain: "mock-domain", - Created: time.Now(), }) require.ErrorIs(t, err, ErrInvalidDomain) }) @@ -508,7 +595,7 @@ func TestVerifier_VerifyProof(t *testing.T) { vm: &did.VerificationMethod{ ID: mockVMID, }, - vr: did.AssertionMethod, + vr: did.CapabilityDelegation, }, }, &mockSuiteInitializer{ @@ -522,7 +609,7 @@ func TestVerifier_VerifyProof(t *testing.T) { Type: models.DataIntegrityProof, CryptoSuite: mockSuiteType, VerificationMethod: mockKID, - ProofPurpose: "mock-purpose", + ProofPurpose: CapabilityDelegation, Challenge: "wrong-challenge", } @@ -530,7 +617,7 @@ func TestVerifier_VerifyProof(t *testing.T) { require.NoError(t, err) err = v.VerifyProof(signedDoc, &models.ProofOptions{ - Purpose: "mock-purpose", + Purpose: CapabilityDelegation, Challenge: "mock-challenge", Created: time.Now(), })