Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Revoked check for a key when signing manifest, schema, presentation request. #579

Merged
merged 9 commits into from
Jul 12, 2023
5 changes: 5 additions & 0 deletions pkg/server/router/credential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,11 @@ func TestCredentialRouter(t *testing.T) {
assert.Empty(tt, createdCred)
assert.Error(tt, err)
assert.ErrorContains(tt, err, "cannot use revoked key")

// create a schema with the revoked key, it fails
_, err = schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Issuer: controllerDID.DID.ID, Name: "schema (revoked key)", Schema: getEmailSchema(), FullyQualifiedVerificationMethodID: keyID})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the wrong file to test this in. Can you move to router/schema_test.go?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I can. I put the test in this file because it seemed like a simplest way to test the change with minimal number of new lines (since the key revocation logic is already in place), and because schema creation was already being tested in this file anyways.

assert.Error(tt, err)
assert.ErrorContains(tt, err, "cannot use revoked key")
})

t.Run("Credential Status List Test", func(tt *testing.T) {
Expand Down
56 changes: 36 additions & 20 deletions pkg/server/router/manifest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import (
"github.com/tbd54566975/ssi-service/pkg/service/credential"
"github.com/tbd54566975/ssi-service/pkg/service/did"
"github.com/tbd54566975/ssi-service/pkg/service/framework"
"github.com/tbd54566975/ssi-service/pkg/service/keystore"
"github.com/tbd54566975/ssi-service/pkg/service/manifest"

"github.com/tbd54566975/ssi-service/pkg/service/manifest/model"
"github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
presmodel "github.com/tbd54566975/ssi-service/pkg/service/presentation/model"
Expand Down Expand Up @@ -198,38 +201,51 @@ func TestManifestRouter(t *testing.T) {
signed, err := signer.SignJSON(applicationRequest)
assert.NoError(ttt, err)

submitApplicationRequest := SubmitApplicationRequest{ApplicationJWT: *signed}
sar, err := submitApplicationRequest.toServiceRequest()
assert.NoError(ttt, err)
createdApplicationResponseOp, err := manifestService.ProcessApplicationSubmission(context.Background(), *sar)
assert.NoError(ttt, err)
assert.False(ttt, createdApplicationResponseOp.Done)

createdApplicationResponse, err := manifestService.ReviewApplication(context.Background(), model.ReviewApplicationRequest{
ID: storage.StatusObjectID(createdApplicationResponseOp.ID),
Approved: true,
Reason: "ApprovalMan is here",
CredentialOverrides: map[string]model.CredentialOverride{
"id1": {
Data: map[string]any{"licenseType": "Class D"},
},
"id2": {
Data: map[string]any{"licenseType": "Class D"},
},
},
})
// submit and review application, the key is valid
createdApplicationResponse, err := submitAndReviewApplication(signed, ttt, manifestService)
assert.NoError(ttt, err)
assert.NotEmpty(ttt, createdManifest)
assert.NotEmpty(ttt, createdApplicationResponse.Response.ID)
assert.NotEmpty(ttt, createdApplicationResponse.Response.Fulfillment)
assert.Empty(ttt, createdApplicationResponse.Response.Denial)
assert.Equal(ttt, len(createManifestRequest.OutputDescriptors), len(createdApplicationResponse.Credentials))

// attempt to submit and review application again, this time with the revoked key
err = keyStoreService.RevokeKey(context.Background(), keystore.RevokeKeyRequest{ID: kid})
assert.NoError(ttt, err)
_, err = submitAndReviewApplication(signed, ttt, manifestService)
assert.Error(tt, err)
assert.ErrorContains(tt, err, "cannot use revoked key")
})
})
})
}
}

