diff --git a/auth/services/notary/notary.go b/auth/services/notary/notary.go
index f24d20abd3..739b485548 100644
--- a/auth/services/notary/notary.go
+++ b/auth/services/notary/notary.go
@@ -107,14 +107,14 @@ func NewNotary(config Config, vcr vcr.VCR, keyResolver types.KeyResolver, keySto
// If the duration is 0 than the default duration is used.
func (n *notary) DrawUpContract(ctx context.Context, template contract.Template, orgID did.DID, validFrom time.Time, validDuration time.Duration, organizationCredential *vc.VerifiableCredential) (*contract.Contract, error) {
// Test if the org in managed by this node:
- signingKeyID, err := n.keyResolver.ResolveSigningKeyID(orgID, &validFrom)
+ signingKeyID, _, err := n.keyResolver.ResolveKey(orgID, &validFrom, types.NutsSigningKeyType)
if errors.Is(err, types.ErrNotFound) {
return nil, services.InvalidContractRequestError{Message: "no valid organization credential at provided validFrom date"}
} else if err != nil {
return nil, fmt.Errorf("could not draw up contract: %w", err)
}
- if !n.privateKeyStore.Exists(ctx, signingKeyID) {
+ if !n.privateKeyStore.Exists(ctx, signingKeyID.String()) {
return nil, services.InvalidContractRequestError{Message: fmt.Errorf("organization is not managed by this node: %w", ErrMissingOrganizationKey)}
}
diff --git a/auth/services/notary/notary_test.go b/auth/services/notary/notary_test.go
index 350cc1dc40..84eb416d24 100644
--- a/auth/services/notary/notary_test.go
+++ b/auth/services/notary/notary_test.go
@@ -54,7 +54,7 @@ func TestContract_DrawUpContract(t *testing.T) {
duration := 10 * time.Minute
// Create DID document for org
- keyID := orgID
+ keyID := orgID.URI()
keyID.Fragment = "key-1"
searchTerms := []vcr.SearchTerm{
@@ -69,7 +69,7 @@ func TestContract_DrawUpContract(t *testing.T) {
t.Run("draw up valid contract", func(t *testing.T) {
test := buildContext(t)
- test.keyResolver.EXPECT().ResolveSigningKeyID(orgID, gomock.Any()).Return(keyID.String(), nil)
+ test.keyResolver.EXPECT().ResolveKey(orgID, &validFrom, types.NutsSigningKeyType).Return(keyID, nil, nil)
test.keyStore.EXPECT().Exists(ctx, keyID.String()).Return(true)
test.vcr.EXPECT().Search(context.Background(), searchTerms, false, nil).Return([]vc.VerifiableCredential{testCredential}, nil)
@@ -84,7 +84,7 @@ func TestContract_DrawUpContract(t *testing.T) {
test := buildContext(t)
defer test.ctrl.Finish()
- test.keyResolver.EXPECT().ResolveSigningKeyID(orgID, gomock.Any()).Return(keyID.String(), nil)
+ test.keyResolver.EXPECT().ResolveKey(orgID, gomock.Any(), types.NutsSigningKeyType).Return(keyID, nil, nil)
test.keyStore.EXPECT().Exists(ctx, keyID.String()).Return(true)
drawnUpContract, err := test.notary.DrawUpContract(ctx, template, orgID, validFrom, duration, &testCredential)
@@ -97,7 +97,7 @@ func TestContract_DrawUpContract(t *testing.T) {
t.Run("no given duration uses default", func(t *testing.T) {
test := buildContext(t)
- test.keyResolver.EXPECT().ResolveSigningKeyID(orgID, gomock.Any()).Return(keyID.String(), nil)
+ test.keyResolver.EXPECT().ResolveKey(orgID, &validFrom, gomock.Any()).Return(keyID, nil, nil)
test.keyStore.EXPECT().Exists(ctx, keyID.String()).Return(true)
test.vcr.EXPECT().Search(context.Background(), searchTerms, false, nil).Return([]vc.VerifiableCredential{testCredential}, nil)
@@ -111,7 +111,7 @@ func TestContract_DrawUpContract(t *testing.T) {
t.Run("no given time uses time.Now()", func(t *testing.T) {
test := buildContext(t)
- test.keyResolver.EXPECT().ResolveSigningKeyID(orgID, gomock.Any()).Return(keyID.String(), nil)
+ test.keyResolver.EXPECT().ResolveKey(orgID, &time.Time{}, gomock.Any()).Return(keyID, nil, nil)
test.keyStore.EXPECT().Exists(ctx, keyID.String()).Return(true)
test.vcr.EXPECT().Search(context.Background(), searchTerms, false, nil).Return([]vc.VerifiableCredential{testCredential}, nil)
@@ -129,7 +129,7 @@ func TestContract_DrawUpContract(t *testing.T) {
t.Run("nok - unknown organization", func(t *testing.T) {
test := buildContext(t)
- test.keyResolver.EXPECT().ResolveSigningKeyID(orgID, gomock.Any()).Return("", types.ErrNotFound)
+ test.keyResolver.EXPECT().ResolveKey(orgID, &validFrom, gomock.Any()).Return(ssi.URI{}, nil, types.ErrNotFound)
drawnUpContract, err := test.notary.DrawUpContract(ctx, template, orgID, validFrom, duration, nil)
@@ -140,7 +140,7 @@ func TestContract_DrawUpContract(t *testing.T) {
t.Run("nok - unknown private key", func(t *testing.T) {
test := buildContext(t)
- test.keyResolver.EXPECT().ResolveSigningKeyID(orgID, gomock.Any()).Return(keyID.String(), nil)
+ test.keyResolver.EXPECT().ResolveKey(orgID, &validFrom, gomock.Any()).Return(keyID, nil, nil)
test.keyStore.EXPECT().Exists(ctx, keyID.String()).Return(false)
drawnUpContract, err := test.notary.DrawUpContract(ctx, template, orgID, validFrom, duration, nil)
@@ -152,7 +152,7 @@ func TestContract_DrawUpContract(t *testing.T) {
t.Run("nok - other DID resolver error", func(t *testing.T) {
test := buildContext(t)
- test.keyResolver.EXPECT().ResolveSigningKeyID(orgID, gomock.Any()).Return("", errors.New("error occurred"))
+ test.keyResolver.EXPECT().ResolveKey(orgID, &validFrom, gomock.Any()).Return(ssi.URI{}, nil, errors.New("error occurred"))
drawnUpContract, err := test.notary.DrawUpContract(ctx, template, orgID, validFrom, duration, nil)
@@ -163,7 +163,7 @@ func TestContract_DrawUpContract(t *testing.T) {
t.Run("nok - could not find credential", func(t *testing.T) {
test := buildContext(t)
- test.keyResolver.EXPECT().ResolveSigningKeyID(orgID, gomock.Any()).Return(keyID.String(), nil)
+ test.keyResolver.EXPECT().ResolveKey(orgID, &validFrom, gomock.Any()).Return(keyID, nil, nil)
test.keyStore.EXPECT().Exists(ctx, keyID.String()).Return(true)
test.vcr.EXPECT().Search(context.Background(), searchTerms, false, nil).Return(nil, errors.New("error occurred"))
@@ -176,7 +176,7 @@ func TestContract_DrawUpContract(t *testing.T) {
t.Run("nok - render error", func(t *testing.T) {
test := buildContext(t)
- test.keyResolver.EXPECT().ResolveSigningKeyID(orgID, gomock.Any()).Return(keyID.String(), nil)
+ test.keyResolver.EXPECT().ResolveKey(orgID, &validFrom, gomock.Any()).Return(keyID, nil, nil)
test.keyStore.EXPECT().Exists(ctx, keyID.String()).Return(true)
test.vcr.EXPECT().Search(context.Background(), searchTerms, false, nil).Return([]vc.VerifiableCredential{testCredential}, nil)
@@ -193,7 +193,7 @@ func TestContract_DrawUpContract(t *testing.T) {
t.Run("ok - multiple (matching) VCs", func(t *testing.T) {
test := buildContext(t)
- test.keyResolver.EXPECT().ResolveSigningKeyID(orgID, gomock.Any()).Return(keyID.String(), nil)
+ test.keyResolver.EXPECT().ResolveKey(orgID, &validFrom, gomock.Any()).Return(keyID, nil, nil)
test.keyStore.EXPECT().Exists(ctx, keyID.String()).Return(true)
test.vcr.EXPECT().Search(context.Background(), searchTerms, false, nil).Return([]vc.VerifiableCredential{testCredential, testCredential}, nil)
@@ -210,7 +210,7 @@ func TestContract_DrawUpContract(t *testing.T) {
testCredential2 := vc.VerifiableCredential{}
_ = json.Unmarshal([]byte(jsonld.TestCredential), &testCredential2)
- test.keyResolver.EXPECT().ResolveSigningKeyID(orgID, gomock.Any()).Return(keyID.String(), nil)
+ test.keyResolver.EXPECT().ResolveKey(orgID, &validFrom, gomock.Any()).Return(keyID, nil, nil)
test.keyStore.EXPECT().Exists(ctx, keyID.String()).Return(true)
test.vcr.EXPECT().Search(context.Background(), searchTerms, false, nil).Return([]vc.VerifiableCredential{testCredential, testCredential2}, nil)
@@ -223,7 +223,7 @@ func TestContract_DrawUpContract(t *testing.T) {
t.Run("nok - given VC does not contain organization name", func(t *testing.T) {
test := buildContext(t)
- test.keyResolver.EXPECT().ResolveSigningKeyID(orgID, gomock.Any()).Return(keyID.String(), nil)
+ test.keyResolver.EXPECT().ResolveKey(orgID, &validFrom, gomock.Any()).Return(keyID, nil, nil)
test.keyStore.EXPECT().Exists(ctx, keyID.String()).Return(true)
drawnUpContract, err := test.notary.DrawUpContract(ctx, template, orgID, validFrom, duration, &vc.VerifiableCredential{})
diff --git a/auth/services/oauth/authz_server.go b/auth/services/oauth/authz_server.go
index f07c5ae439..8ffb1aae14 100644
--- a/auth/services/oauth/authz_server.go
+++ b/auth/services/oauth/authz_server.go
@@ -370,7 +370,7 @@ func (s *authzServer) validateIssuer(vContext *validationContext) error {
}
validationTime := vContext.jwtBearerToken.IssuedAt()
- if _, err := s.keyResolver.ResolveSigningKey(vContext.kid, &validationTime); err != nil {
+ if _, err := s.keyResolver.ResolveKeyByID(vContext.kid, &validationTime, types.NutsSigningKeyType); err != nil {
return fmt.Errorf(errInvalidIssuerKeyFmt, err)
}
@@ -422,11 +422,11 @@ func (s *authzServer) validateSubject(ctx context.Context, validationCtx *valida
validationCtx.authorizer = subject
iat := validationCtx.jwtBearerToken.IssuedAt()
- signingKeyID, err := s.keyResolver.ResolveSigningKeyID(*subject, &iat)
+ signingKeyID, _, err := s.keyResolver.ResolveKey(*subject, &iat, types.NutsSigningKeyType)
if err != nil {
return err
}
- if !s.privateKeyStore.Exists(ctx, signingKeyID) {
+ if !s.privateKeyStore.Exists(ctx, signingKeyID.String()) {
return fmt.Errorf("subject.vendor: %s is not managed by this node", subject)
}
@@ -494,7 +494,7 @@ func (s *authzServer) parseAndValidateJwtBearerToken(context *validationContext)
var kidHdr string
token, err := nutsCrypto.ParseJWT(context.rawJwtBearerToken, func(kid string) (crypto.PublicKey, error) {
kidHdr = kid
- return s.keyResolver.ResolveSigningKey(kid, nil)
+ return s.keyResolver.ResolveKeyByID(kid, nil, types.NutsSigningKeyType)
}, jwt.WithAcceptableSkew(s.clockSkew))
if err != nil {
return err
@@ -512,7 +512,7 @@ func (s *authzServer) IntrospectAccessToken(ctx context.Context, accessToken str
if !s.privateKeyStore.Exists(ctx, kid) {
return nil, fmt.Errorf("JWT signing key not present on this node (kid=%s)", kid)
}
- return s.keyResolver.ResolveSigningKey(kid, nil)
+ return s.keyResolver.ResolveKeyByID(kid, nil, types.NutsSigningKeyType)
}, jwt.WithAcceptableSkew(s.clockSkew))
if err != nil {
return nil, err
@@ -573,11 +573,11 @@ func (s *authzServer) buildAccessToken(ctx context.Context, requester did.DID, a
}
// Sign with the private key of the issuer
- signingKeyID, err := s.keyResolver.ResolveSigningKeyID(authorizer, &issueTime)
+ signingKeyID, _, err := s.keyResolver.ResolveKey(authorizer, &issueTime, types.NutsSigningKeyType)
if err != nil {
return "", accessToken, err
}
- token, err := s.privateKeyStore.SignJWT(ctx, keyVals, nil, signingKeyID)
+ token, err := s.privateKeyStore.SignJWT(ctx, keyVals, nil, signingKeyID.String())
if err != nil {
return token, accessToken, fmt.Errorf("could not build accessToken: %w", err)
}
diff --git a/auth/services/oauth/authz_server_test.go b/auth/services/oauth/authz_server_test.go
index c19cae1449..b4f926243a 100644
--- a/auth/services/oauth/authz_server_test.go
+++ b/auth/services/oauth/authz_server_test.go
@@ -125,8 +125,8 @@ func TestAuth_CreateAccessToken(t *testing.T) {
ctx.nameResolver.EXPECT().Search(context.Background(), searchTerms, false, gomock.Any()).Return([]vc.VerifiableCredential{testCredential}, nil)
ctx.contractNotary.EXPECT().VerifyVP(gomock.Any(), nil).Return(nil, errors.New("identity validation failed"))
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).MinTimes(1).Return(requesterSigningKey.Public(), nil)
- ctx.keyResolver.EXPECT().ResolveSigningKeyID(authorizerDID, gomock.Any()).MinTimes(1).Return(authorizerSigningKeyID.String(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKey.Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKey(authorizerDID, gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(authorizerSigningKeyID, authorizerSigningKey, nil)
ctx.keyStore.EXPECT().Exists(ctx.audit, authorizerSigningKeyID.String()).Return(true)
tokenCtx := validContext()
signToken(tokenCtx)
@@ -140,7 +140,7 @@ func TestAuth_CreateAccessToken(t *testing.T) {
t.Run("JWT validity too long", func(t *testing.T) {
ctx := createContext(t)
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).MinTimes(1).Return(requesterSigningKey.Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), nil, types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKey.Public(), nil)
tokenCtx := validContext()
tokenCtx.jwtBearerToken.Set(jwt.ExpirationKey, time.Now().Add(10*time.Second))
@@ -157,8 +157,8 @@ func TestAuth_CreateAccessToken(t *testing.T) {
ctx.nameResolver.EXPECT().Search(context.Background(), searchTerms, false, gomock.Any()).Return([]vc.VerifiableCredential{testCredential}, nil)
ctx.keyStore.EXPECT().Exists(ctx.audit, authorizerSigningKeyID.String()).Return(true)
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).MinTimes(1).Return(requesterSigningKey.Public(), nil)
- ctx.keyResolver.EXPECT().ResolveSigningKeyID(authorizerDID, gomock.Any()).MinTimes(1).Return(authorizerSigningKeyID.String(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKey.Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKey(authorizerDID, gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(authorizerSigningKeyID, authorizerSigningKey, nil)
ctx.contractNotary.EXPECT().VerifyVP(gomock.Any(), nil).Return(services.TestVPVerificationResult{Val: contract.Invalid, FailureReason: "because of reasons"}, nil)
tokenCtx := validContext()
@@ -172,8 +172,8 @@ func TestAuth_CreateAccessToken(t *testing.T) {
t.Run("error detail masking", func(t *testing.T) {
setup := func(ctx *testContext) *testContext {
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).MinTimes(1).Return(requesterSigningKey.Public(), nil).AnyTimes()
- ctx.keyResolver.EXPECT().ResolveSigningKeyID(authorizerDID, gomock.Any()).MinTimes(1).Return(authorizerSigningKeyID.String(), nil).AnyTimes()
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKey.Public(), nil).AnyTimes()
+ ctx.keyResolver.EXPECT().ResolveKey(authorizerDID, gomock.Any(), gomock.Any()).MinTimes(1).Return(authorizerSigningKeyID, authorizerSigningKey, nil).AnyTimes()
ctx.nameResolver.EXPECT().Search(context.Background(), searchTerms, false, gomock.Any()).Return([]vc.VerifiableCredential{testCredential}, nil).AnyTimes()
ctx.didResolver.EXPECT().Resolve(authorizerDID, gomock.Any()).Return(getAuthorizerDIDDocument(), nil, nil).AnyTimes()
ctx.serviceResolver.EXPECT().GetCompoundServiceEndpoint(authorizerDID, expectedService, services.OAuthEndpointType, true).Return(expectedAudience, nil).AnyTimes()
@@ -218,8 +218,8 @@ func TestAuth_CreateAccessToken(t *testing.T) {
t.Run("valid - without user identity", func(t *testing.T) {
testCtx := createContext(t)
- testCtx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).MinTimes(1).Return(requesterSigningKey.Public(), nil)
- testCtx.keyResolver.EXPECT().ResolveSigningKeyID(authorizerDID, gomock.Any()).MinTimes(1).Return(authorizerSigningKeyID.String(), nil)
+ testCtx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKey.Public(), nil)
+ testCtx.keyResolver.EXPECT().ResolveKey(authorizerDID, gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(authorizerSigningKeyID, authorizerSigningKey, nil)
testCtx.nameResolver.EXPECT().Search(context.Background(), searchTerms, false, gomock.Any()).Return([]vc.VerifiableCredential{testCredential}, nil)
testCtx.didResolver.EXPECT().Resolve(authorizerDID, gomock.Any()).Return(getAuthorizerDIDDocument(), nil, nil).AnyTimes()
testCtx.serviceResolver.EXPECT().GetCompoundServiceEndpoint(authorizerDID, expectedService, services.OAuthEndpointType, true).Return(expectedAudience, nil)
@@ -240,8 +240,8 @@ func TestAuth_CreateAccessToken(t *testing.T) {
t.Run("valid - all fields", func(t *testing.T) {
ctx := createContext(t)
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).MinTimes(1).Return(requesterSigningKey.Public(), nil)
- ctx.keyResolver.EXPECT().ResolveSigningKeyID(authorizerDID, gomock.Any()).MinTimes(1).Return(authorizerSigningKeyID.String(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKey.Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKey(authorizerDID, gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(authorizerSigningKeyID, authorizerSigningKey, nil)
ctx.nameResolver.EXPECT().Search(context.Background(), searchTerms, false, gomock.Any()).Return([]vc.VerifiableCredential{testCredential}, nil)
ctx.didResolver.EXPECT().Resolve(authorizerDID, gomock.Any()).Return(getAuthorizerDIDDocument(), nil, nil).AnyTimes()
ctx.serviceResolver.EXPECT().GetCompoundServiceEndpoint(authorizerDID, expectedService, services.OAuthEndpointType, true).Return(expectedAudience, nil)
@@ -265,7 +265,7 @@ func TestAuth_CreateAccessToken(t *testing.T) {
t.Run("missing organization credential", func(t *testing.T) {
ctx := createContext(t)
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).MinTimes(1).Return(requesterSigningKey.Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKey.Public(), nil)
ctx.nameResolver.EXPECT().Search(context.Background(), searchTerms, false, gomock.Any()).Return([]vc.VerifiableCredential{}, nil)
ctx.didResolver.EXPECT().Resolve(authorizerDID, gomock.Any()).Return(getAuthorizerDIDDocument(), nil, nil).AnyTimes()
@@ -290,7 +290,7 @@ func TestService_validateIssuer(t *testing.T) {
ctx := createContext(t)
tokenCtx := validContext()
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).MinTimes(1).Return(requesterSigningKey.Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKey.Public(), nil)
ctx.nameResolver.EXPECT().Search(context.Background(), searchTerms, false, gomock.Any()).Return([]vc.VerifiableCredential{testCredential}, nil)
err := ctx.oauthService.validateIssuer(tokenCtx)
@@ -302,7 +302,7 @@ func TestService_validateIssuer(t *testing.T) {
ctx := createContext(t)
tokenCtx := validContext()
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).MinTimes(1).Return(requesterSigningKey.Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKey.Public(), nil)
ctx.nameResolver.EXPECT().Search(context.Background(), searchTerms, false, gomock.Any()).Return([]vc.VerifiableCredential{testCredential, testCredential}, nil)
err := ctx.oauthService.validateIssuer(tokenCtx)
@@ -322,7 +322,7 @@ func TestService_validateIssuer(t *testing.T) {
ctx := createContext(t)
tokenCtx := validContext()
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).Return(requesterSigningKey.Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), gomock.Any(), types.NutsSigningKeyType).Return(requesterSigningKey.Public(), nil)
ctx.nameResolver.EXPECT().Search(context.Background(), searchTerms, false, gomock.Any()).Return(nil, errors.New("error occurred"))
err := ctx.oauthService.validateIssuer(tokenCtx)
@@ -332,7 +332,7 @@ func TestService_validateIssuer(t *testing.T) {
ctx := createContext(t)
tokenCtx := validContext()
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).Return(requesterSigningKey.Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), gomock.Any(), types.NutsSigningKeyType).Return(requesterSigningKey.Public(), nil)
ctx.nameResolver.EXPECT().Search(context.Background(), searchTerms, false, gomock.Any()).Return([]vc.VerifiableCredential{}, nil)
err := ctx.oauthService.validateIssuer(tokenCtx)
@@ -343,7 +343,7 @@ func TestService_validateIssuer(t *testing.T) {
tokenCtx := validContext()
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).MinTimes(1).Return(nil, fmt.Errorf("not found"))
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(nil, fmt.Errorf("not found"))
err := ctx.oauthService.validateIssuer(tokenCtx)
assert.EqualError(t, err, "invalid jwt.issuer key ID: not found")
@@ -357,7 +357,7 @@ func TestService_validateSubject(t *testing.T) {
tokenCtx := validContext()
tokenCtx.jwtBearerToken.Set(jwt.SubjectKey, authorizerDID.String())
- ctx.keyResolver.EXPECT().ResolveSigningKeyID(authorizerDID, gomock.Any()).MinTimes(1).Return(authorizerSigningKeyID.String(), nil)
+ ctx.keyResolver.EXPECT().ResolveKey(authorizerDID, gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(authorizerSigningKeyID, authorizerSigningKey, nil)
ctx.keyStore.EXPECT().Exists(ctx.audit, authorizerSigningKeyID.String()).Return(true)
err := ctx.oauthService.validateSubject(ctx.audit, tokenCtx)
@@ -387,7 +387,7 @@ func TestService_validateSubject(t *testing.T) {
tokenCtx := validContext()
tokenCtx.jwtBearerToken.Set(jwt.SubjectKey, authorizerDID.String())
- ctx.keyResolver.EXPECT().ResolveSigningKeyID(authorizerDID, gomock.Any()).MinTimes(1).Return(authorizerSigningKeyID.String(), nil)
+ ctx.keyResolver.EXPECT().ResolveKey(authorizerDID, gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(authorizerSigningKeyID, authorizerSigningKey, nil)
ctx.keyStore.EXPECT().Exists(ctx.audit, authorizerSigningKeyID.String()).Return(false)
err := ctx.oauthService.validateSubject(ctx.audit, tokenCtx)
@@ -587,7 +587,7 @@ func TestService_parseAndValidateJwtBearerToken(t *testing.T) {
keyID := "did:nuts:somedid#key-id"
- ctx.keyResolver.EXPECT().ResolveSigningKey(keyID, gomock.Any()).Return(privateKey.Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(keyID, nil, types.NutsSigningKeyType).Return(privateKey.Public(), nil)
// alg: RS256
token := jwt.New()
@@ -608,7 +608,7 @@ func TestService_parseAndValidateJwtBearerToken(t *testing.T) {
tokenCtx := validContext()
signToken(tokenCtx)
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).Return(requesterSigningKey.PublicKey, nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), nil, types.NutsSigningKeyType).Return(requesterSigningKey.PublicKey, nil)
err := ctx.oauthService.parseAndValidateJwtBearerToken(tokenCtx)
assert.NoError(t, err)
@@ -625,7 +625,7 @@ func TestService_parseAndValidateJwtBearerToken(t *testing.T) {
tokenCtx.jwtBearerToken.Set(jwt.ExpirationKey, time.Now().Add(-4*time.Minute))
signToken(tokenCtx)
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).Return(requesterSigningKey.PublicKey, nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), nil, types.NutsSigningKeyType).Return(requesterSigningKey.PublicKey, nil)
err := ctx.oauthService.parseAndValidateJwtBearerToken(tokenCtx)
assert.NoError(t, err)
@@ -640,7 +640,7 @@ func TestService_parseAndValidateJwtBearerToken(t *testing.T) {
tokenCtx.jwtBearerToken.Set(jwt.ExpirationKey, time.Now().Add(-4*time.Minute))
signToken(tokenCtx)
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).Return(requesterSigningKey.PublicKey, nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), nil, types.NutsSigningKeyType).Return(requesterSigningKey.PublicKey, nil)
err := ctx.oauthService.parseAndValidateJwtBearerToken(tokenCtx)
assert.EqualError(t, err, "exp not satisfied")
@@ -653,7 +653,7 @@ func TestService_buildAccessToken(t *testing.T) {
ctx.oauthService.accessTokenLifeSpan = secureAccessTokenLifeSpan * 10 // ignored by secureMode == true
ctx.oauthService.Configure(5000, true)
- ctx.keyResolver.EXPECT().ResolveSigningKeyID(authorizerDID, gomock.Any()).MinTimes(1).Return(authorizerSigningKeyID.String(), nil)
+ ctx.keyResolver.EXPECT().ResolveKey(authorizerDID, gomock.Any(), types.NutsSigningKeyType).MinTimes(1).Return(authorizerSigningKeyID, authorizerSigningKey, nil)
var actualClaims map[string]interface{}
ctx.keyStore.EXPECT().SignJWT(gomock.Any(), gomock.Any(), nil, gomock.Any()).
@@ -693,7 +693,7 @@ func TestService_IntrospectAccessToken(t *testing.T) {
t.Run("validate access token", func(t *testing.T) {
ctx := createContext(t)
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).MinTimes(1).Return(requesterSigningKey.Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), nil, types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKey.Public(), nil)
ctx.keyStore.EXPECT().Exists(ctx.audit, requesterSigningKeyID.String()).Return(true)
// First build an access token
@@ -714,7 +714,7 @@ func TestService_IntrospectAccessToken(t *testing.T) {
t.Run("invalid signature", func(t *testing.T) {
ctx := createContext(t)
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).MinTimes(1).Return(requesterSigningKey.Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), nil, types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKey.Public(), nil)
ctx.keyStore.EXPECT().Exists(ctx.audit, requesterSigningKeyID.String()).Return(true)
// First build an access token
@@ -747,7 +747,7 @@ func TestService_IntrospectAccessToken(t *testing.T) {
ctx := createContext(t)
ctx.keyStore.EXPECT().Exists(ctx.audit, requesterSigningKeyID.String()).Return(true)
- ctx.keyResolver.EXPECT().ResolveSigningKey(requesterSigningKeyID.String(), gomock.Any()).MinTimes(1).Return(nil, types.ErrNotFound)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(requesterSigningKeyID.String(), nil, types.NutsSigningKeyType).MinTimes(1).Return(nil, types.ErrNotFound)
// First build an access token
tokenCtx := validContext()
diff --git a/auth/services/oauth/relying_party.go b/auth/services/oauth/relying_party.go
index 4a6e8e5570..e521fc440f 100644
--- a/auth/services/oauth/relying_party.go
+++ b/auth/services/oauth/relying_party.go
@@ -118,12 +118,11 @@ func (s *relyingParty) CreateJwtGrant(ctx context.Context, request services.Crea
keyVals := claimsFromRequest(request, endpointURL)
- now := time.Now()
- signingKeyID, err := s.keyResolver.ResolveSigningKeyID(*requester, &now)
+ signingKeyID, _, err := s.keyResolver.ResolveKey(*requester, nil, types.NutsSigningKeyType)
if err != nil {
return nil, err
}
- signingString, err := s.privateKeyStore.SignJWT(ctx, keyVals, nil, signingKeyID)
+ signingString, err := s.privateKeyStore.SignJWT(ctx, keyVals, nil, signingKeyID.String())
if err != nil {
return nil, err
}
diff --git a/auth/services/oauth/relying_party_test.go b/auth/services/oauth/relying_party_test.go
index 84c83cbfe0..c6bc3a7743 100644
--- a/auth/services/oauth/relying_party_test.go
+++ b/auth/services/oauth/relying_party_test.go
@@ -151,7 +151,7 @@ func TestService_CreateJwtBearerToken(t *testing.T) {
ctx.didResolver.EXPECT().Resolve(authorizerDID, gomock.Any()).Return(authorizerDIDDocument, nil, nil).AnyTimes()
ctx.serviceResolver.EXPECT().GetCompoundServiceEndpoint(authorizerDID, expectedService, services.OAuthEndpointType, true).Return(expectedAudience, nil)
- ctx.keyResolver.EXPECT().ResolveSigningKeyID(requesterDID, gomock.Any()).MinTimes(1).Return(requesterSigningKeyID.String(), nil)
+ ctx.keyResolver.EXPECT().ResolveKey(requesterDID, nil, types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKeyID, requesterSigningKey, nil)
ctx.keyStore.EXPECT().SignJWT(gomock.Any(), gomock.Any(), nil, requesterSigningKeyID.String()).Return("token", nil)
token, err := ctx.relyingParty.CreateJwtGrant(ctx.audit, request)
@@ -168,7 +168,7 @@ func TestService_CreateJwtBearerToken(t *testing.T) {
ctx.didResolver.EXPECT().Resolve(authorizerDID, gomock.Any()).Return(authorizerDIDDocument, nil, nil).AnyTimes()
ctx.serviceResolver.EXPECT().GetCompoundServiceEndpoint(authorizerDID, expectedService, services.OAuthEndpointType, true).Return(expectedAudience, nil)
- ctx.keyResolver.EXPECT().ResolveSigningKeyID(requesterDID, gomock.Any()).MinTimes(1).Return(requesterSigningKeyID.String(), nil)
+ ctx.keyResolver.EXPECT().ResolveKey(requesterDID, nil, types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKeyID, requesterSigningKey, nil)
ctx.keyStore.EXPECT().SignJWT(gomock.Any(), gomock.Any(), nil, requesterSigningKeyID.String()).Return("token", nil)
validRequest := request
@@ -229,7 +229,7 @@ func TestService_CreateJwtBearerToken(t *testing.T) {
ctx.didResolver.EXPECT().Resolve(authorizerDID, gomock.Any()).Return(authorizerDIDDocument, nil, nil).AnyTimes()
ctx.serviceResolver.EXPECT().GetCompoundServiceEndpoint(authorizerDID, expectedService, services.OAuthEndpointType, true).Return(expectedAudience, nil)
- ctx.keyResolver.EXPECT().ResolveSigningKeyID(requesterDID, gomock.Any()).MinTimes(1).Return(requesterSigningKeyID.String(), nil)
+ ctx.keyResolver.EXPECT().ResolveKey(requesterDID, nil, types.NutsSigningKeyType).MinTimes(1).Return(requesterSigningKeyID, requesterSigningKey, nil)
ctx.keyStore.EXPECT().SignJWT(gomock.Any(), gomock.Any(), nil, requesterSigningKeyID.String()).Return("", errors.New("boom!"))
token, err := ctx.relyingParty.CreateJwtGrant(ctx.audit, request)
diff --git a/crypto/api/v1/api.go b/crypto/api/v1/api.go
index 0b8cdaf635..e01a5ab97a 100644
--- a/crypto/api/v1/api.go
+++ b/crypto/api/v1/api.go
@@ -195,18 +195,14 @@ func (w *Wrapper) resolvePublicKey(id *did.DID) (key crypt.PublicKey, keyID ssi.
if id.IsURL() {
// Assume it is a keyId
now := time.Now()
- key, err = w.K.ResolveRelationKey(id.String(), &now, types.KeyAgreement)
+ key, err = w.K.ResolveKeyByID(id.String(), &now, types.KeyAgreement)
if err != nil {
return nil, ssi.URI{}, err
}
keyID = id.URI()
} else {
// Assume it is a DID
- key, err = w.K.ResolveKeyAgreementKey(*id)
- if err != nil {
- return nil, ssi.URI{}, err
- }
- keyID, err = w.K.ResolveRelationKeyID(*id, types.KeyAgreement)
+ keyID, key, err = w.K.ResolveKey(*id, nil, types.KeyAgreement)
if err != nil {
return nil, ssi.URI{}, err
}
diff --git a/crypto/api/v1/api_test.go b/crypto/api/v1/api_test.go
index 7af59456b2..82ddd24462 100644
--- a/crypto/api/v1/api_test.go
+++ b/crypto/api/v1/api_test.go
@@ -244,7 +244,7 @@ func TestWrapper_EncryptJwe(t *testing.T) {
assert.Equal(t, err.(core.HTTPStatusCodeError).StatusCode(), http.StatusBadRequest)
assert.Empty(t, jwe)
})
- t.Run("ResolveKeyAgreementKey fails, returns 400", func(t *testing.T) {
+ t.Run("ResolveKey fails, returns 400", func(t *testing.T) {
ctx := newMockContext(t)
headers := map[string]interface{}{"typ": "JWE"}
request := EncryptJweRequest{
@@ -252,14 +252,14 @@ func TestWrapper_EncryptJwe(t *testing.T) {
Payload: payload,
Headers: headers,
}
- ctx.keyResolver.EXPECT().ResolveKeyAgreementKey(gomock.Any()).Return(nil, errors.New("FAIL"))
+ ctx.keyResolver.EXPECT().ResolveKey(gomock.Any(), nil, types.KeyAgreement).Return(ssi.URI{}, nil, errors.New("FAIL"))
jwe, err := ctx.client.EncryptJwe(nil, EncryptJweRequestObject{Body: &request})
assert.EqualError(t, err, "invalid receiver: FAIL")
assert.Equal(t, err.(core.HTTPStatusCodeError).StatusCode(), http.StatusBadRequest)
assert.Empty(t, jwe)
})
- t.Run("ResolveRelationKeyID fails, returns 400", func(t *testing.T) {
+ t.Run("ResolveKey fails, returns 400", func(t *testing.T) {
ctx := newMockContext(t)
headers := map[string]interface{}{"typ": "JWE"}
request := EncryptJweRequest{
@@ -267,15 +267,14 @@ func TestWrapper_EncryptJwe(t *testing.T) {
Payload: payload,
Headers: headers,
}
- ctx.keyResolver.EXPECT().ResolveKeyAgreementKey(gomock.Any())
- ctx.keyResolver.EXPECT().ResolveRelationKeyID(gomock.Any(), types.KeyAgreement).Return(ssi.URI{}, errors.New("FAIL"))
+ ctx.keyResolver.EXPECT().ResolveKey(gomock.Any(), nil, types.KeyAgreement).Return(ssi.URI{}, nil, errors.New("FAIL"))
jwe, err := ctx.client.EncryptJwe(nil, EncryptJweRequestObject{Body: &request})
assert.EqualError(t, err, "invalid receiver: FAIL")
assert.Equal(t, err.(core.HTTPStatusCodeError).StatusCode(), http.StatusBadRequest)
assert.Empty(t, jwe)
})
- t.Run("ResolveRelationKey fails, returns 400", func(t *testing.T) {
+ t.Run("ResolveKeyByID fails, returns 400", func(t *testing.T) {
ctx := newMockContext(t)
headers := map[string]interface{}{"typ": "JWE"}
request := EncryptJweRequest{
@@ -283,14 +282,14 @@ func TestWrapper_EncryptJwe(t *testing.T) {
Payload: payload,
Headers: headers,
}
- ctx.keyResolver.EXPECT().ResolveRelationKey(gomock.Any(), gomock.Any(), types.KeyAgreement).Return(ssi.URI{}, errors.New("FAIL"))
+ ctx.keyResolver.EXPECT().ResolveKeyByID(gomock.Any(), gomock.Any(), types.KeyAgreement).Return(ssi.URI{}, errors.New("FAIL"))
jwe, err := ctx.client.EncryptJwe(nil, EncryptJweRequestObject{Body: &request})
assert.EqualError(t, err, "invalid receiver: FAIL")
assert.Equal(t, err.(core.HTTPStatusCodeError).StatusCode(), http.StatusBadRequest)
assert.Empty(t, jwe)
})
- t.Run("ResolveKeyAgreementKey not found, returns 400", func(t *testing.T) {
+ t.Run("KeyAgreement key not found, returns 400", func(t *testing.T) {
ctx := newMockContext(t)
headers := map[string]interface{}{"typ": "JWE"}
request := EncryptJweRequest{
@@ -298,14 +297,14 @@ func TestWrapper_EncryptJwe(t *testing.T) {
Payload: payload,
Headers: headers,
}
- ctx.keyResolver.EXPECT().ResolveKeyAgreementKey(gomock.Any()).Return(nil, types.ErrNotFound)
+ ctx.keyResolver.EXPECT().ResolveKey(gomock.Any(), nil, types.KeyAgreement).Return(ssi.URI{}, nil, types.ErrNotFound)
jwe, err := ctx.client.EncryptJwe(nil, EncryptJweRequestObject{Body: &request})
assert.EqualError(t, err, "unable to locate receiver did:nuts:12345: unable to find the DID document")
assert.Equal(t, err.(core.HTTPStatusCodeError).StatusCode(), http.StatusBadRequest)
assert.Empty(t, jwe)
})
- t.Run("ResolveRelationKeyID not found, returns 400", func(t *testing.T) {
+ t.Run("Key not found, returns 400", func(t *testing.T) {
ctx := newMockContext(t)
headers := map[string]interface{}{"typ": "JWE"}
request := EncryptJweRequest{
@@ -313,15 +312,14 @@ func TestWrapper_EncryptJwe(t *testing.T) {
Payload: payload,
Headers: headers,
}
- ctx.keyResolver.EXPECT().ResolveKeyAgreementKey(gomock.Any())
- ctx.keyResolver.EXPECT().ResolveRelationKeyID(gomock.Any(), types.KeyAgreement).Return(ssi.URI{}, types.ErrNotFound)
+ ctx.keyResolver.EXPECT().ResolveKey(gomock.Any(), nil, types.KeyAgreement).Return(ssi.URI{}, nil, types.ErrNotFound)
jwe, err := ctx.client.EncryptJwe(nil, EncryptJweRequestObject{Body: &request})
assert.EqualError(t, err, "unable to locate receiver did:nuts:12345: unable to find the DID document")
assert.Equal(t, err.(core.HTTPStatusCodeError).StatusCode(), http.StatusBadRequest)
assert.Empty(t, jwe)
})
- t.Run("ResolveRelationKey not found, returns 400", func(t *testing.T) {
+ t.Run("KeyAgreement key not found, returns 400", func(t *testing.T) {
ctx := newMockContext(t)
headers := map[string]interface{}{"typ": "JWE"}
request := EncryptJweRequest{
@@ -329,7 +327,7 @@ func TestWrapper_EncryptJwe(t *testing.T) {
Payload: payload,
Headers: headers,
}
- ctx.keyResolver.EXPECT().ResolveRelationKey(gomock.Any(), gomock.Any(), types.KeyAgreement).Return(ssi.URI{}, types.ErrNotFound)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(gomock.Any(), gomock.Any(), types.KeyAgreement).Return(ssi.URI{}, types.ErrNotFound)
jwe, err := ctx.client.EncryptJwe(nil, EncryptJweRequestObject{Body: &request})
assert.EqualError(t, err, "unable to locate receiver did:nuts:12345#key-1: unable to find the DID document")
@@ -360,9 +358,8 @@ func TestWrapper_EncryptJwe(t *testing.T) {
}
did, _ := ssi.ParseURI("did:nuts:12345")
ctx.keyStore.EXPECT().EncryptJWE(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return("", errors.New("b00m!"))
- ctx.keyResolver.EXPECT().ResolveKeyAgreementKey(gomock.Any())
- ctx.keyResolver.EXPECT().ResolveRelationKeyID(gomock.Any(), types.KeyAgreement).Return(*did, nil)
+ ctx.keyResolver.EXPECT().ResolveKey(gomock.Any(), nil, types.KeyAgreement).Return(*did, nil, nil)
jwe, err := ctx.client.EncryptJwe(audit.TestContext(), EncryptJweRequestObject{Body: &request})
@@ -380,8 +377,7 @@ func TestWrapper_EncryptJwe(t *testing.T) {
Payload: payload,
}
ctx.keyStore.EXPECT().EncryptJWE(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return("jwe", nil)
- ctx.keyResolver.EXPECT().ResolveKeyAgreementKey(gomock.Any())
- ctx.keyResolver.EXPECT().ResolveRelationKeyID(gomock.Any(), types.KeyAgreement).Return(*did, nil)
+ ctx.keyResolver.EXPECT().ResolveKey(gomock.Any(), nil, types.KeyAgreement).Return(*did, nil, nil)
resp, err := ctx.client.EncryptJwe(nil, EncryptJweRequestObject{Body: &request})
@@ -399,7 +395,7 @@ func TestWrapper_EncryptJwe(t *testing.T) {
Payload: payload,
}
ctx.keyStore.EXPECT().EncryptJWE(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return("jwe", nil)
- ctx.keyResolver.EXPECT().ResolveRelationKey(gomock.Any(), gomock.Any(), types.KeyAgreement).Return(*did, nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(gomock.Any(), gomock.Any(), types.KeyAgreement).Return(*did, nil)
resp, err := ctx.client.EncryptJwe(nil, EncryptJweRequestObject{Body: &request})
@@ -417,8 +413,7 @@ func TestWrapper_EncryptJwe(t *testing.T) {
}
did, _ := ssi.ParseURI(kid)
ctx.keyStore.EXPECT().EncryptJWE(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return("jwe", nil)
- ctx.keyResolver.EXPECT().ResolveKeyAgreementKey(gomock.Any())
- ctx.keyResolver.EXPECT().ResolveRelationKeyID(gomock.Any(), types.KeyAgreement).Return(*did, nil)
+ ctx.keyResolver.EXPECT().ResolveKey(gomock.Any(), nil, types.KeyAgreement).Return(*did, nil, nil)
resp, err := ctx.client.EncryptJwe(nil, EncryptJweRequestObject{Body: &request})
@@ -434,8 +429,7 @@ func TestWrapper_EncryptJwe(t *testing.T) {
Receiver: did.String(),
}
ctx.keyStore.EXPECT().EncryptJWE(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return("jwe", nil)
- ctx.keyResolver.EXPECT().ResolveKeyAgreementKey(gomock.Any())
- ctx.keyResolver.EXPECT().ResolveRelationKeyID(gomock.Any(), types.KeyAgreement).Return(*did, nil)
+ ctx.keyResolver.EXPECT().ResolveKey(gomock.Any(), nil, types.KeyAgreement).Return(*did, nil, nil)
resp, err := ctx.client.EncryptJwe(nil, EncryptJweRequestObject{Body: &request})
diff --git a/network/dag/pal.go b/network/dag/pal.go
index 59d058b7a8..750d3cef6e 100644
--- a/network/dag/pal.go
+++ b/network/dag/pal.go
@@ -58,7 +58,7 @@ func (pal PAL) Encrypt(keyResolver types.KeyResolver) (EncryptedPAL, error) {
var recipients [][]byte
for _, recipient := range pal {
recipients = append(recipients, []byte(recipient.String()))
- rawKak, err := keyResolver.ResolveKeyAgreementKey(recipient)
+ _, rawKak, err := keyResolver.ResolveKey(recipient, nil, types.KeyAgreement)
if err != nil {
return nil, fmt.Errorf("unable to resolve keyAgreement key (recipient=%s): %w", recipient, err)
}
diff --git a/network/dag/pal_test.go b/network/dag/pal_test.go
index b6df7d7927..c5e78c3a0c 100644
--- a/network/dag/pal_test.go
+++ b/network/dag/pal_test.go
@@ -24,6 +24,7 @@ import (
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
+ ssi "github.com/nuts-foundation/go-did"
"github.com/stretchr/testify/require"
"testing"
@@ -46,8 +47,8 @@ func TestEncryptPal(t *testing.T) {
// Encrypt
ctrl := gomock.NewController(t)
keyResolver := types.NewMockKeyResolver(ctrl)
- keyResolver.EXPECT().ResolveKeyAgreementKey(*pA).Return(pkA.Public(), nil)
- keyResolver.EXPECT().ResolveKeyAgreementKey(*pB).Return(pkB.Public(), nil)
+ keyResolver.EXPECT().ResolveKey(*pA, nil, types.KeyAgreement).Return(ssi.URI{}, pkA.Public(), nil)
+ keyResolver.EXPECT().ResolveKey(*pB, nil, types.KeyAgreement).Return(ssi.URI{}, pkB.Public(), nil)
expected := PAL{*pA, *pB}
pal, err := expected.Encrypt(keyResolver)
require.NoError(t, err)
@@ -70,7 +71,7 @@ func TestEncryptPal(t *testing.T) {
t.Run("error - keyAgreement key type is not supported", func(t *testing.T) {
ctrl := gomock.NewController(t)
keyResolver := types.NewMockKeyResolver(ctrl)
- keyResolver.EXPECT().ResolveKeyAgreementKey(*pA).Return(&rsa.PublicKey{}, nil)
+ keyResolver.EXPECT().ResolveKey(*pA, nil, types.KeyAgreement).Return(ssi.URI{}, &rsa.PublicKey{}, nil)
pal, err := PAL{*pA}.Encrypt(keyResolver)
assert.Nil(t, pal)
assert.EqualError(t, err, "resolved keyAgreement key is not an elliptic curve key (recipient=did:nuts:A)")
@@ -78,7 +79,7 @@ func TestEncryptPal(t *testing.T) {
t.Run("error - no keyAgreements", func(t *testing.T) {
ctrl := gomock.NewController(t)
keyResolver := types.NewMockKeyResolver(ctrl)
- keyResolver.EXPECT().ResolveKeyAgreementKey(*pA).Return(nil, types.ErrKeyNotFound)
+ keyResolver.EXPECT().ResolveKey(*pA, nil, types.KeyAgreement).Return(ssi.URI{}, nil, types.ErrKeyNotFound)
pal, err := PAL{*pA}.Encrypt(keyResolver)
assert.Nil(t, pal)
assert.EqualError(t, err, "unable to resolve keyAgreement key (recipient=did:nuts:A): key not found in DID document")
diff --git a/network/dag/verifier_test.go b/network/dag/verifier_test.go
index 2f5a786568..8b3ba0e28d 100644
--- a/network/dag/verifier_test.go
+++ b/network/dag/verifier_test.go
@@ -30,8 +30,6 @@ import (
"time"
"github.com/lestrrat-go/jwx/jwk"
- ssi "github.com/nuts-foundation/go-did"
- "github.com/nuts-foundation/go-did/did"
"github.com/nuts-foundation/go-stoabs"
nutsCrypto "github.com/nuts-foundation/nuts-node/crypto"
"github.com/nuts-foundation/nuts-node/crypto/hash"
@@ -126,7 +124,7 @@ func TestTransactionSignatureVerifier(t *testing.T) {
t.Run("unable to resolve key by hash", func(t *testing.T) {
d := CreateSignedTestTransaction(1, time.Now(), nil, "foo/bar", false)
ctrl := gomock.NewController(t)
- keyResolver := types.NewMockKeyResolver(ctrl)
+ keyResolver := types.NewMockNutsKeyResolver(ctrl)
keyResolver.EXPECT().ResolvePublicKey(gomock.Any(), gomock.Any()).Return(nil, errors.New("failed"))
err := NewTransactionSignatureVerifier(keyResolver)(nil, d)
@@ -135,35 +133,12 @@ func TestTransactionSignatureVerifier(t *testing.T) {
})
}
-var _ types.KeyResolver = &staticKeyResolver{}
var _ types.NutsKeyResolver = &staticKeyResolver{}
type staticKeyResolver struct {
Key crypto.PublicKey
}
-func (s staticKeyResolver) ResolveKeyAgreementKey(_ did.DID) (crypto.PublicKey, error) {
- return s.Key, nil
-}
-
func (s staticKeyResolver) ResolvePublicKey(_ string, _ []hash.SHA256Hash) (crypto.PublicKey, error) {
return s.Key, nil
}
-
-func (s staticKeyResolver) ResolveSigningKeyID(_ did.DID, _ *time.Time) (string, error) {
- panic("implement me")
-}
-
-func (s staticKeyResolver) ResolveSigningKey(_ string, _ *time.Time) (crypto.PublicKey, error) {
- panic("implement me")
-}
-func (s staticKeyResolver) ResolveRelationKey(_ string, _ *time.Time, _ types.RelationType) (crypto.PublicKey, error) {
- panic("implement me")
-}
-
-func (s staticKeyResolver) ResolveAssertionKeyID(_ did.DID) (ssi.URI, error) {
- panic("implement me")
-}
-func (s staticKeyResolver) ResolveRelationKeyID(_ did.DID, _ types.RelationType) (ssi.URI, error) {
- panic("implement me")
-}
diff --git a/network/network_test.go b/network/network_test.go
index a7621fed95..cfa478b66c 100644
--- a/network/network_test.go
+++ b/network/network_test.go
@@ -27,6 +27,7 @@ import (
"crypto/x509"
"errors"
"fmt"
+ ssi "github.com/nuts-foundation/go-did"
testPKI "github.com/nuts-foundation/nuts-node/test/pki"
"github.com/nuts-foundation/nuts-node/vdr/didservice"
"github.com/nuts-foundation/nuts-node/vdr/didstore"
@@ -463,8 +464,8 @@ func TestNetwork_CreateTransaction(t *testing.T) {
cxt.state.EXPECT().Head(gomock.Any())
cxt.state.EXPECT().Add(gomock.Any(), gomock.Any(), payload)
- cxt.keyResolver.EXPECT().ResolveKeyAgreementKey(*sender).Return(senderKey.Public(), nil)
- cxt.keyResolver.EXPECT().ResolveKeyAgreementKey(*receiver).Return(receiverKey.Public(), nil)
+ cxt.keyResolver.EXPECT().ResolveKey(*sender, nil, vdrTypes.KeyAgreement).Return(ssi.MustParseURI("sender"), senderKey.Public(), nil)
+ cxt.keyResolver.EXPECT().ResolveKey(*receiver, nil, vdrTypes.KeyAgreement).Return(ssi.MustParseURI("receiver"), receiverKey.Public(), nil)
_, err = cxt.network.CreateTransaction(ctx, TransactionTemplate(payloadType, payload, key).WithPrivate([]did.DID{*sender, *receiver}))
assert.NoError(t, err)
diff --git a/vcr/ambassador_test.go b/vcr/ambassador_test.go
index 206888a40d..31127ff96d 100644
--- a/vcr/ambassador_test.go
+++ b/vcr/ambassador_test.go
@@ -25,6 +25,7 @@ import (
"errors"
"fmt"
"github.com/nuts-foundation/nuts-node/audit"
+ types2 "github.com/nuts-foundation/nuts-node/vdr/types"
"github.com/piprate/json-gold/ld"
"github.com/stretchr/testify/require"
"net/http"
@@ -113,12 +114,12 @@ func TestAmbassador_handleReprocessEvent(t *testing.T) {
signer, _ := util.PemToPrivateKey(pem)
key := crypto.NewTestKey(fmt.Sprintf("%s#1", vc.Issuer.String()))
- // trust otherwise Resolve wont work
+ // trust otherwise Resolve won't work
ctx.vcr.Trust(vc.Type[0], vc.Issuer)
ctx.vcr.Trust(vc.Type[1], vc.Issuer)
// mocks
- ctx.keyResolver.EXPECT().ResolveSigningKey(gomock.Any(), gomock.Any()).Return(signer.Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(gomock.Any(), gomock.Any(), types2.NutsSigningKeyType).Return(signer.Public(), nil)
// Publish a VC
payload, _ := json.Marshal(vc)
diff --git a/vcr/holder/holder.go b/vcr/holder/holder.go
index 6af96e9439..c19a2690a9 100644
--- a/vcr/holder/holder.go
+++ b/vcr/holder/holder.go
@@ -62,7 +62,7 @@ func (h vcHolder) BuildVP(ctx context.Context, credentials []vc.VerifiableCreden
}
}
- kid, err := h.keyResolver.ResolveAssertionKeyID(*signerDID)
+ kid, _, err := h.keyResolver.ResolveKey(*signerDID, nil, vdr.NutsSigningKeyType)
if err != nil {
return nil, fmt.Errorf("unable to resolve assertion key for signing VP (did=%s): %w", *signerDID, err)
}
diff --git a/vcr/holder/holder_test.go b/vcr/holder/holder_test.go
index cc5b0c9dd7..68d860f9e0 100644
--- a/vcr/holder/holder_test.go
+++ b/vcr/holder/holder_test.go
@@ -63,7 +63,7 @@ func TestHolder_BuildVP(t *testing.T) {
"proof": {
"created": "2021-12-24T13:21:29.087205+01:00",
"jws": "eyJhbGciOiJFUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..hPM2GLc1K9d2D8Sbve004x9SumjLqaXTjWhUhvqWRwxfRWlwfp5gHDUYuRoEjhCXfLt-_u-knChVmK980N3LBw",
- "proofPurpose": "assertionMethod",
+ "proofPurpose": "NutsSigningKeyType",
"type": "JsonWebSignature2020",
"verificationMethod": "` + kid + `"
},
@@ -90,7 +90,7 @@ func TestHolder_BuildVP(t *testing.T) {
keyResolver := types.NewMockKeyResolver(ctrl)
- keyResolver.EXPECT().ResolveAssertionKeyID(testDID).Return(ssi.MustParseURI(kid), nil)
+ keyResolver.EXPECT().ResolveKey(testDID, nil, types.NutsSigningKeyType).Return(ssi.MustParseURI(kid), key.Public(), nil)
holder := New(keyResolver, keyStore, nil, jsonldManager)
@@ -111,7 +111,7 @@ func TestHolder_BuildVP(t *testing.T) {
}
keyResolver := types.NewMockKeyResolver(ctrl)
- keyResolver.EXPECT().ResolveAssertionKeyID(testDID).Return(ssi.MustParseURI(kid), nil)
+ keyResolver.EXPECT().ResolveKey(testDID, nil, types.NutsSigningKeyType).Return(ssi.MustParseURI(kid), key.Public(), nil)
holder := New(keyResolver, keyStore, nil, jsonldManager)
@@ -130,7 +130,7 @@ func TestHolder_BuildVP(t *testing.T) {
keyResolver := types.NewMockKeyResolver(ctrl)
- keyResolver.EXPECT().ResolveAssertionKeyID(testDID).Return(vdr.TestMethodDIDA.URI(), nil)
+ keyResolver.EXPECT().ResolveKey(testDID, nil, types.NutsSigningKeyType).Return(vdr.TestMethodDIDA.URI(), key.Public(), nil)
holder := New(keyResolver, keyStore, nil, jsonldManager)
@@ -150,7 +150,7 @@ func TestHolder_BuildVP(t *testing.T) {
mockVerifier := verifier.NewMockVerifier(ctrl)
mockVerifier.EXPECT().Validate(testCredential, &created)
- keyResolver.EXPECT().ResolveAssertionKeyID(testDID).Return(ssi.MustParseURI(kid), nil)
+ keyResolver.EXPECT().ResolveKey(testDID, nil, types.NutsSigningKeyType).Return(ssi.MustParseURI(kid), key.Public(), nil)
holder := New(keyResolver, keyStore, mockVerifier, jsonldManager)
@@ -166,7 +166,7 @@ func TestHolder_BuildVP(t *testing.T) {
mockVerifier := verifier.NewMockVerifier(ctrl)
mockVerifier.EXPECT().Validate(testCredential, &created).Return(errors.New("failed"))
- keyResolver.EXPECT().ResolveAssertionKeyID(testDID).Return(ssi.MustParseURI(kid), nil)
+ keyResolver.EXPECT().ResolveKey(testDID, nil, types.NutsSigningKeyType).Return(ssi.MustParseURI(kid), key.Public(), nil)
holder := New(keyResolver, keyStore, mockVerifier, jsonldManager)
@@ -184,7 +184,7 @@ func TestHolder_BuildVP(t *testing.T) {
keyResolver := types.NewMockKeyResolver(ctrl)
- keyResolver.EXPECT().ResolveAssertionKeyID(testDID).Return(ssi.MustParseURI(kid), nil)
+ keyResolver.EXPECT().ResolveKey(testDID, nil, types.NutsSigningKeyType).Return(ssi.MustParseURI(kid), key.Public(), nil)
holder := New(keyResolver, keyStore, nil, jsonldManager)
diff --git a/vcr/holder/openid.go b/vcr/holder/openid.go
index 9d3e78ed18..c2a9b53db5 100644
--- a/vcr/holder/openid.go
+++ b/vcr/holder/openid.go
@@ -193,10 +193,10 @@ func getPreAuthorizedCodeFromOffer(offer openid4vci.CredentialOffer) string {
}
func (h *openidHandler) retrieveCredential(ctx context.Context, issuerClient openid4vci.IssuerAPIClient, offer *openid4vci.CredentialDefinition, tokenResponse *openid4vci.TokenResponse) (*vc.VerifiableCredential, error) {
- keyID, err := h.resolver.ResolveSigningKeyID(h.did, nil)
+ keyID, _, err := h.resolver.ResolveKey(h.did, nil, vdr.NutsSigningKeyType)
headers := map[string]interface{}{
"typ": openid4vci.JWTTypeOpenID4VCIProof, // MUST be openid4vci-proof+jwt, which explicitly types the proof JWT as recommended in Section 3.11 of [RFC8725].
- "kid": keyID, // JOSE Header containing the key ID. If the Credential shall be bound to a DID, the kid refers to a DID URL which identifies a particular key in the DID Document that the Credential shall be bound to.
+ "kid": keyID.String(), // JOSE Header containing the key ID. If the Credential shall be bound to a DID, the kid refers to a DID URL which identifies a particular key in the DID Document that the Credential shall be bound to.
}
claims := map[string]interface{}{
"aud": issuerClient.Metadata().CredentialIssuer,
@@ -204,7 +204,7 @@ func (h *openidHandler) retrieveCredential(ctx context.Context, issuerClient ope
"nonce": tokenResponse.CNonce,
}
- proof, err := h.signer.SignJWT(ctx, claims, headers, keyID)
+ proof, err := h.signer.SignJWT(ctx, claims, headers, keyID.String())
if err != nil {
return nil, fmt.Errorf("unable to sign request proof: %w", err)
}
diff --git a/vcr/holder/openid_test.go b/vcr/holder/openid_test.go
index e6484aa36b..fdd4818bb4 100644
--- a/vcr/holder/openid_test.go
+++ b/vcr/holder/openid_test.go
@@ -98,7 +98,7 @@ func Test_wallet_HandleCredentialOffer(t *testing.T) {
"nonce": nonce,
}, gomock.Any(), "key-id").Return("signed-jwt", nil)
keyResolver := vdrTypes.NewMockKeyResolver(ctrl)
- keyResolver.EXPECT().ResolveSigningKeyID(holderDID, nil).Return("key-id", nil)
+ keyResolver.EXPECT().ResolveKey(holderDID, nil, vdrTypes.NutsSigningKeyType).Return(ssi.MustParseURI("key-id"), nil, nil)
nowFunc = func() time.Time {
return time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
@@ -238,7 +238,7 @@ func Test_wallet_HandleCredentialOffer(t *testing.T) {
jwtSigner := crypto.NewMockJWTSigner(ctrl)
jwtSigner.EXPECT().SignJWT(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
keyResolver := vdrTypes.NewMockKeyResolver(ctrl)
- keyResolver.EXPECT().ResolveSigningKeyID(holderDID, nil)
+ keyResolver.EXPECT().ResolveKey(holderDID, nil, vdrTypes.NutsSigningKeyType)
w := NewOpenIDHandler(holderDID, "https://holder.example.com", &http.Client{}, nil, jwtSigner, keyResolver).(*openidHandler)
w.issuerClientCreator = func(_ context.Context, _ core.HTTPRequestDoer, _ string) (openid4vci.IssuerAPIClient, error) {
diff --git a/vcr/issuer/issuer.go b/vcr/issuer/issuer.go
index 575eb50a7a..6d1255166c 100644
--- a/vcr/issuer/issuer.go
+++ b/vcr/issuer/issuer.go
@@ -56,7 +56,10 @@ func NewIssuer(store Store, vcrStore types.Writer, networkPublisher Publisher,
openidHandlerFn func(ctx context.Context, id did.DID) (OpenIDHandler, error),
didstore didstore.Store, keyStore crypto.KeyStore, jsonldManager jsonld.JSONLD, trustConfig *trust.Config,
) Issuer {
- resolver := vdrKeyResolver{didResolver: didservice.Resolver{Store: didstore}, keyResolver: keyStore}
+ resolver := vdrKeyResolver{
+ publicKeyResolver: didservice.KeyResolver{Store: didstore},
+ privateKeyResolver: keyStore,
+ }
return &issuer{
store: store,
networkPublisher: networkPublisher,
diff --git a/vcr/issuer/keyresolver.go b/vcr/issuer/keyresolver.go
index 367ce07617..0815519b8a 100644
--- a/vcr/issuer/keyresolver.go
+++ b/vcr/issuer/keyresolver.go
@@ -23,31 +23,23 @@ import (
"fmt"
"github.com/nuts-foundation/go-did/did"
"github.com/nuts-foundation/nuts-node/crypto"
- "github.com/nuts-foundation/nuts-node/vdr/didservice"
vdr "github.com/nuts-foundation/nuts-node/vdr/types"
)
// vdrKeyResolver resolves private keys based upon the VDR document resolver
type vdrKeyResolver struct {
- didResolver vdr.DIDResolver
- keyResolver crypto.KeyResolver
+ publicKeyResolver vdr.KeyResolver
+ privateKeyResolver crypto.KeyResolver
}
// ResolveAssertionKey is a convenience method which tries to find a assertionKey on in the VDR for a given issuerDID.
func (r vdrKeyResolver) ResolveAssertionKey(ctx context.Context, issuerDID did.DID) (crypto.Key, error) {
- // find did document/metadata for originating TXs
- document, _, err := r.didResolver.Resolve(issuerDID, nil)
- if err != nil {
- return nil, err
- }
-
- // resolve an assertionMethod key for issuer
- kid, err := didservice.ExtractFirstRelationKeyIDByType(*document, vdr.AssertionMethod)
+ kid, _, err := r.publicKeyResolver.ResolveKey(issuerDID, nil, vdr.AssertionMethod)
if err != nil {
return nil, fmt.Errorf("invalid issuer: %w", err)
}
- key, err := r.keyResolver.Resolve(ctx, kid.String())
+ key, err := r.privateKeyResolver.Resolve(ctx, kid.String())
if err != nil {
return nil, fmt.Errorf("failed to resolve assertionKey: could not resolve key from keyStore: %w", err)
}
diff --git a/vcr/issuer/keyresolver_test.go b/vcr/issuer/keyresolver_test.go
index a108344dba..8c746dc7a5 100644
--- a/vcr/issuer/keyresolver_test.go
+++ b/vcr/issuer/keyresolver_test.go
@@ -36,21 +36,22 @@ func Test_vdrKeyResolver_ResolveAssertionKey(t *testing.T) {
issuerDID, _ := did.ParseDID("did:nuts:123")
methodID := *issuerDID
methodID.Fragment = "abc"
- newMethod, err := did.NewVerificationMethod(methodID, ssi.JsonWebKey2020, *issuerDID, crypto.NewTestKey(issuerDID.String()+"abc").Public())
+ publicKey := crypto.NewTestKey(issuerDID.String() + "abc").Public()
+ newMethod, err := did.NewVerificationMethod(methodID, ssi.JsonWebKey2020, *issuerDID, publicKey)
require.NoError(t, err)
docWithAssertionKey := &did.Document{}
docWithAssertionKey.AddAssertionMethod(newMethod)
t.Run("ok", func(t *testing.T) {
ctrl := gomock.NewController(t)
- mockDockResolver := types.NewMockDIDResolver(ctrl)
- mockDockResolver.EXPECT().Resolve(*issuerDID, nil).Return(docWithAssertionKey, &types.DocumentMetadata{}, nil)
- mockKeyResolver := crypto.NewMockKeyResolver(ctrl)
- mockKeyResolver.EXPECT().Resolve(ctx, methodID.String()).Return(crypto.NewTestKey(methodID.String()), nil)
+ mockPubKeyResolver := types.NewMockKeyResolver(ctrl)
+ mockPubKeyResolver.EXPECT().ResolveKey(*issuerDID, nil, types.NutsSigningKeyType).Return(methodID.URI(), publicKey, nil)
+ mockPrivKeyResolver := crypto.NewMockKeyResolver(ctrl)
+ mockPrivKeyResolver.EXPECT().Resolve(ctx, methodID.String()).Return(crypto.NewTestKey(methodID.String()), nil)
sut := vdrKeyResolver{
- didResolver: mockDockResolver,
- keyResolver: mockKeyResolver,
+ publicKeyResolver: mockPubKeyResolver,
+ privateKeyResolver: mockPrivKeyResolver,
}
key, err := sut.ResolveAssertionKey(ctx, *issuerDID)
@@ -62,52 +63,35 @@ func Test_vdrKeyResolver_ResolveAssertionKey(t *testing.T) {
t.Run("document for issuer not found in vdr", func(t *testing.T) {
ctrl := gomock.NewController(t)
- mockDockResolver := types.NewMockDIDResolver(ctrl)
- mockDockResolver.EXPECT().Resolve(*issuerDID, nil).Return(nil, nil, errors.New("not found"))
- mockKeyResolver := crypto.NewMockKeyResolver(ctrl)
+ mockPubKeyResolver := types.NewMockKeyResolver(ctrl)
+ mockPubKeyResolver.EXPECT().ResolveKey(*issuerDID, nil, types.NutsSigningKeyType).Return(ssi.URI{}, nil, errors.New("not found"))
+ mockPrivKeyResolver := crypto.NewMockKeyResolver(ctrl)
sut := vdrKeyResolver{
- didResolver: mockDockResolver,
- keyResolver: mockKeyResolver,
+ publicKeyResolver: mockPubKeyResolver,
+ privateKeyResolver: mockPrivKeyResolver,
}
key, err := sut.ResolveAssertionKey(ctx, *issuerDID)
assert.Nil(t, key)
- assert.EqualError(t, err, "not found")
+ assert.EqualError(t, err, "invalid issuer: not found")
})
t.Run("key not found in crypto", func(t *testing.T) {
ctrl := gomock.NewController(t)
- mockDockResolver := types.NewMockDIDResolver(ctrl)
- mockDockResolver.EXPECT().Resolve(*issuerDID, nil).Return(docWithAssertionKey, &types.DocumentMetadata{}, nil)
- mockKeyResolver := crypto.NewMockKeyResolver(ctrl)
- mockKeyResolver.EXPECT().Resolve(ctx, methodID.String()).Return(nil, errors.New("not found"))
+ mockPubKeyResolver := types.NewMockKeyResolver(ctrl)
+ mockPubKeyResolver.EXPECT().ResolveKey(*issuerDID, nil, types.NutsSigningKeyType).Return(methodID.URI(), publicKey, nil)
+ mockPrivKeyResolver := crypto.NewMockKeyResolver(ctrl)
+ mockPrivKeyResolver.EXPECT().Resolve(ctx, methodID.String()).Return(nil, errors.New("not found"))
sut := vdrKeyResolver{
- didResolver: mockDockResolver,
- keyResolver: mockKeyResolver,
+ publicKeyResolver: mockPubKeyResolver,
+ privateKeyResolver: mockPrivKeyResolver,
}
key, err := sut.ResolveAssertionKey(ctx, *issuerDID)
assert.Nil(t, key)
assert.EqualError(t, err, "failed to resolve assertionKey: could not resolve key from keyStore: not found")
})
-
- t.Run("did document has no assertionKey", func(t *testing.T) {
- ctrl := gomock.NewController(t)
- mockDockResolver := types.NewMockDIDResolver(ctrl)
- mockDockResolver.EXPECT().Resolve(*issuerDID, nil).Return(&did.Document{}, &types.DocumentMetadata{}, nil)
- mockKeyResolver := crypto.NewMockKeyResolver(ctrl)
-
- sut := vdrKeyResolver{
- didResolver: mockDockResolver,
- keyResolver: mockKeyResolver,
- }
-
- key, err := sut.ResolveAssertionKey(ctx, *issuerDID)
- assert.Nil(t, key)
- assert.EqualError(t, err, "invalid issuer: key not found in DID document")
- })
-
}
diff --git a/vcr/issuer/network_publisher.go b/vcr/issuer/network_publisher.go
index abfa53e24d..1432067831 100644
--- a/vcr/issuer/network_publisher.go
+++ b/vcr/issuer/network_publisher.go
@@ -52,8 +52,8 @@ func NewNetworkPublisher(networkTx network.Transactions, store didstore.Store, k
didResolver: didResolver,
serviceResolver: didservice.ServiceResolver{Store: store},
keyResolver: vdrKeyResolver{
- didResolver: didResolver,
- keyResolver: keyResolver,
+ publicKeyResolver: didservice.KeyResolver{Store: store},
+ privateKeyResolver: keyResolver,
},
}
diff --git a/vcr/issuer/openid.go b/vcr/issuer/openid.go
index e1d214e4c3..d40ae134f6 100644
--- a/vcr/issuer/openid.go
+++ b/vcr/issuer/openid.go
@@ -321,7 +321,7 @@ func (i *openidHandler) validateProof(ctx context.Context, flow *Flow, request o
var signingKeyID string
token, err := crypto.ParseJWT(request.Proof.Jwt, func(kid string) (crypt.PublicKey, error) {
signingKeyID = kid
- return i.keyResolver.ResolveSigningKey(kid, nil)
+ return i.keyResolver.ResolveKeyByID(kid, nil, types.NutsSigningKeyType)
}, jwt.WithAcceptableSkew(5*time.Second))
if err != nil {
return generateProofError(openid4vci.Error{
diff --git a/vcr/issuer/openid_test.go b/vcr/issuer/openid_test.go
index 37c453ecbc..9805fc59d7 100644
--- a/vcr/issuer/openid_test.go
+++ b/vcr/issuer/openid_test.go
@@ -123,7 +123,7 @@ func Test_memoryIssuer_HandleCredentialRequest(t *testing.T) {
})
ctrl := gomock.NewController(t)
keyResolver := types.NewMockKeyResolver(ctrl)
- keyResolver.EXPECT().ResolveSigningKey(keyID, nil).AnyTimes().Return(signerKey.Public(), nil)
+ keyResolver.EXPECT().ResolveKeyByID(keyID, nil, types.NutsSigningKeyType).AnyTimes().Return(signerKey.Public(), nil)
createHeaders := func() map[string]interface{} {
return map[string]interface{}{
@@ -265,7 +265,7 @@ func Test_memoryIssuer_HandleCredentialRequest(t *testing.T) {
})
t.Run("signing key is unknown", func(t *testing.T) {
keyResolver := types.NewMockKeyResolver(ctrl)
- keyResolver.EXPECT().ResolveSigningKey(keyID, nil).AnyTimes().Return(nil, types.ErrKeyNotFound)
+ keyResolver.EXPECT().ResolveKeyByID(keyID, nil, types.NutsSigningKeyType).AnyTimes().Return(nil, types.ErrKeyNotFound)
service := requireNewTestHandler(t, keyResolver)
_, err := service.createOffer(ctx, issuedVC, preAuthCode)
require.NoError(t, err)
diff --git a/vcr/store_test.go b/vcr/store_test.go
index f984ee8253..bdce82ab0c 100644
--- a/vcr/store_test.go
+++ b/vcr/store_test.go
@@ -24,6 +24,7 @@ import (
"crypto/sha1"
"encoding/json"
"github.com/nuts-foundation/nuts-node/crypto/storage/spi"
+ "github.com/nuts-foundation/nuts-node/vdr/types"
"github.com/stretchr/testify/require"
"os"
"testing"
@@ -50,7 +51,7 @@ func TestVcr_StoreCredential(t *testing.T) {
t.Run("ok", func(t *testing.T) {
ctx := newMockContext(t)
- ctx.keyResolver.EXPECT().ResolveSigningKey(gomock.Any(), nil).Return(pk, nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(gomock.Any(), nil, types.NutsSigningKeyType).Return(pk, nil)
err := ctx.vcr.StoreCredential(target, nil)
@@ -61,7 +62,7 @@ func TestVcr_StoreCredential(t *testing.T) {
ctx := newMockContext(t)
now := time.Now()
- ctx.keyResolver.EXPECT().ResolveSigningKey(gomock.Any(), &now).Return(pk, nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(gomock.Any(), &now, types.NutsSigningKeyType).Return(pk, nil)
err := ctx.vcr.StoreCredential(target, &now)
@@ -72,7 +73,7 @@ func TestVcr_StoreCredential(t *testing.T) {
ctx := newMockContext(t)
now := time.Now()
- ctx.keyResolver.EXPECT().ResolveSigningKey(gomock.Any(), &now).Return(pk, nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(gomock.Any(), &now, types.NutsSigningKeyType).Return(pk, nil)
_ = ctx.vcr.StoreCredential(target, &now)
@@ -85,7 +86,7 @@ func TestVcr_StoreCredential(t *testing.T) {
ctx := newMockContext(t)
now := time.Now()
- ctx.keyResolver.EXPECT().ResolveSigningKey(gomock.Any(), &now).Return(pk, nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(gomock.Any(), &now, types.NutsSigningKeyType).Return(pk, nil)
_ = ctx.vcr.StoreCredential(target, &now)
diff --git a/vcr/verifier/verifier.go b/vcr/verifier/verifier.go
index 095927e5f4..b5201a7fba 100644
--- a/vcr/verifier/verifier.go
+++ b/vcr/verifier/verifier.go
@@ -128,7 +128,7 @@ func (v *verifier) Validate(credentialToVerify vc.VerifiableCredential, at *time
}
// find key
- pk, err := v.keyResolver.ResolveSigningKey(ldProof.VerificationMethod.String(), at)
+ pk, err := v.keyResolver.ResolveKeyByID(ldProof.VerificationMethod.String(), at, vdr.NutsSigningKeyType)
if err != nil {
if at == nil {
return fmt.Errorf("unable to resolve signing key: %w", err)
@@ -239,7 +239,7 @@ func (v *verifier) RegisterRevocation(revocation credential.Revocation) error {
return errors.New("verificationMethod should owned by the issuer")
}
- pk, err := v.keyResolver.ResolveSigningKey(revocation.Proof.VerificationMethod.String(), &revocation.Date)
+ pk, err := v.keyResolver.ResolveKeyByID(revocation.Proof.VerificationMethod.String(), &revocation.Date, vdr.NutsSigningKeyType)
if err != nil {
return fmt.Errorf("unable to resolve key for revocation: %w", err)
}
@@ -283,7 +283,7 @@ func (v verifier) doVerifyVP(vcVerifier Verifier, vp vc.VerifiablePresentation,
}
// Validate signature
- signingKey, err := v.keyResolver.ResolveSigningKey(ldProof.VerificationMethod.String(), validAt)
+ signingKey, err := v.keyResolver.ResolveKeyByID(ldProof.VerificationMethod.String(), validAt, vdr.NutsSigningKeyType)
if err != nil {
return nil, fmt.Errorf("unable to resolve valid signing key: %w", err)
}
diff --git a/vcr/verifier/verifier_test.go b/vcr/verifier/verifier_test.go
index 90322ea306..d1eca06a9a 100644
--- a/vcr/verifier/verifier_test.go
+++ b/vcr/verifier/verifier_test.go
@@ -74,7 +74,7 @@ func Test_verifier_Validate(t *testing.T) {
ctx := newMockContext(t)
instance := ctx.verifier
- ctx.keyResolver.EXPECT().ResolveSigningKey(testKID, gomock.Any()).Return(pk, nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(testKID, gomock.Any(), vdrTypes.NutsSigningKeyType).Return(pk, nil)
err := instance.Validate(testCredential(t), nil)
@@ -123,7 +123,7 @@ func Test_verifier_Validate(t *testing.T) {
vc2 := testCredential(t)
vc2.IssuanceDate = time.Now()
- ctx.keyResolver.EXPECT().ResolveSigningKey(testKID, nil).Return(pk, nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(testKID, nil, vdrTypes.NutsSigningKeyType).Return(pk, nil)
err := instance.Validate(vc2, nil)
@@ -139,7 +139,7 @@ func Test_verifier_Validate(t *testing.T) {
pr[0].Created = time.Now()
vc2.Proof = []interface{}{pr[0]}
- ctx.keyResolver.EXPECT().ResolveSigningKey(testKID, nil).Return(pk, nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(testKID, nil, vdrTypes.NutsSigningKeyType).Return(pk, nil)
err := instance.Validate(vc2, nil)
@@ -159,7 +159,7 @@ func Test_verifier_Validate(t *testing.T) {
t.Run("error - wrong jws in proof", func(t *testing.T) {
ctx := newMockContext(t)
- ctx.keyResolver.EXPECT().ResolveSigningKey(testKID, nil).Return(pk, nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(testKID, nil, vdrTypes.NutsSigningKeyType).Return(pk, nil)
instance := ctx.verifier
vc2 := testCredential(t)
pr := make([]vc.JSONWebSignature2020Proof, 0)
@@ -174,7 +174,7 @@ func Test_verifier_Validate(t *testing.T) {
t.Run("error - wrong base64 encoding in jws", func(t *testing.T) {
ctx := newMockContext(t)
- ctx.keyResolver.EXPECT().ResolveSigningKey(testKID, nil).Return(pk, nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(testKID, nil, vdrTypes.NutsSigningKeyType).Return(pk, nil)
instance := ctx.verifier
vc2 := testCredential(t)
pr := make([]vc.JSONWebSignature2020Proof, 0)
@@ -191,7 +191,7 @@ func Test_verifier_Validate(t *testing.T) {
ctx := newMockContext(t)
instance := ctx.verifier
- ctx.keyResolver.EXPECT().ResolveSigningKey(testKID, nil).Return(nil, errors.New("b00m!"))
+ ctx.keyResolver.EXPECT().ResolveKeyByID(testKID, nil, vdrTypes.NutsSigningKeyType).Return(nil, errors.New("b00m!"))
err := instance.Validate(testCredential(t), nil)
@@ -231,7 +231,7 @@ func TestVerifier_Verify(t *testing.T) {
subject := testCredential(t)
subject.IssuanceDate.Add(-1 * time.Minute)
- ctx.keyResolver.EXPECT().ResolveSigningKey(testKID, gomock.Any()).Return(nil, errors.New("not found"))
+ ctx.keyResolver.EXPECT().ResolveKeyByID(testKID, gomock.Any(), vdrTypes.NutsSigningKeyType).Return(nil, errors.New("not found"))
at := time.Now()
err := instance.Validate(subject, &at)
@@ -250,7 +250,7 @@ func TestVerifier_Verify(t *testing.T) {
ctx.store.EXPECT().GetRevocations(*vc.ID).Return(nil, ErrNotFound)
proofs, _ := vc.Proofs()
ctx.didResolver.EXPECT().Resolve(did.MustParseDID(vc.Issuer.String()), gomock.Any()).Return(nil, nil, nil)
- ctx.keyResolver.EXPECT().ResolveSigningKey(proofs[0].VerificationMethod.String(), nil).Return(nil, vdrTypes.ErrKeyNotFound)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(proofs[0].VerificationMethod.String(), nil, vdrTypes.NutsSigningKeyType).Return(nil, vdrTypes.ErrKeyNotFound)
validationErr := ctx.verifier.Verify(vc, true, true, nil)
@@ -417,7 +417,7 @@ func Test_verifier_CheckAndStoreRevocation(t *testing.T) {
t.Run("it checks and stores a valid revocation", func(t *testing.T) {
sut := newMockContext(t)
- sut.keyResolver.EXPECT().ResolveSigningKey(revocation.Proof.VerificationMethod.String(), &revocation.Date).Return(key, nil)
+ sut.keyResolver.EXPECT().ResolveKeyByID(revocation.Proof.VerificationMethod.String(), &revocation.Date, vdrTypes.NutsSigningKeyType).Return(key, nil)
sut.store.EXPECT().StoreRevocation(revocation)
err := sut.verifier.RegisterRevocation(revocation)
assert.NoError(t, err)
@@ -461,14 +461,14 @@ func Test_verifier_CheckAndStoreRevocation(t *testing.T) {
t.Run("it handles an unknown key error", func(t *testing.T) {
sut := newMockContext(t)
- sut.keyResolver.EXPECT().ResolveSigningKey(revocation.Proof.VerificationMethod.String(), &revocation.Date).Return(nil, errors.New("unknown key"))
+ sut.keyResolver.EXPECT().ResolveKeyByID(revocation.Proof.VerificationMethod.String(), &revocation.Date, vdrTypes.NutsSigningKeyType).Return(nil, errors.New("unknown key"))
err := sut.verifier.RegisterRevocation(revocation)
assert.EqualError(t, err, "unable to resolve key for revocation: unknown key")
})
t.Run("it handles an error from store operation", func(t *testing.T) {
sut := newMockContext(t)
- sut.keyResolver.EXPECT().ResolveSigningKey(revocation.Proof.VerificationMethod.String(), &revocation.Date).Return(key, nil)
+ sut.keyResolver.EXPECT().ResolveKeyByID(revocation.Proof.VerificationMethod.String(), &revocation.Date, vdrTypes.NutsSigningKeyType).Return(key, nil)
sut.store.EXPECT().StoreRevocation(revocation).Return(errors.New("storage error"))
err := sut.verifier.RegisterRevocation(revocation)
assert.EqualError(t, err, "unable to store revocation: storage error")
@@ -477,7 +477,7 @@ func Test_verifier_CheckAndStoreRevocation(t *testing.T) {
t.Run("it handles an invalid signature error", func(t *testing.T) {
sut := newMockContext(t)
otherKey := crypto.NewTestKey("did:nuts:123#abc").Public()
- sut.keyResolver.EXPECT().ResolveSigningKey(revocation.Proof.VerificationMethod.String(), &revocation.Date).Return(otherKey, nil)
+ sut.keyResolver.EXPECT().ResolveKeyByID(revocation.Proof.VerificationMethod.String(), &revocation.Date, vdrTypes.NutsSigningKeyType).Return(otherKey, nil)
err := sut.verifier.RegisterRevocation(revocation)
assert.EqualError(t, err, "unable to verify revocation signature: invalid proof signature: failed to verify signature using ecdsa")
})
@@ -535,7 +535,7 @@ func TestVerifier_VerifyVP(t *testing.T) {
var validAt *time.Time
ctx := newMockContext(t)
- ctx.keyResolver.EXPECT().ResolveSigningKey(vpSignerKeyID.String(), validAt).Return(vdr.TestMethodDIDAPrivateKey().Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(vpSignerKeyID.String(), validAt, vdrTypes.NutsSigningKeyType).Return(vdr.TestMethodDIDAPrivateKey().Public(), nil)
vcs, err := ctx.verifier.VerifyVP(vp, false, validAt)
@@ -548,7 +548,7 @@ func TestVerifier_VerifyVP(t *testing.T) {
var validAt *time.Time
ctx := newMockContext(t)
- ctx.keyResolver.EXPECT().ResolveSigningKey(vpSignerKeyID.String(), validAt).Return(vdr.TestMethodDIDAPrivateKey().Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(vpSignerKeyID.String(), validAt, vdrTypes.NutsSigningKeyType).Return(vdr.TestMethodDIDAPrivateKey().Public(), nil)
mockVerifier := NewMockVerifier(ctx.ctrl)
mockVerifier.EXPECT().Verify(vp.VerifiableCredential[0], false, true, validAt)
@@ -578,7 +578,7 @@ func TestVerifier_VerifyVP(t *testing.T) {
var validAt *time.Time
ctx := newMockContext(t)
- ctx.keyResolver.EXPECT().ResolveSigningKey(vpSignerKeyID.String(), validAt).Return(vdr.TestMethodDIDAPrivateKey().Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(vpSignerKeyID.String(), validAt, vdrTypes.NutsSigningKeyType).Return(vdr.TestMethodDIDAPrivateKey().Public(), nil)
mockVerifier := NewMockVerifier(ctx.ctrl)
mockVerifier.EXPECT().Verify(vp.VerifiableCredential[0], false, true, validAt).Return(errors.New("invalid"))
@@ -595,7 +595,7 @@ func TestVerifier_VerifyVP(t *testing.T) {
ctx := newMockContext(t)
// Return incorrect key, causing signature verification failure
- ctx.keyResolver.EXPECT().ResolveSigningKey(vpSignerKeyID.String(), validAt).Return(vdr.TestMethodDIDBPrivateKey().Public(), nil)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(vpSignerKeyID.String(), validAt, vdrTypes.NutsSigningKeyType).Return(vdr.TestMethodDIDBPrivateKey().Public(), nil)
vcs, err := ctx.verifier.VerifyVP(vp, false, validAt)
@@ -609,7 +609,7 @@ func TestVerifier_VerifyVP(t *testing.T) {
ctx := newMockContext(t)
// Return incorrect key, causing signature verification failure
- ctx.keyResolver.EXPECT().ResolveSigningKey(vpSignerKeyID.String(), validAt).Return(nil, vdrTypes.ErrKeyNotFound)
+ ctx.keyResolver.EXPECT().ResolveKeyByID(vpSignerKeyID.String(), validAt, vdrTypes.NutsSigningKeyType).Return(nil, vdrTypes.ErrKeyNotFound)
vcs, err := ctx.verifier.VerifyVP(vp, false, validAt)
diff --git a/vdr/ambassador.go b/vdr/ambassador.go
index 883fe35a85..c91af162c6 100644
--- a/vdr/ambassador.go
+++ b/vdr/ambassador.go
@@ -63,7 +63,7 @@ type ambassador struct {
networkClient network.Transactions
didStore didstore.Store
keyResolver types.NutsKeyResolver
- didResolver *didservice.Resolver
+ didResolver types.DIDResolver
eventManager events.Event
}
diff --git a/vdr/ambassador_test.go b/vdr/ambassador_test.go
index 3160bffce7..16fa8e6420 100644
--- a/vdr/ambassador_test.go
+++ b/vdr/ambassador_test.go
@@ -377,7 +377,7 @@ func TestAmbassador_handleUpdateDIDDocument(t *testing.T) {
_ = signingKey.Raw(&pKey)
ctx.didStore.EXPECT().Resolve(didDocument.ID, &types.ResolveMetadata{AllowDeactivated: true}).Return(&storedDocument, currentMetadata, nil)
- ctx.keyStore.EXPECT().ResolvePublicKey(storedDocument.CapabilityInvocation[0].ID.String(), gomock.Any()).Return(pKey, nil)
+ ctx.keyResolver.EXPECT().ResolvePublicKey(storedDocument.CapabilityInvocation[0].ID.String(), gomock.Any()).Return(pKey, nil)
ctx.didStore.EXPECT().Add(deactivatedDocument, toStoreTX(tx))
err = ctx.ambassador.handleUpdateDIDDocument(tx, deactivatedDocument)
@@ -413,8 +413,8 @@ func TestAmbassador_handleUpdateDIDDocument(t *testing.T) {
_ = signingKey.Raw(&pKey)
ctx.didStore.EXPECT().Resolve(didDocument.ID, &types.ResolveMetadata{AllowDeactivated: true}).Return(&expectedDocument, currentMetadata, nil)
- ctx.didStore.EXPECT().Resolve(controllerDoc.ID, &types.ResolveMetadata{ResolveTime: &tx.signingTime}).Return(&controllerDoc, nil, nil)
- ctx.keyStore.EXPECT().ResolvePublicKey(controllerDoc.CapabilityInvocation[0].ID.String(), gomock.Any()).Return(pKey, nil)
+ ctx.didResolver.EXPECT().Resolve(controllerDoc.ID, gomock.Any()).Return(&controllerDoc, currentMetadata, nil)
+ ctx.keyResolver.EXPECT().ResolvePublicKey(controllerDoc.CapabilityInvocation[0].ID.String(), gomock.Any()).Return(pKey, nil)
ctx.didStore.EXPECT().Add(expectedDocument, toStoreTX(tx))
err := ctx.ambassador.handleUpdateDIDDocument(tx, expectedDocument)
@@ -449,7 +449,7 @@ func TestAmbassador_handleUpdateDIDDocument(t *testing.T) {
_ = signingKey.Raw(&pKey)
ctx.didStore.EXPECT().Resolve(currentDoc.ID, &types.ResolveMetadata{AllowDeactivated: true, SourceTransaction: &prev}).Return(¤tDoc, currentMetadata, nil)
- ctx.keyStore.EXPECT().ResolvePublicKey(currentDoc.CapabilityInvocation[0].ID.String(), gomock.Any()).Return(pKey, nil)
+ ctx.keyResolver.EXPECT().ResolvePublicKey(currentDoc.CapabilityInvocation[0].ID.String(), gomock.Any()).Return(pKey, nil)
ctx.didStore.EXPECT().Add(newDoc, toStoreTX(tx))
err := ctx.ambassador.handleUpdateDIDDocument(tx, newDoc)
@@ -487,7 +487,7 @@ func TestAmbassador_handleUpdateDIDDocument(t *testing.T) {
ctx.didStore.EXPECT().Resolve(currentDoc.ID, gomock.Any()).Return(nil, nil, types.ErrNotFound),
ctx.didStore.EXPECT().Resolve(currentDoc.ID, &types.ResolveMetadata{AllowDeactivated: true, SourceTransaction: &prev}).Return(¤tDoc, currentMetadata, nil),
)
- ctx.keyStore.EXPECT().ResolvePublicKey(currentDoc.CapabilityInvocation[0].ID.String(), gomock.Any()).Return(pKey, nil)
+ ctx.keyResolver.EXPECT().ResolvePublicKey(currentDoc.CapabilityInvocation[0].ID.String(), gomock.Any()).Return(pKey, nil)
ctx.didStore.EXPECT().Add(newDoc, toStoreTX(tx))
err := ctx.ambassador.handleUpdateDIDDocument(tx, newDoc)
@@ -541,8 +541,8 @@ func TestAmbassador_handleUpdateDIDDocument(t *testing.T) {
}
ctx.didStore.EXPECT().Resolve(didDocument.ID, &types.ResolveMetadata{AllowDeactivated: true}).Return(&expectedDocument, currentMetadata, nil)
- ctx.didStore.EXPECT().Resolve(didDocumentController.ID, gomock.Any()).Return(&didDocumentController, currentMetadata, nil)
- ctx.keyStore.EXPECT().ResolvePublicKey(didDocumentController.CapabilityInvocation[0].ID.String(), gomock.Any()).Return(pKey, nil)
+ ctx.didResolver.EXPECT().Resolve(didDocumentController.ID, gomock.Any()).Return(&didDocumentController, currentMetadata, nil)
+ ctx.keyResolver.EXPECT().ResolvePublicKey(didDocumentController.CapabilityInvocation[0].ID.String(), gomock.Any()).Return(pKey, nil)
ctx.didStore.EXPECT().Add(expectedDocument, toStoreTX(tx))
err = ctx.ambassador.handleUpdateDIDDocument(tx, expectedDocument)
@@ -602,8 +602,8 @@ func TestAmbassador_handleUpdateDIDDocument(t *testing.T) {
}
ctx.didStore.EXPECT().Resolve(didDocument.ID, &types.ResolveMetadata{AllowDeactivated: true}).Return(&expectedDocument, currentMetadata, nil)
- ctx.didStore.EXPECT().Resolve(didDocumentController.ID, &types.ResolveMetadata{ResolveTime: &tx.signingTime}).Return(&didDocumentController, currentMetadata, nil)
- ctx.keyStore.EXPECT().ResolvePublicKey(keyID, gomock.Any()).Return(pKey, nil)
+ ctx.didResolver.EXPECT().Resolve(didDocumentController.ID, gomock.Any()).Return(&didDocumentController, currentMetadata, nil)
+ ctx.keyResolver.EXPECT().ResolvePublicKey(keyID, gomock.Any()).Return(pKey, nil)
err = ctx.ambassador.handleUpdateDIDDocument(tx, didDocument)
assert.EqualError(t, err, "network document not signed by one of its controllers")
@@ -624,7 +624,7 @@ func Test_handleUpdateDIDDocument(t *testing.T) {
ctrl := gomock.NewController(t)
didStoreMock := didstore.NewMockStore(ctrl)
- keyStoreMock := types.NewMockKeyResolver(ctrl)
+ keyStoreMock := types.NewMockNutsKeyResolver(ctrl)
didResolver := &didservice.Resolver{Store: didStoreMock}
am := ambassador{
@@ -827,7 +827,8 @@ func newDidDoc() (did.Document, jwk.Key, error) {
type mockContext struct {
ctrl *gomock.Controller
didStore *didstore.MockStore
- keyStore *types.MockKeyResolver
+ keyResolver *types.MockNutsKeyResolver
+ didResolver *types.MockDIDResolver
eventManager *events.MockEvent
network *network.MockTransactions
ambassador ambassador
@@ -836,13 +837,14 @@ type mockContext struct {
func newMockContext(t *testing.T) mockContext {
ctrl := gomock.NewController(t)
didStoreMock := didstore.NewMockStore(ctrl)
- keyStoreMock := types.NewMockKeyResolver(ctrl)
+ keyResolverMock := types.NewMockNutsKeyResolver(ctrl)
+ resolverMock := types.NewMockDIDResolver(ctrl)
eventManager := events.NewMockEvent(ctrl)
networkMock := network.NewMockTransactions(ctrl)
am := ambassador{
didStore: didStoreMock,
- didResolver: &didservice.Resolver{Store: didStoreMock},
- keyResolver: keyStoreMock,
+ didResolver: resolverMock,
+ keyResolver: keyResolverMock,
eventManager: eventManager,
networkClient: networkMock,
}
@@ -850,7 +852,8 @@ func newMockContext(t *testing.T) mockContext {
return mockContext{
ctrl: ctrl,
didStore: didStoreMock,
- keyStore: keyStoreMock,
+ keyResolver: keyResolverMock,
+ didResolver: resolverMock,
ambassador: am,
eventManager: eventManager,
network: networkMock,
diff --git a/vdr/didservice/nuts_resolvers.go b/vdr/didservice/nuts_resolvers.go
new file mode 100644
index 0000000000..b49389becb
--- /dev/null
+++ b/vdr/didservice/nuts_resolvers.go
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package didservice
+
+import (
+ "crypto"
+ "github.com/nuts-foundation/nuts-node/crypto/hash"
+ "github.com/nuts-foundation/nuts-node/vdr/types"
+)
+
+// NutsKeyResolver implements the NutsKeyResolver interface.
+type NutsKeyResolver struct {
+ Resolver types.DIDResolver
+}
+
+func (r NutsKeyResolver) ResolvePublicKey(kid string, sourceTransactionsRefs []hash.SHA256Hash) (crypto.PublicKey, error) {
+ // try all keys, continue when err == types.ErrNotFound
+ for _, h := range sourceTransactionsRefs {
+ publicKey, err := resolvePublicKey(r.Resolver, kid, types.ResolveMetadata{
+ SourceTransaction: &h,
+ })
+ if err == nil {
+ return publicKey, nil
+ }
+ if err != types.ErrNotFound {
+ return nil, err
+ }
+ }
+
+ return nil, types.ErrNotFound
+}
diff --git a/vdr/didservice/nuts_resolvers_test.go b/vdr/didservice/nuts_resolvers_test.go
new file mode 100644
index 0000000000..fdbdf840fd
--- /dev/null
+++ b/vdr/didservice/nuts_resolvers_test.go
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package didservice
+
+import (
+ "github.com/nuts-foundation/nuts-node/crypto/hash"
+ "github.com/nuts-foundation/nuts-node/vdr/types"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "go.uber.org/mock/gomock"
+ "testing"
+)
+
+func TestNutsKeyResolver_ResolvePublicKey(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ didResolver := types.NewMockDIDResolver(ctrl)
+ keyResolver := NutsKeyResolver{Resolver: didResolver}
+ keyCreator := newMockKeyCreator()
+ docCreator := Creator{KeyStore: keyCreator}
+ doc, _, _ := docCreator.Create(nil, DefaultCreationOptions())
+
+ t.Run("ok by hash", func(t *testing.T) {
+ didResolver.EXPECT().Resolve(testDID, gomock.Any()).Do(func(arg0 interface{}, arg1 interface{}) {
+ resolveMetadata := arg1.(*types.ResolveMetadata)
+ assert.Equal(t, hash.EmptyHash(), *resolveMetadata.SourceTransaction)
+ }).Return(doc, nil, nil)
+
+ key, err := keyResolver.ResolvePublicKey(mockKID, []hash.SHA256Hash{hash.EmptyHash()})
+ require.NoError(t, err)
+
+ assert.NotNil(t, key)
+ })
+
+}
diff --git a/vdr/didservice/resolvers.go b/vdr/didservice/resolvers.go
index 2322de6a13..aa836c8078 100644
--- a/vdr/didservice/resolvers.go
+++ b/vdr/didservice/resolvers.go
@@ -23,7 +23,6 @@ import (
"crypto"
"errors"
"fmt"
- "github.com/nuts-foundation/nuts-node/crypto/hash"
"github.com/nuts-foundation/nuts-node/vdr/didstore"
"time"
@@ -129,54 +128,14 @@ func resolveControllers(resolver types.DIDResolver, doc did.Document, metadata *
return leaves[:j], nil
}
-// NutsKeyResolver implements the NutsKeyResolver interface.
-type NutsKeyResolver struct {
- Resolver types.DIDResolver
-}
-
-func (r NutsKeyResolver) ResolvePublicKey(kid string, sourceTransactionsRefs []hash.SHA256Hash) (crypto.PublicKey, error) {
- // try all keys, continue when err == types.ErrNotFound
- for _, h := range sourceTransactionsRefs {
- publicKey, err := r.resolvePublicKey(r.Resolver, kid, types.ResolveMetadata{
- SourceTransaction: &h,
- })
- if err == nil {
- return publicKey, nil
- }
- if err != types.ErrNotFound {
- return nil, err
- }
- }
-
- return nil, types.ErrNotFound
-}
+var _ types.KeyResolver = KeyResolver{}
// KeyResolver implements the KeyResolver interface with a types.Store as backend
type KeyResolver struct {
Store didstore.Store
}
-// ResolveSigningKeyID resolves the ID of the first valid AssertionMethod for an indicated DID document at a given time.
-func (r KeyResolver) ResolveSigningKeyID(holder did.DID, validAt *time.Time) (string, error) {
- doc, _, err := r.Store.Resolve(holder, &types.ResolveMetadata{
- ResolveTime: validAt,
- })
- if err != nil {
- return "", err
- }
- if len(doc.AssertionMethod) == 0 {
- return "", types.ErrKeyNotFound
- }
- return doc.AssertionMethod[0].ID.String(), nil
-}
-
-// ResolveSigningKey resolves the PublicKey of the first valid AssertionMethod for an indicated
-// DID document at a validAt time.
-func (r KeyResolver) ResolveSigningKey(keyID string, validAt *time.Time) (crypto.PublicKey, error) {
- return r.ResolveRelationKey(keyID, validAt, types.AssertionMethod)
-}
-
-func (r KeyResolver) ResolveRelationKey(keyID string, validAt *time.Time, relationType types.RelationType) (crypto.PublicKey, error) {
+func (r KeyResolver) ResolveKeyByID(keyID string, validAt *time.Time, relationType types.RelationType) (crypto.PublicKey, error) {
holder, err := GetDIDFromURL(keyID)
if err != nil {
return nil, fmt.Errorf("invalid key ID (id=%s): %w", keyID, err)
@@ -185,16 +144,39 @@ func (r KeyResolver) ResolveRelationKey(keyID string, validAt *time.Time, relati
ResolveTime: validAt,
})
if err != nil {
- return "", err
+ return nil, err
+ }
+ relationships, err := resolveRelationships(doc, relationType)
+ if err != nil {
+ return nil, err
}
- relationships, _ := resolveRelationships(doc, relationType)
-
for _, rel := range relationships {
if rel.ID.String() == keyID {
return rel.PublicKey()
}
}
- return "", types.ErrKeyNotFound
+ return nil, types.ErrKeyNotFound
+}
+
+func (r KeyResolver) ResolveKey(id did.DID, validAt *time.Time, relationType types.RelationType) (ssi.URI, crypto.PublicKey, error) {
+ doc, _, err := r.Store.Resolve(id, &types.ResolveMetadata{
+ ResolveTime: validAt,
+ })
+ if err != nil {
+ return ssi.URI{}, nil, err
+ }
+ keys, err := resolveRelationships(doc, relationType)
+ if err != nil {
+ return ssi.URI{}, nil, err
+ }
+ if len(keys) == 0 {
+ return ssi.URI{}, nil, types.ErrKeyNotFound
+ }
+ publicKey, err := keys[0].PublicKey()
+ if err != nil {
+ return ssi.URI{}, nil, err
+ }
+ return keys[0].ID.URI(), publicKey, nil
}
func resolveRelationships(doc *did.Document, relationType types.RelationType) (relationships did.VerificationRelationships, err error) {
@@ -213,56 +195,7 @@ func resolveRelationships(doc *did.Document, relationType types.RelationType) (r
return nil, fmt.Errorf("unable to locate RelationType %v", relationType)
}
}
-
-// ResolveAssertionKeyID resolves the id of the first valid AssertionMethod of an indicated DID document in the current state.
-func (r KeyResolver) ResolveAssertionKeyID(id did.DID) (ssi.URI, error) {
- doc, _, err := r.Store.Resolve(id, nil)
- if err != nil {
- return ssi.URI{}, err
- }
-
- return ExtractFirstRelationKeyIDByType(*doc, types.AssertionMethod)
-}
-
-func (r KeyResolver) ResolveRelationKeyID(id did.DID, relationType types.RelationType) (ssi.URI, error) {
- doc, _, err := r.Store.Resolve(id, nil)
- if err != nil {
- return ssi.URI{}, err
- }
-
- return ExtractFirstRelationKeyIDByType(*doc, relationType)
-}
-
-// ResolveKeyAgreementKey resolves the public key of the first valid KeyAgreement of an indicated DID document in the current state.
-// If the document has no KeyAgreements, types.ErrKeyNotFound is returned.
-func (r KeyResolver) ResolveKeyAgreementKey(id did.DID) (crypto.PublicKey, error) {
- doc, _, err := r.Store.Resolve(id, nil)
- if err != nil {
- return ssi.URI{}, err
- }
- if len(doc.KeyAgreement) == 0 {
- return nil, types.ErrKeyNotFound
- }
- return doc.KeyAgreement[0].PublicKey()
-}
-
-// ExtractFirstRelationKeyIDByType returns the first relation key ID from the given DID document matching the relationType.
-// Returns a types.ErrKeyNotFound if no relation key of the given relationType is present.
-func ExtractFirstRelationKeyIDByType(doc did.Document, relationType types.RelationType) (ssi.URI, error) {
- keys, err := resolveRelationships(&doc, relationType)
- if err != nil {
- return ssi.URI{}, err
- }
- for _, key := range keys {
- kid := key.ID.String()
- u, _ := ssi.ParseURI(kid)
- return *u, nil
- }
-
- return ssi.URI{}, types.ErrKeyNotFound
-}
-
-func (r NutsKeyResolver) resolvePublicKey(resolver types.DIDResolver, kid string, metadata types.ResolveMetadata) (crypto.PublicKey, error) {
+func resolvePublicKey(resolver types.DIDResolver, kid string, metadata types.ResolveMetadata) (crypto.PublicKey, error) {
id, err := did.ParseDIDURL(kid)
if err != nil {
return nil, fmt.Errorf("invalid key ID (id=%s): %w", kid, err)
diff --git a/vdr/didservice/resolvers_test.go b/vdr/didservice/resolvers_test.go
index 97db93baf1..2a0ada5fe8 100644
--- a/vdr/didservice/resolvers_test.go
+++ b/vdr/didservice/resolvers_test.go
@@ -20,7 +20,6 @@ package didservice
import (
"errors"
"fmt"
- "github.com/nuts-foundation/nuts-node/audit"
"testing"
"time"
@@ -34,177 +33,6 @@ import (
"go.uber.org/mock/gomock"
)
-func TestResolveSigningKey(t *testing.T) {
- ctrl := gomock.NewController(t)
- store := didstore.NewMockStore(ctrl)
- keyResolver := KeyResolver{Store: store}
- keyCreator := newMockKeyCreator()
- docCreator := Creator{KeyStore: keyCreator}
- doc, _, _ := docCreator.Create(nil, DefaultCreationOptions())
- // add a second key to the document
- methodID := doc.ID
- methodID.Fragment = "key2"
- newMethod := &did.VerificationMethod{ID: methodID}
- doc.AddAssertionMethod(newMethod)
-
- t.Run("ok", func(t *testing.T) {
- store.EXPECT().Resolve(testDID, gomock.Any()).Return(doc, nil, nil)
-
- key, err := keyResolver.ResolveSigningKey(mockKID, nil)
-
- require.NoError(t, err)
- assert.NotNil(t, key)
- })
-
- t.Run("unable to resolve document", func(t *testing.T) {
- store.EXPECT().Resolve(testDID, gomock.Any()).Return(nil, nil, types.ErrNotFound)
-
- _, err := keyResolver.ResolveSigningKey(mockKID, nil)
-
- assert.Error(t, err)
- assert.Equal(t, types.ErrNotFound, err)
- })
-
- t.Run("signing key not found in document", func(t *testing.T) {
- store.EXPECT().Resolve(testDID, gomock.Any()).Return(doc, nil, nil)
-
- _, err := keyResolver.ResolveSigningKey(mockKID[:len(mockKID)-2], nil)
-
- assert.Error(t, err)
- assert.Equal(t, types.ErrKeyNotFound, err)
- })
-
- t.Run("invalid key ID", func(t *testing.T) {
- _, err := keyResolver.ResolveSigningKey("asdasdsa", nil)
-
- assert.Error(t, err)
- assert.ErrorIs(t, err, did.ErrInvalidDID)
- })
-}
-
-func TestResolveSigningKeyID(t *testing.T) {
- keyCreator := newMockKeyCreator()
- docCreator := Creator{KeyStore: keyCreator}
- doc, _, _ := docCreator.Create(nil, DefaultCreationOptions())
-
- t.Run("ok", func(t *testing.T) {
- ctrl := gomock.NewController(t)
- store := didstore.NewMockStore(ctrl)
- keyResolver := KeyResolver{Store: store}
- store.EXPECT().Resolve(testDID, gomock.Any()).Return(doc, nil, nil)
-
- actual, err := keyResolver.ResolveSigningKeyID(testDID, nil)
-
- require.NoError(t, err)
- assert.Equal(t, mockKID, actual)
- })
-
- t.Run("unable to resolve", func(t *testing.T) {
- ctrl := gomock.NewController(t)
- store := didstore.NewMockStore(ctrl)
- keyResolver := KeyResolver{Store: store}
- store.EXPECT().Resolve(testDID, gomock.Any()).Return(nil, nil, types.ErrNotFound)
-
- _, err := keyResolver.ResolveSigningKeyID(testDID, nil)
-
- assert.Error(t, err)
- assert.Equal(t, types.ErrNotFound, err)
- })
-
- t.Run("signing key not found", func(t *testing.T) {
- ctrl := gomock.NewController(t)
- store := didstore.NewMockStore(ctrl)
- keyResolver := KeyResolver{Store: store}
- store.EXPECT().Resolve(testDID, gomock.Any()).Return(&did.Document{}, nil, nil)
-
- _, err := keyResolver.ResolveSigningKeyID(testDID, nil)
-
- assert.Equal(t, types.ErrKeyNotFound, err)
- })
-}
-
-func TestKeyResolver_ResolveAssertionKeyID(t *testing.T) {
- keyCreator := newMockKeyCreator()
- docCreator := Creator{KeyStore: keyCreator}
- doc, _, _ := docCreator.Create(nil, DefaultCreationOptions())
-
- t.Run("ok - resolve a known key", func(t *testing.T) {
- ctrl := gomock.NewController(t)
- store := didstore.NewMockStore(ctrl)
- keyResolver := KeyResolver{Store: store}
- store.EXPECT().Resolve(testDID, gomock.Any()).Return(doc, nil, nil)
-
- actual, err := keyResolver.ResolveAssertionKeyID(testDID)
-
- require.NoError(t, err)
- assert.Equal(t, mockKID, actual.String())
- })
-
- t.Run("unable to resolve", func(t *testing.T) {
- ctrl := gomock.NewController(t)
- store := didstore.NewMockStore(ctrl)
- keyResolver := KeyResolver{Store: store}
- store.EXPECT().Resolve(testDID, gomock.Any()).Return(nil, nil, types.ErrNotFound)
-
- _, err := keyResolver.ResolveAssertionKeyID(testDID)
-
- assert.Error(t, err)
- assert.Equal(t, types.ErrNotFound, err)
- })
-
- t.Run("signing key not found", func(t *testing.T) {
- ctrl := gomock.NewController(t)
- store := didstore.NewMockStore(ctrl)
- keyResolver := KeyResolver{Store: store}
- store.EXPECT().Resolve(testDID, gomock.Any()).Return(&did.Document{}, nil, nil)
-
- _, err := keyResolver.ResolveAssertionKeyID(testDID)
-
- assert.Equal(t, types.ErrKeyNotFound, err)
- })
-}
-
-func TestKeyResolver_ResolveKeyAgreementKey(t *testing.T) {
- keyCreator := newMockKeyCreator()
- docCreator := Creator{KeyStore: keyCreator}
- doc, _, _ := docCreator.Create(audit.TestContext(), DefaultCreationOptions())
-
- t.Run("ok - resolve a known key", func(t *testing.T) {
- ctrl := gomock.NewController(t)
- store := didstore.NewMockStore(ctrl)
- keyResolver := KeyResolver{Store: store}
- store.EXPECT().Resolve(testDID, gomock.Any()).Return(doc, nil, nil)
-
- actual, err := keyResolver.ResolveKeyAgreementKey(testDID)
-
- require.NoError(t, err)
- assert.NotNil(t, actual)
- })
-
- t.Run("unable to resolve", func(t *testing.T) {
- ctrl := gomock.NewController(t)
- store := didstore.NewMockStore(ctrl)
- keyResolver := KeyResolver{Store: store}
- store.EXPECT().Resolve(testDID, gomock.Any()).Return(nil, nil, types.ErrNotFound)
-
- _, err := keyResolver.ResolveKeyAgreementKey(testDID)
-
- assert.Error(t, err)
- assert.Equal(t, types.ErrNotFound, err)
- })
-
- t.Run("key not found", func(t *testing.T) {
- ctrl := gomock.NewController(t)
- store := didstore.NewMockStore(ctrl)
- keyResolver := KeyResolver{Store: store}
- store.EXPECT().Resolve(testDID, gomock.Any()).Return(&did.Document{}, nil, nil)
-
- _, err := keyResolver.ResolveKeyAgreementKey(testDID)
-
- assert.Equal(t, types.ErrKeyNotFound, err)
- })
-}
-
func TestResolver_Resolve(t *testing.T) {
id123, _ := did.ParseDID("did:nuts:123")
id456, _ := did.ParseDID("did:nuts:456")
@@ -452,28 +280,6 @@ func TestResolveControllers(t *testing.T) {
})
}
-func TestNutsKeyResolver_ResolvePublicKey(t *testing.T) {
- ctrl := gomock.NewController(t)
- didResolver := types.NewMockDIDResolver(ctrl)
- keyResolver := NutsKeyResolver{Resolver: didResolver}
- keyCreator := newMockKeyCreator()
- docCreator := Creator{KeyStore: keyCreator}
- doc, _, _ := docCreator.Create(nil, DefaultCreationOptions())
-
- t.Run("ok by hash", func(t *testing.T) {
- didResolver.EXPECT().Resolve(testDID, gomock.Any()).Do(func(arg0 interface{}, arg1 interface{}) {
- resolveMetadata := arg1.(*types.ResolveMetadata)
- assert.Equal(t, hash.EmptyHash(), *resolveMetadata.SourceTransaction)
- }).Return(doc, nil, nil)
-
- key, err := keyResolver.ResolvePublicKey(mockKID, []hash.SHA256Hash{hash.EmptyHash()})
- require.NoError(t, err)
-
- assert.NotNil(t, key)
- })
-
-}
-
func TestServiceResolver_Resolve(t *testing.T) {
meta := &types.DocumentMetadata{Hash: hash.EmptyHash()}
@@ -583,62 +389,49 @@ func TestServiceResolver_Resolve(t *testing.T) {
}
-func TestExtractFirstRelationKeyIDByType(t *testing.T) {
+func TestKeyResolver_ResolveKey(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ store := didstore.NewMockStore(ctrl)
+ keyResolver := KeyResolver{Store: store}
+
keyCreator := newMockKeyCreator()
docCreator := Creator{KeyStore: keyCreator}
doc, _, err := docCreator.Create(nil, DefaultCreationOptions())
require.NoError(t, err)
- type args struct {
- doc did.Document
- relationType types.RelationType
- }
- tests := []struct {
- name string
- args args
- want ssi.URI
- expectedErr error
- }{
- {
- name: "ok - it finds the key",
- args: args{
- doc: *doc,
- relationType: types.AssertionMethod,
- },
- want: doc.VerificationMethod[0].ID.URI(),
- expectedErr: nil,
- },
- {
- name: "err - key not found",
- args: args{
- doc: *doc,
- relationType: types.CapabilityDelegation,
- },
- want: ssi.URI{},
- expectedErr: types.ErrKeyNotFound,
- },
- {
- name: "err - unknown relation type",
- args: args{
- doc: *doc,
- relationType: 20,
- },
- want: ssi.URI{},
- expectedErr: errors.New("unable to locate RelationType 20"),
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := ExtractFirstRelationKeyIDByType(tt.args.doc, tt.args.relationType)
- if tt.expectedErr != nil {
- require.EqualError(t, err, tt.expectedErr.Error())
- return
- }
- assert.Equalf(t, tt.want, got, "ExtractFirstRelationKeyIDByType(%v, %v)", tt.args.doc, tt.args.relationType)
- })
- }
+ store.EXPECT().Resolve(doc.ID, gomock.Any()).AnyTimes().Return(doc, nil, nil)
+
+ t.Run("ok - it finds the key", func(t *testing.T) {
+ keyId, key, err := keyResolver.ResolveKey(doc.ID, nil, types.AssertionMethod)
+ require.NoError(t, err)
+ assert.Equal(t, doc.VerificationMethod[0].ID.URI(), keyId)
+ assert.NotNil(t, key)
+ })
+
+ t.Run("error - document not found", func(t *testing.T) {
+ unknownDID := did.MustParseDID("did:example:123")
+ store.EXPECT().Resolve(unknownDID, gomock.Any()).Return(nil, nil, types.ErrNotFound)
+ keyId, key, err := keyResolver.ResolveKey(unknownDID, nil, types.AssertionMethod)
+ assert.EqualError(t, err, "unable to find the DID document")
+ assert.Empty(t, keyId)
+ assert.Nil(t, key)
+ })
+
+ t.Run("error - key not found", func(t *testing.T) {
+ keyId, key, err := keyResolver.ResolveKey(did.MustParseDIDURL(doc.ID.String()), nil, types.CapabilityDelegation)
+ assert.EqualError(t, err, "key not found in DID document")
+ assert.Empty(t, keyId)
+ assert.Nil(t, key)
+ })
+
+ t.Run("error - unknown relationship type", func(t *testing.T) {
+ keyId, key, err := keyResolver.ResolveKey(doc.ID, nil, 1000)
+ assert.EqualError(t, err, "unable to locate RelationType 1000")
+ assert.Empty(t, keyId)
+ assert.Nil(t, key)
+ })
}
-func TestKeyResolver_ResolveRelationKeyID(t *testing.T) {
+func TestKeyResolver_ResolveKeyByID(t *testing.T) {
ctrl := gomock.NewController(t)
store := didstore.NewMockStore(ctrl)
keyResolver := KeyResolver{Store: store}
@@ -646,21 +439,40 @@ func TestKeyResolver_ResolveRelationKeyID(t *testing.T) {
keyCreator := newMockKeyCreator()
docCreator := Creator{KeyStore: keyCreator}
doc, _, err := docCreator.Create(nil, DefaultCreationOptions())
- store.EXPECT().Resolve(doc.ID, gomock.Any()).Return(doc, nil, nil)
require.NoError(t, err)
+ store.EXPECT().Resolve(doc.ID, gomock.Any()).AnyTimes().Return(doc, nil, nil)
+ keyID := doc.VerificationMethod[0].ID
t.Run("ok - it finds the key", func(t *testing.T) {
- keyId, err := keyResolver.ResolveRelationKeyID(doc.ID, types.AssertionMethod)
- require.NoError(t, err)
- assert.Equal(t, doc.VerificationMethod[0].ID.URI(), keyId)
+ key, err := keyResolver.ResolveKeyByID(keyID.String(), nil, types.AssertionMethod)
+ assert.NoError(t, err)
+ assert.NotNil(t, key)
})
- t.Run("err - document not found", func(t *testing.T) {
- unknownDID := did.MustParseDID("did:example:123")
+ t.Run("error - invalid key ID", func(t *testing.T) {
+ key, err := keyResolver.ResolveKeyByID("abcdef", nil, types.AssertionMethod)
+ assert.EqualError(t, err, "invalid key ID (id=abcdef): invalid DID")
+ assert.Nil(t, key)
+ })
+
+ t.Run("error - document not found", func(t *testing.T) {
+ unknownDID := did.MustParseDIDURL("did:example:123")
store.EXPECT().Resolve(unknownDID, gomock.Any()).Return(nil, nil, types.ErrNotFound)
- keyId, err := keyResolver.ResolveRelationKeyID(unknownDID, types.AssertionMethod)
- require.EqualError(t, err, "unable to find the DID document")
- require.Equal(t, ssi.URI{}, keyId)
+ key, err := keyResolver.ResolveKeyByID(unknownDID.String()+"#456", nil, types.AssertionMethod)
+ assert.EqualError(t, err, "unable to find the DID document")
+ assert.Nil(t, key)
+ })
+
+ t.Run("error - key not found", func(t *testing.T) {
+ key, err := keyResolver.ResolveKeyByID(did.MustParseDIDURL(doc.ID.String()+"#123").String(), nil, types.AssertionMethod)
+ assert.EqualError(t, err, "key not found in DID document")
+ assert.Nil(t, key)
+ })
+
+ t.Run("error - unknown relationship type", func(t *testing.T) {
+ key, err := keyResolver.ResolveKeyByID(keyID.String(), nil, 1000)
+ assert.EqualError(t, err, "unable to locate RelationType 1000")
+ assert.Nil(t, key)
})
}
diff --git a/vdr/integration_test.go b/vdr/integration_test.go
index 82482f9aae..3dcff7ba78 100644
--- a/vdr/integration_test.go
+++ b/vdr/integration_test.go
@@ -97,7 +97,7 @@ func TestVDRIntegration_Test(t *testing.T) {
"unexpected error while resolving documentB")
// Update the controller of DocumentA with DocumentB
- // And remove it's own authenticationMethod
+ // And remove its own authenticationMethod
docA.Controller = []did.DID{docB.ID}
docA.AssertionMethod = []did.VerificationRelationship{}
docA.CapabilityInvocation = []did.VerificationRelationship{}
diff --git a/vdr/types/interface.go b/vdr/types/interface.go
index 9e122043c4..bb2f12a47f 100644
--- a/vdr/types/interface.go
+++ b/vdr/types/interface.go
@@ -79,28 +79,19 @@ type DocUpdater interface {
// KeyResolver is the interface for resolving keys.
// This can be used for checking if a signing key is valid at a point in time or to just find a valid key for signing.
type KeyResolver interface {
- // ResolveSigningKeyID looks up a signing key of the specified holder. It returns the ID
- // of the found key. Typically used to find a key for signing one's own documents. If no suitable keys
- // are found an error is returned.
- ResolveSigningKeyID(holder did.DID, validAt *time.Time) (string, error)
- // ResolveSigningKey looks up a specific signing key and returns it as crypto.PublicKey. If the key can't be found
- // or isn't meant for signing an error is returned.
- ResolveSigningKey(keyID string, validAt *time.Time) (crypto.PublicKey, error)
- // ResolveAssertionKeyID look for a valid assertion key for the give DID. If multiple keys are valid, the first one is returned.
- // An ErrKeyNotFound is returned when no key is found.
- ResolveAssertionKeyID(id did.DID) (ssi.URI, error)
- // ResolveKeyAgreementKey look for a valid keyAgreement key for the give DID. If multiple keys are valid, the first one is returned.
- // An ErrKeyNotFound is returned when no key is found.
- ResolveKeyAgreementKey(id did.DID) (crypto.PublicKey, error)
- // ResolveRelationKey looks up a specific key of the given RelationType and returns it as crypto.PublicKey.
- // If the key can't be found or isn't meant for signing an error is returned.
- ResolveRelationKey(keyID string, validAt *time.Time, relationType RelationType) (crypto.PublicKey, error)
- // ResolveRelationKeyID look for a valid key of the given RelationType for the give DID.
+ // ResolveKeyByID looks up a specific key of the given RelationType and returns it as crypto.PublicKey.
// If multiple keys are valid, the first one is returned.
- // An ErrKeyNotFound is returned when no key is found.
- ResolveRelationKeyID(id did.DID, relationType RelationType) (ssi.URI, error)
+ // An ErrKeyNotFound is returned when no key (of the specified type) is found.
+ ResolveKeyByID(keyID string, validAt *time.Time, relationType RelationType) (crypto.PublicKey, error)
+ // ResolveKey looks for a valid key of the given RelationType for the given DID, and returns its ID and the key itself.
+ // If multiple keys are valid, the first one is returned.
+ // An ErrKeyNotFound is returned when no key (of the specified type) is found.
+ ResolveKey(id did.DID, validAt *time.Time, relationType RelationType) (ssi.URI, crypto.PublicKey, error)
}
+// NutsSigningKeyType defines the verification method relationship type for signing keys in Nuts DID Documents.
+const NutsSigningKeyType = AssertionMethod
+
// NutsKeyResolver is the interface for resolving keys from Nuts DID Documents,
// supporting Nuts-specific DID resolution parameters.
type NutsKeyResolver interface {
diff --git a/vdr/types/mock.go b/vdr/types/mock.go
index d6fe1730ea..8ed6320ca5 100644
--- a/vdr/types/mock.go
+++ b/vdr/types/mock.go
@@ -271,109 +271,73 @@ func (m *MockKeyResolver) EXPECT() *MockKeyResolverMockRecorder {
return m.recorder
}
-// ResolveAssertionKeyID mocks base method.
-func (m *MockKeyResolver) ResolveAssertionKeyID(id did.DID) (ssi.URI, error) {
+// ResolveKey mocks base method.
+func (m *MockKeyResolver) ResolveKey(id did.DID, validAt *time.Time, relationType RelationType) (ssi.URI, crypto.PublicKey, error) {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "ResolveAssertionKeyID", id)
+ ret := m.ctrl.Call(m, "ResolveKey", id, validAt, relationType)
ret0, _ := ret[0].(ssi.URI)
- ret1, _ := ret[1].(error)
- return ret0, ret1
+ ret1, _ := ret[1].(crypto.PublicKey)
+ ret2, _ := ret[2].(error)
+ return ret0, ret1, ret2
}
-// ResolveAssertionKeyID indicates an expected call of ResolveAssertionKeyID.
-func (mr *MockKeyResolverMockRecorder) ResolveAssertionKeyID(id interface{}) *gomock.Call {
+// ResolveKey indicates an expected call of ResolveKey.
+func (mr *MockKeyResolverMockRecorder) ResolveKey(id, validAt, relationType interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResolveAssertionKeyID", reflect.TypeOf((*MockKeyResolver)(nil).ResolveAssertionKeyID), id)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResolveKey", reflect.TypeOf((*MockKeyResolver)(nil).ResolveKey), id, validAt, relationType)
}
-// ResolveKeyAgreementKey mocks base method.
-func (m *MockKeyResolver) ResolveKeyAgreementKey(id did.DID) (crypto.PublicKey, error) {
+// ResolveKeyByID mocks base method.
+func (m *MockKeyResolver) ResolveKeyByID(keyID string, validAt *time.Time, relationType RelationType) (crypto.PublicKey, error) {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "ResolveKeyAgreementKey", id)
+ ret := m.ctrl.Call(m, "ResolveKeyByID", keyID, validAt, relationType)
ret0, _ := ret[0].(crypto.PublicKey)
ret1, _ := ret[1].(error)
return ret0, ret1
}
-// ResolveKeyAgreementKey indicates an expected call of ResolveKeyAgreementKey.
-func (mr *MockKeyResolverMockRecorder) ResolveKeyAgreementKey(id interface{}) *gomock.Call {
+// ResolveKeyByID indicates an expected call of ResolveKeyByID.
+func (mr *MockKeyResolverMockRecorder) ResolveKeyByID(keyID, validAt, relationType interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResolveKeyAgreementKey", reflect.TypeOf((*MockKeyResolver)(nil).ResolveKeyAgreementKey), id)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResolveKeyByID", reflect.TypeOf((*MockKeyResolver)(nil).ResolveKeyByID), keyID, validAt, relationType)
}
-// ResolvePublicKey mocks base method.
-func (m *MockKeyResolver) ResolvePublicKey(kid string, sourceTransactionsRefs []hash.SHA256Hash) (crypto.PublicKey, error) {
- m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "ResolvePublicKey", kid, sourceTransactionsRefs)
- ret0, _ := ret[0].(crypto.PublicKey)
- ret1, _ := ret[1].(error)
- return ret0, ret1
-}
-
-// ResolvePublicKey indicates an expected call of ResolvePublicKey.
-func (mr *MockKeyResolverMockRecorder) ResolvePublicKey(kid, sourceTransactionsRefs interface{}) *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResolvePublicKey", reflect.TypeOf((*MockKeyResolver)(nil).ResolvePublicKey), kid, sourceTransactionsRefs)
+// MockNutsKeyResolver is a mock of NutsKeyResolver interface.
+type MockNutsKeyResolver struct {
+ ctrl *gomock.Controller
+ recorder *MockNutsKeyResolverMockRecorder
}
-// ResolveRelationKey mocks base method.
-func (m *MockKeyResolver) ResolveRelationKey(keyID string, validAt *time.Time, relationType RelationType) (crypto.PublicKey, error) {
- m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "ResolveRelationKey", keyID, validAt, relationType)
- ret0, _ := ret[0].(crypto.PublicKey)
- ret1, _ := ret[1].(error)
- return ret0, ret1
+// MockNutsKeyResolverMockRecorder is the mock recorder for MockNutsKeyResolver.
+type MockNutsKeyResolverMockRecorder struct {
+ mock *MockNutsKeyResolver
}
-// ResolveRelationKey indicates an expected call of ResolveRelationKey.
-func (mr *MockKeyResolverMockRecorder) ResolveRelationKey(keyID, validAt, relationType interface{}) *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResolveRelationKey", reflect.TypeOf((*MockKeyResolver)(nil).ResolveRelationKey), keyID, validAt, relationType)
-}
-
-// ResolveRelationKeyID mocks base method.
-func (m *MockKeyResolver) ResolveRelationKeyID(id did.DID, relationType RelationType) (ssi.URI, error) {
- m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "ResolveRelationKeyID", id, relationType)
- ret0, _ := ret[0].(ssi.URI)
- ret1, _ := ret[1].(error)
- return ret0, ret1
+// NewMockNutsKeyResolver creates a new mock instance.
+func NewMockNutsKeyResolver(ctrl *gomock.Controller) *MockNutsKeyResolver {
+ mock := &MockNutsKeyResolver{ctrl: ctrl}
+ mock.recorder = &MockNutsKeyResolverMockRecorder{mock}
+ return mock
}
-// ResolveRelationKeyID indicates an expected call of ResolveRelationKeyID.
-func (mr *MockKeyResolverMockRecorder) ResolveRelationKeyID(id, relationType interface{}) *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResolveRelationKeyID", reflect.TypeOf((*MockKeyResolver)(nil).ResolveRelationKeyID), id, relationType)
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockNutsKeyResolver) EXPECT() *MockNutsKeyResolverMockRecorder {
+ return m.recorder
}
-// ResolveSigningKey mocks base method.
-func (m *MockKeyResolver) ResolveSigningKey(keyID string, validAt *time.Time) (crypto.PublicKey, error) {
+// ResolvePublicKey mocks base method.
+func (m *MockNutsKeyResolver) ResolvePublicKey(kid string, sourceTransactionsRefs []hash.SHA256Hash) (crypto.PublicKey, error) {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "ResolveSigningKey", keyID, validAt)
+ ret := m.ctrl.Call(m, "ResolvePublicKey", kid, sourceTransactionsRefs)
ret0, _ := ret[0].(crypto.PublicKey)
ret1, _ := ret[1].(error)
return ret0, ret1
}
-// ResolveSigningKey indicates an expected call of ResolveSigningKey.
-func (mr *MockKeyResolverMockRecorder) ResolveSigningKey(keyID, validAt interface{}) *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResolveSigningKey", reflect.TypeOf((*MockKeyResolver)(nil).ResolveSigningKey), keyID, validAt)
-}
-
-// ResolveSigningKeyID mocks base method.
-func (m *MockKeyResolver) ResolveSigningKeyID(holder did.DID, validAt *time.Time) (string, error) {
- m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "ResolveSigningKeyID", holder, validAt)
- ret0, _ := ret[0].(string)
- ret1, _ := ret[1].(error)
- return ret0, ret1
-}
-
-// ResolveSigningKeyID indicates an expected call of ResolveSigningKeyID.
-func (mr *MockKeyResolverMockRecorder) ResolveSigningKeyID(holder, validAt interface{}) *gomock.Call {
+// ResolvePublicKey indicates an expected call of ResolvePublicKey.
+func (mr *MockNutsKeyResolverMockRecorder) ResolvePublicKey(kid, sourceTransactionsRefs interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResolveSigningKeyID", reflect.TypeOf((*MockKeyResolver)(nil).ResolveSigningKeyID), holder, validAt)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResolvePublicKey", reflect.TypeOf((*MockNutsKeyResolver)(nil).ResolvePublicKey), kid, sourceTransactionsRefs)
}
// MockVDR is a mock of VDR interface.