func submitAndReviewApplication(signed *keyaccess.JWT, ttt *testing.T, manifestService *manifest.Service) (*model.SubmitApplicationResponse, error) {
submitApplicationRequest := SubmitApplicationRequest{ApplicationJWT: *signed}
sar, err := submitApplicationRequest.toServiceRequest()
assert.NoError(ttt, err)
createdApplicationResponseOp, err := manifestService.ProcessApplicationSubmission(context.Background(), *sar)
assert.NoError(ttt, err)
assert.False(ttt, createdApplicationResponseOp.Done)

createdApplicationResponse, err := manifestService.ReviewApplication(context.Background(), model.ReviewApplicationRequest{
ID: storage.StatusObjectID(createdApplicationResponseOp.ID),
Approved: true,
Reason: "ApprovalMan is here",
CredentialOverrides: map[string]model.CredentialOverride{
"id1": {
Data: map[string]any{"licenseType": "Class D"},
},
"id2": {
Data: map[string]any{"licenseType": "Class D"},
},
},
})
return createdApplicationResponse, err
}

func getValidManifestRequestRequest(issuerDID *did.CreateDIDResponse, kid string, createdManifest *model.CreateManifestResponse) model.CreateRequestRequest {
return model.CreateRequestRequest{
ManifestRequest: model.Request{
Expand Down
3 changes: 3 additions & 0 deletions pkg/service/keystore/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ func (s Service) Sign(ctx context.Context, keyID string, data any) (*keyaccess.J
if err != nil {
return nil, sdkutil.LoggingErrorMsgf(err, "getting key with keyID<%s>", keyID)
}
if gotKey.Revoked {
return nil, sdkutil.LoggingNewErrorf("cannot use revoked key<%s>", gotKey.ID)
}
keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.Controller, gotKey.ID, gotKey.Key)
if err != nil {
return nil, sdkutil.LoggingErrorMsgf(err, "creating key access for keyID<%s>", keyID)
Expand Down
5 changes: 5 additions & 0 deletions pkg/service/keystore/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ func TestRevokeKey(t *testing.T) {
assert.Equal(t, privKey, keyResponse.Key)
assert.True(t, keyResponse.Revoked)
assert.Equal(t, "2023-06-23T00:00:00Z", keyResponse.RevokedAt)

// attempt to "Sign()" with the revoked key, ensure it is prohibited
_, err = keyStore.Sign(context.Background(), keyID, "sampleDataAsString")
assert.Error(t, err)
assert.ErrorContains(t, err, "cannot use revoked key")
}

func createKeyStoreService(t *testing.T) (*Service, error) {
Expand Down
3 changes: 3 additions & 0 deletions pkg/service/manifest/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ func (s Service) signCredentialResponse(ctx context.Context, keyStoreID string,
if err != nil {
return nil, sdkutil.LoggingErrorMsgf(err, "getting key for signing response with key<%s>", keyStoreID)
}
if gotKey.Revoked {
return nil, sdkutil.LoggingNewErrorf("cannot use revoked key<%s>", gotKey.ID)
}
keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.Controller, gotKey.ID, gotKey.Key)
if err != nil {
return nil, sdkutil.LoggingErrorMsgf(err, "creating key access for signing response with key<%s>", gotKey.ID)
Expand Down
3 changes: 3 additions & 0 deletions pkg/service/schema/service.go
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to add a test for this changes as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ func (s Service) signCredentialSchema(ctx context.Context, cred credential.Verif
if gotKey.Controller != issuer {
return nil, sdkutil.LoggingNewErrorf("key controller<%s> does not match credential issuer<%s> for key<%s>", gotKey.Controller, issuer, fullyQualifiedVerificationMethodID)
}
if gotKey.Revoked {
return nil, sdkutil.LoggingNewErrorf("cannot use revoked key<%s>", gotKey.ID)
}
keyAccess, err := keyaccess.NewJWKKeyAccess(fullyQualifiedVerificationMethodID, gotKey.ID, gotKey.Key)
if err != nil {
return nil, errors.Wrapf(err, "creating key access for signing credential schema with key<%s>", gotKey.ID)
Expand Down
Loading