diff --git a/cmd/vc-rest/go.mod b/cmd/vc-rest/go.mod index d45a6c80b..bc9449ddc 100644 --- a/cmd/vc-rest/go.mod +++ b/cmd/vc-rest/go.mod @@ -21,9 +21,9 @@ require ( github.com/spf13/cobra v1.7.0 github.com/stretchr/testify v1.8.4 github.com/trustbloc/cmdutil-go v1.0.0 - github.com/trustbloc/did-go v1.0.0 + github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 github.com/trustbloc/logutil-go v1.0.0 - github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 + github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 github.com/trustbloc/vcs v0.0.0 github.com/trustbloc/vcs/component/credentialstatus v0.0.0-00010101000000-000000000000a github.com/trustbloc/vcs/component/echo v0.0.0-00010101000000-000000000000 @@ -115,7 +115,6 @@ require ( github.com/hashicorp/go-version v1.2.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 // indirect - github.com/hyperledger/ursa-wrapper-go v0.3.1 // indirect github.com/imdario/mergo v0.3.15 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect @@ -177,7 +176,8 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect - github.com/trustbloc/kms-go v1.0.0 // indirect + github.com/trustbloc/bbs-signature-go v1.0.0 // indirect + github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 // indirect github.com/trustbloc/sidetree-core-go v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fastjson v1.6.3 // indirect diff --git a/cmd/vc-rest/go.sum b/cmd/vc-rest/go.sum index b764d271f..07d68b62d 100644 --- a/cmd/vc-rest/go.sum +++ b/cmd/vc-rest/go.sum @@ -354,8 +354,6 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 h1:B1Nt8hKb//KvgGRprk0h1t4lCnwhE9/ryb1WqfZbV+M= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2/go.mod h1:X+DIyUsaTmalOpmpQfIvFZjKHQedrURQ5t4YqquX7lE= -github.com/hyperledger/ursa-wrapper-go v0.3.1 h1:Do+QrVNniY77YK2jTIcyWqj9rm/Yb5SScN0bqCjiibA= -github.com/hyperledger/ursa-wrapper-go v0.3.1/go.mod h1:nPSAuMasIzSVciQo22PedBk4Opph6bJ6ia3ms7BH/mk= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= @@ -586,18 +584,20 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/trustbloc/bbs-signature-go v1.0.0 h1:JOKmPRTpjbbGODt71i3wJyiEBcu5XEoeSMQaM0WHR7Q= +github.com/trustbloc/bbs-signature-go v1.0.0/go.mod h1:8xptu/lbVUDACQW10yiHtqATzC2kpTKQk5mKsKTD85Y= github.com/trustbloc/cmdutil-go v1.0.0 h1:QCe7wVEIASWmy9ZDD0l0tsQCEsX6fx+kBFX5UqCVRdk= github.com/trustbloc/cmdutil-go v1.0.0/go.mod h1:o/v7C1z6d/5UrjaC6GAUc1hk0XVuE3M4tpyvsMMUw5k= -github.com/trustbloc/did-go v1.0.0 h1:emrE2iG7/sQ2ZIPg60FnNIfe1dTAVG3A/Ls0i8jHO10= -github.com/trustbloc/did-go v1.0.0/go.mod h1:+A6OLKYBSh5cGjc6qk3KZ1DXOAlfIjdUwqz+tzcjOKM= -github.com/trustbloc/kms-go v1.0.0 h1:uV4J95DXKgpcxEQtRLJ6Aa9nk1CY8cLSUHgSwwzqJIQ= -github.com/trustbloc/kms-go v1.0.0/go.mod h1:1rvrHRuIRT7qLapB0lSpFgy1CjFunx85EyEzcZpIxG8= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 h1:UA6QlD58VZnSd2EpFJCi9XctBY3naKouBOtjMss4ewc= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9/go.mod h1:qqTm9zd5rGhHSOtC8jjadqM01Od9zcDbUiUYLv+M6ls= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 h1:nNmYk/CX3UrLe4a7qCaMjsc+IWcQdZlJGvY5D2gsewE= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30/go.mod h1:7arOSG9GewtV1WiqYZ23dSZ6haamosSABwyG//cRaXQ= github.com/trustbloc/logutil-go v1.0.0 h1:KzNs9TRbnmn+M3oYw9UkrtOjNd3ZGO8aLgfYttMypcE= github.com/trustbloc/logutil-go v1.0.0/go.mod h1:JlxT0oZfNKgIlSNtgc001WEeDMxlnAvOM43gNm8DQVc= github.com/trustbloc/sidetree-core-go v1.0.0 h1:kzfKZOJ0sgDy9D1AYNcoR3JHutqtMtKvF2P9UwUcDjU= github.com/trustbloc/sidetree-core-go v1.0.0/go.mod h1:jdxAFuorlIwFOGVW6O455/lZqxg2mZkRHNTEolcZdDI= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 h1:FG8enh3pfxjxedtKdI7gOMrUQeKMhUlpuXR3O8kGwvg= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269/go.mod h1:047WbpZu3QQ/mRqMO4JBDMUtY9M/LaEHwBJNo7XxdTY= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 h1:GizDlcTPMuOh8HHifl8qp+ohaGMhiIT7k4+NcI/CA/I= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468/go.mod h1:6I4D1Hlf5CpSXBbfOIf58ZPtheyT8ZdsorN2kef2ZxU= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= diff --git a/component/credentialstatus/credentialstatus_service_test.go b/component/credentialstatus/credentialstatus_service_test.go index 5b33a33cf..c8f07323a 100644 --- a/component/credentialstatus/credentialstatus_service_test.go +++ b/component/credentialstatus/credentialstatus_service_test.go @@ -73,12 +73,14 @@ func validateVCStatus( statusListVC, err := s.GetStatusListVC(context.Background(), externalProfileID, existingStatusVCListID) require.NoError(t, err) - require.Equal(t, existingStatusListVCID, statusListVC.ID) - require.Equal(t, "did:test:abc", statusListVC.Issuer.ID) - require.Equal(t, vcutil.DefVCContext, statusListVC.Context[0]) - require.Equal(t, statustype.StatusList2021Context, statusListVC.Context[1]) - credSubject, ok := statusListVC.Subject.([]verifiable.Subject) - require.True(t, ok) + + statusListVCC := statusListVC.Contents() + + require.Equal(t, existingStatusListVCID, statusListVCC.ID) + require.Equal(t, "did:test:abc", statusListVCC.Issuer.ID) + require.Equal(t, vcutil.DefVCContext, statusListVCC.Context[0]) + require.Equal(t, statustype.StatusList2021Context, statusListVCC.Context[1]) + credSubject := statusListVCC.Subject require.Equal(t, existingStatusListVCID+"#list", credSubject[0].ID) require.Equal(t, statustype.StatusList2021VCSubjectType, credSubject[0].CustomFields["type"].(string)) require.Equal(t, "revocation", credSubject[0].CustomFields[statustype.StatusPurpose].(string)) @@ -303,8 +305,7 @@ func TestCredentialStatusList_UpdateVCStatus(t *testing.T) { revocationListIndex, err := strconv.Atoi(statusListEntry.TypedID.CustomFields[statustype.StatusListIndex].(string)) require.NoError(t, err) - credSubject, ok := statusListVC.Subject.([]verifiable.Subject) - require.True(t, ok) + credSubject := statusListVC.Contents().Subject require.NotEmpty(t, credSubject[0].CustomFields["encodedList"].(string)) bitString, err := bitstring.DecodeBits(credSubject[0].CustomFields["encodedList"].(string)) require.NoError(t, err) @@ -732,8 +733,7 @@ func TestCredentialStatusList_UpdateVCStatus(t *testing.T) { revocationListIndex, err := strconv.Atoi(statusListEntry.TypedID.CustomFields[statustype.StatusListIndex].(string)) require.NoError(t, err) - credSubject, ok := revocationListVC.Subject.([]verifiable.Subject) - require.True(t, ok) + credSubject := revocationListVC.Contents().Subject require.NotEmpty(t, credSubject[0].CustomFields["encodedList"].(string)) bitString, err := bitstring.DecodeBits(credSubject[0].CustomFields["encodedList"].(string)) require.NoError(t, err) diff --git a/component/credentialstatus/go.mod b/component/credentialstatus/go.mod index dd3c8fe87..40cf24a9c 100644 --- a/component/credentialstatus/go.mod +++ b/component/credentialstatus/go.mod @@ -12,10 +12,10 @@ require ( github.com/piprate/json-gold v0.5.1-0.20230111113000-6ddbe6e6f19f github.com/spf13/cobra v1.7.0 github.com/stretchr/testify v1.8.4 - github.com/trustbloc/did-go v1.0.0 - github.com/trustbloc/kms-go v1.0.0 + github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 + github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 github.com/trustbloc/logutil-go v1.0.0 - github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 + github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 github.com/trustbloc/vcs v0.0.0 ) @@ -66,7 +66,6 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 // indirect - github.com/hyperledger/ursa-wrapper-go v0.3.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kawamuray/jsonpath v0.0.0-20201211160320-7483bafabd7e // indirect github.com/kilic/bls12-381 v0.1.1-0.20210503002446-7b7597926c69 // indirect @@ -114,6 +113,7 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect + github.com/trustbloc/bbs-signature-go v1.0.0 // indirect github.com/trustbloc/sidetree-core-go v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.1 // indirect diff --git a/component/credentialstatus/go.sum b/component/credentialstatus/go.sum index cfe4e8a1d..3f3fbba0a 100644 --- a/component/credentialstatus/go.sum +++ b/component/credentialstatus/go.sum @@ -278,8 +278,6 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 h1:B1Nt8hKb//KvgGRprk0h1t4lCnwhE9/ryb1WqfZbV+M= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2/go.mod h1:X+DIyUsaTmalOpmpQfIvFZjKHQedrURQ5t4YqquX7lE= -github.com/hyperledger/ursa-wrapper-go v0.3.1 h1:Do+QrVNniY77YK2jTIcyWqj9rm/Yb5SScN0bqCjiibA= -github.com/hyperledger/ursa-wrapper-go v0.3.1/go.mod h1:nPSAuMasIzSVciQo22PedBk4Opph6bJ6ia3ms7BH/mk= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= @@ -447,16 +445,18 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/trustbloc/did-go v1.0.0 h1:emrE2iG7/sQ2ZIPg60FnNIfe1dTAVG3A/Ls0i8jHO10= -github.com/trustbloc/did-go v1.0.0/go.mod h1:+A6OLKYBSh5cGjc6qk3KZ1DXOAlfIjdUwqz+tzcjOKM= -github.com/trustbloc/kms-go v1.0.0 h1:uV4J95DXKgpcxEQtRLJ6Aa9nk1CY8cLSUHgSwwzqJIQ= -github.com/trustbloc/kms-go v1.0.0/go.mod h1:1rvrHRuIRT7qLapB0lSpFgy1CjFunx85EyEzcZpIxG8= +github.com/trustbloc/bbs-signature-go v1.0.0 h1:JOKmPRTpjbbGODt71i3wJyiEBcu5XEoeSMQaM0WHR7Q= +github.com/trustbloc/bbs-signature-go v1.0.0/go.mod h1:8xptu/lbVUDACQW10yiHtqATzC2kpTKQk5mKsKTD85Y= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 h1:UA6QlD58VZnSd2EpFJCi9XctBY3naKouBOtjMss4ewc= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9/go.mod h1:qqTm9zd5rGhHSOtC8jjadqM01Od9zcDbUiUYLv+M6ls= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 h1:nNmYk/CX3UrLe4a7qCaMjsc+IWcQdZlJGvY5D2gsewE= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30/go.mod h1:7arOSG9GewtV1WiqYZ23dSZ6haamosSABwyG//cRaXQ= github.com/trustbloc/logutil-go v1.0.0 h1:KzNs9TRbnmn+M3oYw9UkrtOjNd3ZGO8aLgfYttMypcE= github.com/trustbloc/logutil-go v1.0.0/go.mod h1:JlxT0oZfNKgIlSNtgc001WEeDMxlnAvOM43gNm8DQVc= github.com/trustbloc/sidetree-core-go v1.0.0 h1:kzfKZOJ0sgDy9D1AYNcoR3JHutqtMtKvF2P9UwUcDjU= github.com/trustbloc/sidetree-core-go v1.0.0/go.mod h1:jdxAFuorlIwFOGVW6O455/lZqxg2mZkRHNTEolcZdDI= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 h1:FG8enh3pfxjxedtKdI7gOMrUQeKMhUlpuXR3O8kGwvg= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269/go.mod h1:047WbpZu3QQ/mRqMO4JBDMUtY9M/LaEHwBJNo7XxdTY= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 h1:GizDlcTPMuOh8HHifl8qp+ohaGMhiIT7k4+NcI/CA/I= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468/go.mod h1:6I4D1Hlf5CpSXBbfOIf58ZPtheyT8ZdsorN2kef2ZxU= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= diff --git a/component/event/go.mod b/component/event/go.mod index 5e70966f8..98cea48a7 100644 --- a/component/event/go.mod +++ b/component/event/go.mod @@ -12,7 +12,7 @@ require ( github.com/stretchr/testify v1.8.4 github.com/trustbloc/cmdutil-go v1.0.0 github.com/trustbloc/logutil-go v1.0.0 - github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 + github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 github.com/trustbloc/vcs v0.0.0 go.opentelemetry.io/otel/trace v1.14.0 ) @@ -64,7 +64,6 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 // indirect - github.com/hyperledger/ursa-wrapper-go v0.3.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kawamuray/jsonpath v0.0.0-20201211160320-7483bafabd7e // indirect github.com/kilic/bls12-381 v0.1.1-0.20210503002446-7b7597926c69 // indirect @@ -104,8 +103,9 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect - github.com/trustbloc/did-go v1.0.0 // indirect - github.com/trustbloc/kms-go v1.0.0 // indirect + github.com/trustbloc/bbs-signature-go v1.0.0 // indirect + github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 // indirect + github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.1 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect diff --git a/component/event/go.sum b/component/event/go.sum index 48e0c35d7..61777156f 100644 --- a/component/event/go.sum +++ b/component/event/go.sum @@ -277,8 +277,6 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 h1:B1Nt8hKb//KvgGRprk0h1t4lCnwhE9/ryb1WqfZbV+M= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2/go.mod h1:X+DIyUsaTmalOpmpQfIvFZjKHQedrURQ5t4YqquX7lE= -github.com/hyperledger/ursa-wrapper-go v0.3.1 h1:Do+QrVNniY77YK2jTIcyWqj9rm/Yb5SScN0bqCjiibA= -github.com/hyperledger/ursa-wrapper-go v0.3.1/go.mod h1:nPSAuMasIzSVciQo22PedBk4Opph6bJ6ia3ms7BH/mk= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= @@ -429,16 +427,18 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/trustbloc/bbs-signature-go v1.0.0 h1:JOKmPRTpjbbGODt71i3wJyiEBcu5XEoeSMQaM0WHR7Q= +github.com/trustbloc/bbs-signature-go v1.0.0/go.mod h1:8xptu/lbVUDACQW10yiHtqATzC2kpTKQk5mKsKTD85Y= github.com/trustbloc/cmdutil-go v1.0.0 h1:QCe7wVEIASWmy9ZDD0l0tsQCEsX6fx+kBFX5UqCVRdk= github.com/trustbloc/cmdutil-go v1.0.0/go.mod h1:o/v7C1z6d/5UrjaC6GAUc1hk0XVuE3M4tpyvsMMUw5k= -github.com/trustbloc/did-go v1.0.0 h1:emrE2iG7/sQ2ZIPg60FnNIfe1dTAVG3A/Ls0i8jHO10= -github.com/trustbloc/did-go v1.0.0/go.mod h1:+A6OLKYBSh5cGjc6qk3KZ1DXOAlfIjdUwqz+tzcjOKM= -github.com/trustbloc/kms-go v1.0.0 h1:uV4J95DXKgpcxEQtRLJ6Aa9nk1CY8cLSUHgSwwzqJIQ= -github.com/trustbloc/kms-go v1.0.0/go.mod h1:1rvrHRuIRT7qLapB0lSpFgy1CjFunx85EyEzcZpIxG8= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 h1:UA6QlD58VZnSd2EpFJCi9XctBY3naKouBOtjMss4ewc= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9/go.mod h1:qqTm9zd5rGhHSOtC8jjadqM01Od9zcDbUiUYLv+M6ls= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 h1:nNmYk/CX3UrLe4a7qCaMjsc+IWcQdZlJGvY5D2gsewE= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30/go.mod h1:7arOSG9GewtV1WiqYZ23dSZ6haamosSABwyG//cRaXQ= github.com/trustbloc/logutil-go v1.0.0 h1:KzNs9TRbnmn+M3oYw9UkrtOjNd3ZGO8aLgfYttMypcE= github.com/trustbloc/logutil-go v1.0.0/go.mod h1:JlxT0oZfNKgIlSNtgc001WEeDMxlnAvOM43gNm8DQVc= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 h1:FG8enh3pfxjxedtKdI7gOMrUQeKMhUlpuXR3O8kGwvg= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269/go.mod h1:047WbpZu3QQ/mRqMO4JBDMUtY9M/LaEHwBJNo7XxdTY= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 h1:GizDlcTPMuOh8HHifl8qp+ohaGMhiIT7k4+NcI/CA/I= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468/go.mod h1:6I4D1Hlf5CpSXBbfOIf58ZPtheyT8ZdsorN2kef2ZxU= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= diff --git a/component/profile/reader/file/go.mod b/component/profile/reader/file/go.mod index fdbae1c6f..3ae79e37f 100644 --- a/component/profile/reader/file/go.mod +++ b/component/profile/reader/file/go.mod @@ -10,8 +10,8 @@ require ( github.com/spf13/cobra v1.7.0 github.com/stretchr/testify v1.8.4 github.com/trustbloc/cmdutil-go v1.0.0 - github.com/trustbloc/did-go v1.0.0 - github.com/trustbloc/kms-go v1.0.0 + github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 + github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 github.com/trustbloc/logutil-go v1.0.0 github.com/trustbloc/vcs v0.0.0 ) @@ -70,7 +70,6 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 // indirect - github.com/hyperledger/ursa-wrapper-go v0.3.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kawamuray/jsonpath v0.0.0-20201211160320-7483bafabd7e // indirect @@ -121,8 +120,9 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect + github.com/trustbloc/bbs-signature-go v1.0.0 // indirect github.com/trustbloc/sidetree-core-go v1.0.0 // indirect - github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 // indirect + github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.1 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect diff --git a/component/profile/reader/file/go.sum b/component/profile/reader/file/go.sum index 2b35dc06a..ab4cf7407 100644 --- a/component/profile/reader/file/go.sum +++ b/component/profile/reader/file/go.sum @@ -314,8 +314,6 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 h1:B1Nt8hKb//KvgGRprk0h1t4lCnwhE9/ryb1WqfZbV+M= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2/go.mod h1:X+DIyUsaTmalOpmpQfIvFZjKHQedrURQ5t4YqquX7lE= -github.com/hyperledger/ursa-wrapper-go v0.3.1 h1:Do+QrVNniY77YK2jTIcyWqj9rm/Yb5SScN0bqCjiibA= -github.com/hyperledger/ursa-wrapper-go v0.3.1/go.mod h1:nPSAuMasIzSVciQo22PedBk4Opph6bJ6ia3ms7BH/mk= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= @@ -518,18 +516,20 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/trustbloc/bbs-signature-go v1.0.0 h1:JOKmPRTpjbbGODt71i3wJyiEBcu5XEoeSMQaM0WHR7Q= +github.com/trustbloc/bbs-signature-go v1.0.0/go.mod h1:8xptu/lbVUDACQW10yiHtqATzC2kpTKQk5mKsKTD85Y= github.com/trustbloc/cmdutil-go v1.0.0 h1:QCe7wVEIASWmy9ZDD0l0tsQCEsX6fx+kBFX5UqCVRdk= github.com/trustbloc/cmdutil-go v1.0.0/go.mod h1:o/v7C1z6d/5UrjaC6GAUc1hk0XVuE3M4tpyvsMMUw5k= -github.com/trustbloc/did-go v1.0.0 h1:emrE2iG7/sQ2ZIPg60FnNIfe1dTAVG3A/Ls0i8jHO10= -github.com/trustbloc/did-go v1.0.0/go.mod h1:+A6OLKYBSh5cGjc6qk3KZ1DXOAlfIjdUwqz+tzcjOKM= -github.com/trustbloc/kms-go v1.0.0 h1:uV4J95DXKgpcxEQtRLJ6Aa9nk1CY8cLSUHgSwwzqJIQ= -github.com/trustbloc/kms-go v1.0.0/go.mod h1:1rvrHRuIRT7qLapB0lSpFgy1CjFunx85EyEzcZpIxG8= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 h1:UA6QlD58VZnSd2EpFJCi9XctBY3naKouBOtjMss4ewc= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9/go.mod h1:qqTm9zd5rGhHSOtC8jjadqM01Od9zcDbUiUYLv+M6ls= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 h1:nNmYk/CX3UrLe4a7qCaMjsc+IWcQdZlJGvY5D2gsewE= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30/go.mod h1:7arOSG9GewtV1WiqYZ23dSZ6haamosSABwyG//cRaXQ= github.com/trustbloc/logutil-go v1.0.0 h1:KzNs9TRbnmn+M3oYw9UkrtOjNd3ZGO8aLgfYttMypcE= github.com/trustbloc/logutil-go v1.0.0/go.mod h1:JlxT0oZfNKgIlSNtgc001WEeDMxlnAvOM43gNm8DQVc= github.com/trustbloc/sidetree-core-go v1.0.0 h1:kzfKZOJ0sgDy9D1AYNcoR3JHutqtMtKvF2P9UwUcDjU= github.com/trustbloc/sidetree-core-go v1.0.0/go.mod h1:jdxAFuorlIwFOGVW6O455/lZqxg2mZkRHNTEolcZdDI= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 h1:FG8enh3pfxjxedtKdI7gOMrUQeKMhUlpuXR3O8kGwvg= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269/go.mod h1:047WbpZu3QQ/mRqMO4JBDMUtY9M/LaEHwBJNo7XxdTY= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 h1:GizDlcTPMuOh8HHifl8qp+ohaGMhiIT7k4+NcI/CA/I= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468/go.mod h1:6I4D1Hlf5CpSXBbfOIf58ZPtheyT8ZdsorN2kef2ZxU= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= diff --git a/component/wallet-cli/go.mod b/component/wallet-cli/go.mod index 38697d85a..1a0910a0c 100644 --- a/component/wallet-cli/go.mod +++ b/component/wallet-cli/go.mod @@ -20,9 +20,9 @@ require ( github.com/spf13/cobra v1.7.0 github.com/stretchr/testify v1.8.4 github.com/syndtr/goleveldb v1.0.0 - github.com/trustbloc/did-go v1.0.0 - github.com/trustbloc/kms-go v1.0.0 - github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 + github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 + github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 + github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 github.com/trustbloc/vcs v0.1.9-0.20230210204445-f2870a36f0ea github.com/valyala/fastjson v1.6.3 go.mongodb.org/mongo-driver v1.11.4 @@ -90,7 +90,6 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 // indirect - github.com/hyperledger/ursa-wrapper-go v0.3.1 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -146,6 +145,7 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect + github.com/trustbloc/bbs-signature-go v1.0.0 // indirect github.com/trustbloc/logutil-go v1.0.0-rc1 // indirect github.com/trustbloc/sidetree-core-go v1.0.0 // indirect github.com/trustbloc/vcs/component/oidc/fosite v0.0.0-20230724110323-79c5330617d6 // indirect diff --git a/component/wallet-cli/go.sum b/component/wallet-cli/go.sum index e11d451bb..1df717634 100644 --- a/component/wallet-cli/go.sum +++ b/component/wallet-cli/go.sum @@ -332,8 +332,6 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 h1:B1Nt8hKb//KvgGRprk0h1t4lCnwhE9/ryb1WqfZbV+M= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2/go.mod h1:X+DIyUsaTmalOpmpQfIvFZjKHQedrURQ5t4YqquX7lE= -github.com/hyperledger/ursa-wrapper-go v0.3.1 h1:Do+QrVNniY77YK2jTIcyWqj9rm/Yb5SScN0bqCjiibA= -github.com/hyperledger/ursa-wrapper-go v0.3.1/go.mod h1:nPSAuMasIzSVciQo22PedBk4Opph6bJ6ia3ms7BH/mk= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= @@ -558,16 +556,18 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/trustbloc/did-go v1.0.0 h1:emrE2iG7/sQ2ZIPg60FnNIfe1dTAVG3A/Ls0i8jHO10= -github.com/trustbloc/did-go v1.0.0/go.mod h1:+A6OLKYBSh5cGjc6qk3KZ1DXOAlfIjdUwqz+tzcjOKM= -github.com/trustbloc/kms-go v1.0.0 h1:uV4J95DXKgpcxEQtRLJ6Aa9nk1CY8cLSUHgSwwzqJIQ= -github.com/trustbloc/kms-go v1.0.0/go.mod h1:1rvrHRuIRT7qLapB0lSpFgy1CjFunx85EyEzcZpIxG8= +github.com/trustbloc/bbs-signature-go v1.0.0 h1:JOKmPRTpjbbGODt71i3wJyiEBcu5XEoeSMQaM0WHR7Q= +github.com/trustbloc/bbs-signature-go v1.0.0/go.mod h1:8xptu/lbVUDACQW10yiHtqATzC2kpTKQk5mKsKTD85Y= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 h1:UA6QlD58VZnSd2EpFJCi9XctBY3naKouBOtjMss4ewc= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9/go.mod h1:qqTm9zd5rGhHSOtC8jjadqM01Od9zcDbUiUYLv+M6ls= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 h1:nNmYk/CX3UrLe4a7qCaMjsc+IWcQdZlJGvY5D2gsewE= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30/go.mod h1:7arOSG9GewtV1WiqYZ23dSZ6haamosSABwyG//cRaXQ= github.com/trustbloc/logutil-go v1.0.0-rc1 h1:rRJbvgQfrlUfyej+mY0nuQJymGqjRW4oZEwKi544F4c= github.com/trustbloc/logutil-go v1.0.0-rc1/go.mod h1:JlxT0oZfNKgIlSNtgc001WEeDMxlnAvOM43gNm8DQVc= github.com/trustbloc/sidetree-core-go v1.0.0 h1:kzfKZOJ0sgDy9D1AYNcoR3JHutqtMtKvF2P9UwUcDjU= github.com/trustbloc/sidetree-core-go v1.0.0/go.mod h1:jdxAFuorlIwFOGVW6O455/lZqxg2mZkRHNTEolcZdDI= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 h1:FG8enh3pfxjxedtKdI7gOMrUQeKMhUlpuXR3O8kGwvg= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269/go.mod h1:047WbpZu3QQ/mRqMO4JBDMUtY9M/LaEHwBJNo7XxdTY= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 h1:GizDlcTPMuOh8HHifl8qp+ohaGMhiIT7k4+NcI/CA/I= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468/go.mod h1:6I4D1Hlf5CpSXBbfOIf58ZPtheyT8ZdsorN2kef2ZxU= github.com/trustbloc/vcs/component/oidc/fosite v0.0.0-20230724110323-79c5330617d6 h1:iqqHGeoI6fXZbjtjvV9OCql7XQtr8P4LQBE9d2j9Ll8= github.com/trustbloc/vcs/component/oidc/fosite v0.0.0-20230724110323-79c5330617d6/go.mod h1:D/dD0ld+XRAt/MjhKnrpaVbaKTe5Zq9uAXONf5c4OxU= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= diff --git a/component/wallet-cli/pkg/walletrunner/vcprovider/vcs.go b/component/wallet-cli/pkg/walletrunner/vcprovider/vcs.go index 9287b8cdb..ab0c564da 100644 --- a/component/wallet-cli/pkg/walletrunner/vcprovider/vcs.go +++ b/component/wallet-cli/pkg/walletrunner/vcprovider/vcs.go @@ -133,15 +133,13 @@ func (p *vcsCredentialsProvider) createVCSCredential(credential, authToken strin return nil, fmt.Errorf("err parsing credentials: %w", err) } - cred.ID = uuid.New().URN() - - subjs, ok := cred.Subject.([]verifiable.Subject) - if !ok { - return nil, fmt.Errorf("cred subject has wrong type, not verifiable.Subject") - } - + subjs := cred.Contents().Subject subjs[0].ID = p.conf.WalletParams.DidID[0] + cred = cred. + WithModifiedID(uuid.New().URN()). + WithModifiedSubject(subjs) + reqData, err := GetIssueCredentialRequestData(cred, p.conf.VCFormat) if err != nil { return nil, fmt.Errorf("unable to get issue credential request data: %w", err) diff --git a/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4ci.go b/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4ci.go index 6e32c3d44..7acaa362f 100644 --- a/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4ci.go +++ b/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4ci.go @@ -228,7 +228,7 @@ func (s *Service) RunOIDC4CI(config *OIDC4CIConfig, hooks *Hooks) error { log.Printf( "Credential with ID [%s] and type [%v] added successfully", - vcParsed.ID, + vcParsed.Contents().ID, config.CredentialType, ) @@ -385,7 +385,7 @@ func (s *Service) RunOIDC4CIWalletInitiated(config *OIDC4CIConfig, hooks *Hooks) log.Printf( "Credential with ID [%s] and type [%v] added successfully", - vcParsed.ID, + vcParsed.Contents().ID, config.CredentialType, ) diff --git a/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4ci_pre_auth.go b/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4ci_pre_auth.go index 7fd0f2fae..d32358e36 100644 --- a/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4ci_pre_auth.go +++ b/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4ci_pre_auth.go @@ -139,7 +139,8 @@ func (s *Service) RunOIDC4CIPreAuth(config *OIDC4CIConfig) (*verifiable.Credenti return nil, fmt.Errorf("parse vc: %w", err) } - log.Printf("Credential with ID [%s] and type [%v] added successfully", vcParsed.ID, config.CredentialType) + log.Printf("Credential with ID [%s] and type [%v] added successfully", + vcParsed.Contents().ID, config.CredentialType) if !s.keepWalletOpen { s.wallet.Close() diff --git a/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4vp.go b/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4vp.go index 76071b1a8..b7f4ee4cb 100644 --- a/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4vp.go +++ b/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4vp.go @@ -330,10 +330,7 @@ func (e *VPFlowExecutor) QueryCredentialFromWalletMultiVP() error { return fmt.Errorf("query credentials from wallet: %w", err) } - credentials, err := e.getCredentials(legacyVP[0].Credentials()) - if err != nil { - return fmt.Errorf("failed to parse credentials from vp: %w", err) - } + credentials := legacyVP[0].Credentials() // Create a list of verifiable presentations, with one presentation for each provided credential. vps, ps, err := e.requestObject.Claims.VPToken.PresentationDefinition.CreateVPArray(credentials, e.ariesServices.documentLoader, verifiable.WithJSONLDDocumentLoader(e.ariesServices.documentLoader)) @@ -566,33 +563,22 @@ func (e *VPFlowExecutor) getDIDIndex(did string) int { return -1 } -func (e *VPFlowExecutor) GetSubjectID(creds []interface{}) (string, error) { +func (e *VPFlowExecutor) GetSubjectID(creds []*verifiable.Credential) (string, error) { subjectIDMap := make(map[string]bool) var subjectID string + var err error - for _, cred := range creds { - vcBytes, err := json.Marshal(cred) - if err != nil { - return "", err - } - - vc, err := verifiable.ParseCredential(vcBytes, - verifiable.WithDisabledProofCheck(), - verifiable.WithJSONLDDocumentLoader(e.ariesServices.documentLoader)) - if err != nil { - return "", fmt.Errorf("fail to parse credential: %w", err) - } - - subjectID, err = verifiable.SubjectID(vc.Subject) + for _, vc := range creds { + subjectID, err = verifiable.SubjectID(vc.Contents().Subject) if err != nil { return "", fmt.Errorf("failed to get subject ID: %w", err) } - if vc.JWT != "" { + if vc.IsJWT() { // We use this strange code, because cred.JWTClaims(false) not take to account "sub" claim from jwt _, rawClaims, credErr := jwt.Parse( - vc.JWT, + vc.JWTEnvelope.JWT, jwt.WithSignatureVerifier(&noVerifier{}), jwt.WithIgnoreClaimsMapDecoding(true), ) diff --git a/go.mod b/go.mod index 16a18cb1b..7f8c80a7f 100644 --- a/go.mod +++ b/go.mod @@ -36,10 +36,11 @@ require ( github.com/stretchr/testify v1.8.4 github.com/tidwall/gjson v1.14.4 github.com/tidwall/sjson v1.2.5 - github.com/trustbloc/did-go v1.0.0 - github.com/trustbloc/kms-go v1.0.0 + github.com/trustbloc/bbs-signature-go v1.0.0 + github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 + github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 github.com/trustbloc/logutil-go v1.0.0-rc1 - github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 + github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 github.com/trustbloc/vcs/component/oidc/fosite v0.0.0-20230724110323-79c5330617d6 github.com/valyala/fastjson v1.6.3 github.com/xeipuuv/gojsonschema v1.2.0 @@ -114,7 +115,6 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 // indirect - github.com/hyperledger/ursa-wrapper-go v0.3.1 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect diff --git a/go.sum b/go.sum index c97823da3..43c9f5e55 100644 --- a/go.sum +++ b/go.sum @@ -368,8 +368,6 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 h1:B1Nt8hKb//KvgGRprk0h1t4lCnwhE9/ryb1WqfZbV+M= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2/go.mod h1:X+DIyUsaTmalOpmpQfIvFZjKHQedrURQ5t4YqquX7lE= -github.com/hyperledger/ursa-wrapper-go v0.3.1 h1:Do+QrVNniY77YK2jTIcyWqj9rm/Yb5SScN0bqCjiibA= -github.com/hyperledger/ursa-wrapper-go v0.3.1/go.mod h1:nPSAuMasIzSVciQo22PedBk4Opph6bJ6ia3ms7BH/mk= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= @@ -623,14 +621,16 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/trustbloc/did-go v1.0.0 h1:emrE2iG7/sQ2ZIPg60FnNIfe1dTAVG3A/Ls0i8jHO10= -github.com/trustbloc/did-go v1.0.0/go.mod h1:+A6OLKYBSh5cGjc6qk3KZ1DXOAlfIjdUwqz+tzcjOKM= -github.com/trustbloc/kms-go v1.0.0 h1:uV4J95DXKgpcxEQtRLJ6Aa9nk1CY8cLSUHgSwwzqJIQ= -github.com/trustbloc/kms-go v1.0.0/go.mod h1:1rvrHRuIRT7qLapB0lSpFgy1CjFunx85EyEzcZpIxG8= +github.com/trustbloc/bbs-signature-go v1.0.0 h1:JOKmPRTpjbbGODt71i3wJyiEBcu5XEoeSMQaM0WHR7Q= +github.com/trustbloc/bbs-signature-go v1.0.0/go.mod h1:8xptu/lbVUDACQW10yiHtqATzC2kpTKQk5mKsKTD85Y= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 h1:UA6QlD58VZnSd2EpFJCi9XctBY3naKouBOtjMss4ewc= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9/go.mod h1:qqTm9zd5rGhHSOtC8jjadqM01Od9zcDbUiUYLv+M6ls= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 h1:nNmYk/CX3UrLe4a7qCaMjsc+IWcQdZlJGvY5D2gsewE= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30/go.mod h1:7arOSG9GewtV1WiqYZ23dSZ6haamosSABwyG//cRaXQ= github.com/trustbloc/logutil-go v1.0.0-rc1 h1:rRJbvgQfrlUfyej+mY0nuQJymGqjRW4oZEwKi544F4c= github.com/trustbloc/logutil-go v1.0.0-rc1/go.mod h1:JlxT0oZfNKgIlSNtgc001WEeDMxlnAvOM43gNm8DQVc= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 h1:FG8enh3pfxjxedtKdI7gOMrUQeKMhUlpuXR3O8kGwvg= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269/go.mod h1:047WbpZu3QQ/mRqMO4JBDMUtY9M/LaEHwBJNo7XxdTY= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 h1:GizDlcTPMuOh8HHifl8qp+ohaGMhiIT7k4+NcI/CA/I= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468/go.mod h1:6I4D1Hlf5CpSXBbfOIf58ZPtheyT8ZdsorN2kef2ZxU= github.com/trustbloc/vcs/component/oidc/fosite v0.0.0-20230724110323-79c5330617d6 h1:iqqHGeoI6fXZbjtjvV9OCql7XQtr8P4LQBE9d2j9Ll8= github.com/trustbloc/vcs/component/oidc/fosite v0.0.0-20230724110323-79c5330617d6/go.mod h1:D/dD0ld+XRAt/MjhKnrpaVbaKTe5Zq9uAXONf5c4OxU= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= diff --git a/pkg/cslmanager/cslmanager_test.go b/pkg/cslmanager/cslmanager_test.go index f2fc39129..67d3c1c9b 100644 --- a/pkg/cslmanager/cslmanager_test.go +++ b/pkg/cslmanager/cslmanager_test.go @@ -781,12 +781,14 @@ func validateVCStatus(t *testing.T, cslVCStore *mockCSLVCStore, statusID *creden verifiable.WithJSONLDDocumentLoader(loader)) require.NoError(t, err) - require.Equal(t, existingStatusListVCID, statusListVC.ID) - require.Equal(t, "did:test:abc", statusListVC.Issuer.ID) - require.Equal(t, vcutil.DefVCContext, statusListVC.Context[0]) - require.Equal(t, statustype.StatusList2021Context, statusListVC.Context[1]) - credSubject, ok := statusListVC.Subject.([]verifiable.Subject) - require.True(t, ok) + statusListVCC := statusListVC.Contents() + + require.Equal(t, existingStatusListVCID, statusListVCC.ID) + require.Equal(t, "did:test:abc", statusListVCC.Issuer.ID) + require.Equal(t, vcutil.DefVCContext, statusListVCC.Context[0]) + require.Equal(t, statustype.StatusList2021Context, statusListVCC.Context[1]) + credSubject := statusListVCC.Subject + require.Equal(t, existingStatusListVCID+"#list", credSubject[0].ID) require.Equal(t, statustype.StatusList2021VCSubjectType, credSubject[0].CustomFields["type"].(string)) require.Equal(t, "revocation", credSubject[0].CustomFields[statustype.StatusPurpose].(string)) diff --git a/pkg/doc/vc/crypto/crypto.go b/pkg/doc/vc/crypto/crypto.go index 1c9dbdd0b..b3aea6181 100644 --- a/pkg/doc/vc/crypto/crypto.go +++ b/pkg/doc/vc/crypto/crypto.go @@ -292,18 +292,13 @@ func (c *Crypto) getJWTSignedCredential( signer vc.SignerAlgorithm, jwsAlgo verifiable.JWSAlgorithm, signingKeyID string) (*verifiable.Credential, error) { - claims, err := credential.JWTClaims(false) - if err != nil { - return nil, fmt.Errorf("creating JWT claims for VC: %w", err) - } + var err error - jwt, err := claims.MarshalJWS(jwsAlgo, signer, signingKeyID) + credential, err = credential.CreateSignedJWTVC(false, jwsAlgo, signer, signingKeyID) if err != nil { return nil, fmt.Errorf("MarshalJWS error: %w", err) } - credential.JWT = jwt - return credential, nil } @@ -327,9 +322,13 @@ func (c *Crypto) getSDJWTSignedCredential( return nil, fmt.Errorf("make SDJWT credential error: %w", err) } - credential.JWT = sdjwt + sdCred, err := verifiable.ParseCredential([]byte(sdjwt), verifiable.WithCredDisableValidation(), + verifiable.WithDisabledProofCheck()) + if err != nil { + return nil, fmt.Errorf("reparse SDJWT credential error: %w", err) + } - return credential, nil + return sdCred, nil } // SignPresentation signs a presentation. @@ -358,7 +357,7 @@ func (c *Crypto) SignPresentation(signerData *vc.Signer, vp *verifiable.Presenta err = vp.AddLinkedDataProof(signingCtx, ldprocessor.WithDocumentLoader(c.documentLoader)) if err != nil { - return nil, fmt.Errorf("failed to sign vc: %w", err) + return nil, fmt.Errorf("failed to sign vp: %w", err) } return vp, nil diff --git a/pkg/doc/vc/crypto/crypto_test.go b/pkg/doc/vc/crypto/crypto_test.go index 68857a314..b92c771a0 100644 --- a/pkg/doc/vc/crypto/crypto_test.go +++ b/pkg/doc/vc/crypto/crypto_test.go @@ -56,9 +56,9 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit ) signedVC, err := c.signCredentialLDP( - getTestLDPSigner(), &verifiable.Credential{ID: "http://example.edu/credentials/1872"}) + getTestLDPSigner(), createVC(t, verifiable.CredentialContents{ID: "http://example.edu/credentials/1872"})) require.NoError(t, err) - require.Equal(t, 1, len(signedVC.Proofs)) + require.Equal(t, 1, len(signedVC.Proofs())) }) t.Run("test successful sign credential using opts", func(t *testing.T) { @@ -173,7 +173,7 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit } signedVC, err := c.signCredentialLDP( - vcSigner, &verifiable.Credential{ID: "http://example.edu/credentials/1872"}, + vcSigner, createVC(t, verifiable.CredentialContents{ID: "http://example.edu/credentials/1872"}), tc.signingOpts...) if tc.err != "" { @@ -183,20 +183,20 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit } require.NoError(t, err) - require.Equal(t, 1, len(signedVC.Proofs)) - require.Equal(t, tc.responsePurpose, signedVC.Proofs[0]["proofPurpose"]) - require.Equal(t, tc.responseVerMethod, signedVC.Proofs[0]["verificationMethod"]) - require.NotEmpty(t, signedVC.Proofs[0]["created"]) + require.Equal(t, 1, len(signedVC.Proofs())) + require.Equal(t, tc.responsePurpose, signedVC.Proofs()[0]["proofPurpose"]) + require.Equal(t, tc.responseVerMethod, signedVC.Proofs()[0]["verificationMethod"]) + require.NotEmpty(t, signedVC.Proofs()[0]["created"]) - if signedVC.Proofs[0]["challenge"] != nil { - require.Equal(t, tc.responseChallenge, signedVC.Proofs[0]["challenge"].(string)) + if signedVC.Proofs()[0]["challenge"] != nil { + require.Equal(t, tc.responseChallenge, signedVC.Proofs()[0]["challenge"].(string)) } - if signedVC.Proofs[0]["domain"] != nil { - require.Equal(t, tc.responseDomain, signedVC.Proofs[0]["domain"].(string)) + if signedVC.Proofs()[0]["domain"] != nil { + require.Equal(t, tc.responseDomain, signedVC.Proofs()[0]["domain"].(string)) } - created, err := time.Parse(time.RFC3339, signedVC.Proofs[0]["created"].(string)) + created, err := time.Parse(time.RFC3339, signedVC.Proofs()[0]["created"].(string)) require.NoError(t, err) responseTime := time.Now() @@ -219,7 +219,7 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit p := getTestLDPSigner() p.Creator = "wrongValue" signedVC, err := c.signCredentialLDP( - p, &verifiable.Credential{ID: "http://example.edu/credentials/1872"}) + p, createVC(t, verifiable.CredentialContents{ID: "http://example.edu/credentials/1872"})) require.Error(t, err) require.Contains(t, err.Error(), "verificationMethod value wrongValue should be in did#keyID format") require.Nil(t, signedVC) @@ -240,7 +240,7 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit kms: &mockkms.KeyManager{}, crypto: &cryptomock.Crypto{SignErr: fmt.Errorf("failed to sign")}}, }, - &verifiable.Credential{ID: "http://example.edu/credentials/1872"}) + createVC(t, verifiable.CredentialContents{ID: "http://example.edu/credentials/1872"})) require.Error(t, err) require.Contains(t, err.Error(), "failed to sign vc") require.Nil(t, signedVC) @@ -253,7 +253,7 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit p := getTestLDPSigner() signedVC, err := c.signCredentialLDP( - p, &verifiable.Credential{ID: "http://example.edu/credentials/1872"}, + p, createVC(t, verifiable.CredentialContents{ID: "http://example.edu/credentials/1872"}), WithPurpose("invalid")) require.Error(t, err) require.Contains(t, err.Error(), "proof purpose invalid not supported") @@ -267,7 +267,7 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit p := getTestLDPSigner() signedVC, err := c.signCredentialLDP( - p, &verifiable.Credential{ID: "http://example.edu/credentials/1872"}, + p, createVC(t, verifiable.CredentialContents{ID: "http://example.edu/credentials/1872"}), WithPurpose(CapabilityInvocation)) require.NoError(t, err) require.NotNil(t, signedVC) @@ -280,7 +280,7 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit p := getTestLDPSigner() signedVC, err := c.signCredentialLDP( - p, &verifiable.Credential{ID: "http://example.edu/credentials/1872"}, + p, createVC(t, verifiable.CredentialContents{ID: "http://example.edu/credentials/1872"}), WithPurpose(CapabilityInvocation)) require.NoError(t, err) require.NotNil(t, signedVC) @@ -288,11 +288,11 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit } func TestCrypto_SignCredentialJWT(t *testing.T) { - unsignedVc := verifiable.Credential{ + unsignedVc, err := verifiable.CreateCredential(verifiable.CredentialContents{ ID: "http://example.edu/credentials/1872", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, - Subject: verifiable.Subject{ + Subject: []verifiable.Subject{{ ID: "did:example:ebfeb1f712ebc6f1c276e12ec21", CustomFields: map[string]interface{}{ "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1", @@ -302,19 +302,36 @@ func TestCrypto_SignCredentialJWT(t *testing.T) { "degree": "MIT", }, }, - }, + }}, Issued: &utiltime.TimeWrapper{ Time: time.Now(), }, - Issuer: verifiable.Issuer{ + Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, - CustomFields: map[string]interface{}{ - "first_name": "First name", - "last_name": "Last name", - "info": "Info", + }, map[string]interface{}{ + "first_name": "First name", + "last_name": "Last name", + "info": "Info", + }) + require.NoError(t, err) + + unsignedVcNoSub, err := verifiable.CreateCredential(verifiable.CredentialContents{ + ID: "http://example.edu/credentials/1872", + Context: []string{verifiable.ContextURI}, + Types: []string{verifiable.VCType}, + Issued: &utiltime.TimeWrapper{ + Time: time.Now(), }, - } + Issuer: &verifiable.Issuer{ + ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", + }, + }, map[string]interface{}{ + "first_name": "First name", + "last_name": "Last name", + "info": "Info", + }) + require.NoError(t, err) customKMS := createKMS(t) @@ -352,7 +369,7 @@ func TestCrypto_SignCredentialJWT(t *testing.T) { args: args{ signerData: getJWTSigner(customCrypto, customKMS, keyID), getVC: func() *verifiable.Credential { - return &unsignedVc + return unsignedVc }, opts: nil, }, @@ -368,7 +385,7 @@ func TestCrypto_SignCredentialJWT(t *testing.T) { args: args{ signerData: getJWTSigner(customCrypto, customKMS, keyID), getVC: func() *verifiable.Credential { - return &unsignedVc + return unsignedVc }, opts: []SigningOpts{ WithSignatureType("JsonWebSignature2020"), @@ -388,7 +405,7 @@ func TestCrypto_SignCredentialJWT(t *testing.T) { args: args{ signerData: getSDJWTSigner(customCrypto, customKMS, keyID), getVC: func() *verifiable.Credential { - return &unsignedVc + return unsignedVc }, opts: []SigningOpts{ WithSignatureType("JsonWebSignature2020"), @@ -409,7 +426,7 @@ func TestCrypto_SignCredentialJWT(t *testing.T) { signerData: getSDJWTSigner( &cryptomock.Crypto{SignErr: fmt.Errorf("failed to sign")}, customKMS, keyID), getVC: func() *verifiable.Credential { - return &unsignedVc + return unsignedVc }, opts: []SigningOpts{}, }, @@ -425,7 +442,7 @@ func TestCrypto_SignCredentialJWT(t *testing.T) { args: args{ signerData: getJWTSigner(customCrypto, customKMS, keyID), getVC: func() *verifiable.Credential { - return &unsignedVc + return unsignedVc }, opts: []SigningOpts{}, }, @@ -441,7 +458,7 @@ func TestCrypto_SignCredentialJWT(t *testing.T) { args: args{ signerData: getJWTSigner(customCrypto, customKMS, keyID), getVC: func() *verifiable.Credential { - return &unsignedVc + return unsignedVc }, opts: []SigningOpts{ WithPurpose("keyAgreement"), @@ -461,7 +478,7 @@ func TestCrypto_SignCredentialJWT(t *testing.T) { args: args{ signerData: getJWTSigner(customCrypto, customKMS, keyID), getVC: func() *verifiable.Credential { - return &unsignedVc + return unsignedVc }, opts: []SigningOpts{}, }, @@ -477,9 +494,7 @@ func TestCrypto_SignCredentialJWT(t *testing.T) { args: args{ signerData: getJWTSigner(customCrypto, customKMS, keyID), getVC: func() *verifiable.Credential { - cred := unsignedVc - cred.Subject = nil - return &cred + return unsignedVcNoSub }, opts: []SigningOpts{}, }, @@ -506,7 +521,7 @@ func TestCrypto_SignCredentialJWT(t *testing.T) { KeyType: "unsupported", }, getVC: func() *verifiable.Credential { - return &unsignedVc + return unsignedVc }, opts: []SigningOpts{}, }, @@ -523,7 +538,7 @@ func TestCrypto_SignCredentialJWT(t *testing.T) { signerData: getJWTSigner( &cryptomock.Crypto{SignErr: fmt.Errorf("failed to sign")}, customKMS, keyID), getVC: func() *verifiable.Credential { - return &unsignedVc + return unsignedVc }, opts: []SigningOpts{}, }, @@ -544,10 +559,10 @@ func TestCrypto_SignCredentialJWT(t *testing.T) { if err != nil { return } - if got.JWT == "" { + if !got.IsJWT() { t.Errorf("JWT field empty") } - if len(got.Proofs) > 0 { + if len(got.Proofs()) > 0 { t.Errorf("Proof field is not empty") } }) @@ -571,9 +586,9 @@ func TestCrypto_SignCredentialBBS(t *testing.T) { crypto: &cryptomock.Crypto{}, kms: &mockkms.KeyManager{}, }, - }, &verifiable.Credential{ID: "http://example.edu/credentials/1872"}) + }, createVC(t, verifiable.CredentialContents{ID: "http://example.edu/credentials/1872"})) require.NoError(t, err) - require.Equal(t, 1, len(signedVC.Proofs)) + require.Equal(t, 1, len(signedVC.Proofs())) }) } @@ -643,14 +658,14 @@ func TestSignCredential(t *testing.T) { testutil.DocumentLoader(t), ) - unsignedVC := &verifiable.Credential{ + unsignedVC := createVC(t, verifiable.CredentialContents{ ID: "http://example.edu/credentials/1872", - } + }) signedVC, err := c.SignCredential(getTestLDPSigner(), unsignedVC) require.NoError(t, err) - require.Equal(t, 1, len(signedVC.Proofs)) - require.Empty(t, signedVC.JWT) + require.Equal(t, 1, len(signedVC.Proofs())) + require.False(t, signedVC.IsJWT()) }) t.Run("sign credential LDP Data Integrity - success", func(t *testing.T) { customKMS := createKMS(t) @@ -676,11 +691,11 @@ func TestSignCredential(t *testing.T) { testutil.DocumentLoader(t), ) - unsignedVc := verifiable.Credential{ + unsignedVC := createVCWithCF(t, verifiable.CredentialContents{ ID: "http://example.edu/credentials/1872", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, - Subject: verifiable.Subject{ + Subject: []verifiable.Subject{{ ID: "did:example:ebfeb1f712ebc6f1c276e12ec21", CustomFields: map[string]interface{}{ "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1", @@ -690,24 +705,23 @@ func TestSignCredential(t *testing.T) { "degree": "MIT", }, }, - }, + }}, Issued: &utiltime.TimeWrapper{ Time: time.Now(), }, - Issuer: verifiable.Issuer{ + Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, - CustomFields: map[string]interface{}{ - "first_name": "First name", - "last_name": "Last name", - "info": "Info", - }, - } + }, map[string]interface{}{ + "first_name": "First name", + "last_name": "Last name", + "info": "Info", + }) - signedVC, err := c.SignCredential(getTestLDPDataIntegritySigner(), &unsignedVc) + signedVC, err := c.SignCredential(getTestLDPDataIntegritySigner(), unsignedVC) require.NoError(t, err) - require.Equal(t, 1, len(signedVC.Proofs)) - require.Empty(t, signedVC.JWT) + require.Equal(t, 1, len(signedVC.Proofs())) + require.False(t, signedVC.IsJWT()) }) t.Run("sign credential LDP - error", func(t *testing.T) { c := New( @@ -715,9 +729,9 @@ func TestSignCredential(t *testing.T) { testutil.DocumentLoader(t), ) - unsignedVC := &verifiable.Credential{ + unsignedVC := createVC(t, verifiable.CredentialContents{ ID: "http://example.edu/credentials/1872", - } + }) signedVC, err := c.SignCredential(getTestLDPSigner(), unsignedVC) require.Error(t, err) @@ -729,9 +743,9 @@ func TestSignCredential(t *testing.T) { testutil.DocumentLoader(t), ) - unsignedVC := &verifiable.Credential{ + unsignedVC := createVC(t, verifiable.CredentialContents{ ID: "http://example.edu/credentials/1872", - } + }) signedVC, err := c.SignCredential(&vc.Signer{ DID: "did:trustbloc:abc", @@ -753,16 +767,16 @@ func TestSignCredential(t *testing.T) { testutil.DocumentLoader(t), ) - unsignedVC := &verifiable.Credential{ + unsignedVC := createVC(t, verifiable.CredentialContents{ ID: "http://example.edu/credentials/1872", - Subject: "did:example:76e12ec712ebc6f1c221ebfeb1f", + Subject: []verifiable.Subject{{ID: "did:example:76e12ec712ebc6f1c221ebfeb1f"}}, Issued: &utiltime.TimeWrapper{ Time: time.Now(), }, - Issuer: verifiable.Issuer{ + Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, - } + }) signedVC, err := c.SignCredential(&vc.Signer{ DID: "did:trustbloc:abc", @@ -778,8 +792,8 @@ func TestSignCredential(t *testing.T) { }, unsignedVC) require.NoError(t, err) require.NotNil(t, signedVC) - require.NotEmpty(t, signedVC.JWT) - require.False(t, strings.Contains(signedVC.JWT, common.CombinedFormatSeparator)) + require.True(t, signedVC.IsJWT()) + require.False(t, strings.Contains(signedVC.JWTEnvelope.JWT, common.CombinedFormatSeparator)) }) t.Run("sign credential JWT - error", func(t *testing.T) { c := New( @@ -787,16 +801,16 @@ func TestSignCredential(t *testing.T) { testutil.DocumentLoader(t), ) - unsignedVC := &verifiable.Credential{ + unsignedVC := createVC(t, verifiable.CredentialContents{ ID: "http://example.edu/credentials/1872", - Subject: "did:example:76e12ec712ebc6f1c221ebfeb1f", - Issuer: verifiable.Issuer{ + Subject: []verifiable.Subject{{ID: "did:example:76e12ec712ebc6f1c221ebfeb1f"}}, + Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, Issued: &utiltime.TimeWrapper{ Time: time.Now(), }, - } + }) signedVC, err := c.SignCredential(&vc.Signer{ DID: "did:trustbloc:abc", @@ -1056,3 +1070,18 @@ func TestCrypto_NewJWTSigned(t *testing.T) { }) } } + +func createVC(t *testing.T, vcc verifiable.CredentialContents) *verifiable.Credential { + vc, err := verifiable.CreateCredential(vcc, nil) + require.NoError(t, err) + + return vc +} + +func createVCWithCF(t *testing.T, vcc verifiable.CredentialContents, + cf verifiable.CustomFields) *verifiable.Credential { + vc, err := verifiable.CreateCredential(vcc, cf) + require.NoError(t, err) + + return vc +} diff --git a/pkg/doc/vc/crypto/dataIntegrity.go b/pkg/doc/vc/crypto/dataIntegrity.go index ca1a81c5b..3fa597ee6 100644 --- a/pkg/doc/vc/crypto/dataIntegrity.go +++ b/pkg/doc/vc/crypto/dataIntegrity.go @@ -67,8 +67,8 @@ func (c *Crypto) signCredentialLDPDataIntegrity(signerData *vc.Signer, } // Update VC context for Data Integrity. - if !lo.Contains(vc.Context, dataIntegrityProofContext) { - vc.Context = append(vc.Context, dataIntegrityProofContext) + if !lo.Contains(vc.Contents().Context, dataIntegrityProofContext) { + vc = vc.WithModifiedContext(append(vc.Contents().Context, dataIntegrityProofContext)) } err = vc.AddDataIntegrityProof(signingCtx, diSigner) diff --git a/pkg/doc/vc/crypto/dataIntegrity_test.go b/pkg/doc/vc/crypto/dataIntegrity_test.go index 3c600defd..5b2100053 100644 --- a/pkg/doc/vc/crypto/dataIntegrity_test.go +++ b/pkg/doc/vc/crypto/dataIntegrity_test.go @@ -46,11 +46,11 @@ func TestCrypto_SignCredentialLDPDataIntegrity(t *testing.T) { //nolint:gocognit testSigner := getTestLDPDataIntegritySigner() - unsignedVc := verifiable.Credential{ + unsignedVc, err := verifiable.CreateCredential(verifiable.CredentialContents{ ID: "http://example.edu/credentials/1872", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, - Subject: verifiable.Subject{ + Subject: []verifiable.Subject{{ ID: "did:example:ebfeb1f712ebc6f1c276e12ec21", CustomFields: map[string]interface{}{ "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1", @@ -60,32 +60,32 @@ func TestCrypto_SignCredentialLDPDataIntegrity(t *testing.T) { //nolint:gocognit "degree": "MIT", }, }, - }, + }}, Issued: &utiltime.TimeWrapper{ Time: time.Now(), }, - Issuer: verifiable.Issuer{ + Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, - CustomFields: map[string]interface{}{ - "first_name": "First name", - "last_name": "Last name", - "info": "Info", - }, - } + }, map[string]interface{}{ + "first_name": "First name", + "last_name": "Last name", + "info": "Info", + }) + require.NoError(t, err) t.Run("Success", func(t *testing.T) { - signedVC, err := c.signCredentialLDPDataIntegrity(testSigner, &unsignedVc) + signedVC, err := c.signCredentialLDPDataIntegrity(testSigner, unsignedVc) require.NoError(t, err) - require.Equal(t, 1, len(signedVC.Proofs)) - - require.Equal(t, "DataIntegrityProof", signedVC.Proofs[0]["type"]) - require.Equal(t, "ecdsa-2019", signedVC.Proofs[0]["cryptosuite"]) - require.Equal(t, "#key1", signedVC.Proofs[0]["verificationMethod"]) - require.Equal(t, "assertionMethod", signedVC.Proofs[0]["proofPurpose"]) - require.Empty(t, signedVC.Proofs[0]["challenge"]) - require.Empty(t, signedVC.Proofs[0]["domain"]) - require.NotEmpty(t, signedVC.Proofs[0]["proofValue"]) + require.Equal(t, 1, len(signedVC.Proofs())) + + require.Equal(t, "DataIntegrityProof", signedVC.Proofs()[0]["type"]) + require.Equal(t, "ecdsa-2019", signedVC.Proofs()[0]["cryptosuite"]) + require.Equal(t, "#key1", signedVC.Proofs()[0]["verificationMethod"]) + require.Equal(t, "assertionMethod", signedVC.Proofs()[0]["proofPurpose"]) + require.Empty(t, signedVC.Proofs()[0]["challenge"]) + require.Empty(t, signedVC.Proofs()[0]["domain"]) + require.NotEmpty(t, signedVC.Proofs()[0]["proofValue"]) }) t.Run("Success with options", func(t *testing.T) { @@ -98,7 +98,7 @@ func TestCrypto_SignCredentialLDPDataIntegrity(t *testing.T) { //nolint:gocognit ) now := time.Now() - signedVC, err := testCrypto.signCredentialLDPDataIntegrity(testSigner, &unsignedVc, + signedVC, err := testCrypto.signCredentialLDPDataIntegrity(testSigner, unsignedVc, WithDomain("example.com"), WithChallenge("challenge"), WithCreated(&now), @@ -106,19 +106,21 @@ func TestCrypto_SignCredentialLDPDataIntegrity(t *testing.T) { //nolint:gocognit WithSignatureType("JsonWebSignature2020"), ) require.NoError(t, err) - require.Equal(t, 1, len(signedVC.Proofs)) - - require.Equal(t, "DataIntegrityProof", signedVC.Proofs[0]["type"]) - require.Equal(t, "ecdsa-2019", signedVC.Proofs[0]["cryptosuite"]) - require.Equal(t, "#key1", signedVC.Proofs[0]["verificationMethod"]) - require.Equal(t, "assertionMethod", signedVC.Proofs[0]["proofPurpose"]) - require.Equal(t, "challenge", signedVC.Proofs[0]["challenge"]) - require.Equal(t, "example.com", signedVC.Proofs[0]["domain"]) - require.NotEmpty(t, signedVC.Proofs[0]["proofValue"]) + require.Equal(t, 1, len(signedVC.Proofs())) + + require.Equal(t, "DataIntegrityProof", signedVC.Proofs()[0]["type"]) + require.Equal(t, "ecdsa-2019", signedVC.Proofs()[0]["cryptosuite"]) + require.Equal(t, "#key1", signedVC.Proofs()[0]["verificationMethod"]) + require.Equal(t, "assertionMethod", signedVC.Proofs()[0]["proofPurpose"]) + require.Equal(t, "challenge", signedVC.Proofs()[0]["challenge"]) + require.Equal(t, "example.com", signedVC.Proofs()[0]["domain"]) + require.NotEmpty(t, signedVC.Proofs()[0]["proofValue"]) }) t.Run("Error invalid suite", func(t *testing.T) { - testCredentials := &verifiable.Credential{ID: "http://example.edu/credentials/1872"} + testCredentials, err := verifiable.CreateCredential( + verifiable.CredentialContents{ID: "http://example.edu/credentials/1872"}, nil) + require.NoError(t, err) ariesSigner := getTestLDPDataIntegritySigner() ariesSigner.DataIntegrityProof.SuiteType = "undefined" @@ -138,14 +140,16 @@ func TestCrypto_SignCredentialLDPDataIntegrity(t *testing.T) { //nolint:gocognit }, } - signedVC, err := c.signCredentialLDPDataIntegrity(ariesSigner, &unsignedVc) + signedVC, err := c.signCredentialLDPDataIntegrity(ariesSigner, unsignedVc) require.Nil(t, signedVC) require.Error(t, err) require.ErrorContains(t, err, "some error") }) t.Run("Error add proof", func(t *testing.T) { - testCredentials := &verifiable.Credential{ID: "http://example.edu/credentials/1872"} + testCredentials, err := verifiable.CreateCredential( + verifiable.CredentialContents{ID: "http://example.edu/credentials/1872"}, nil) + require.NoError(t, err) testCrypto := New( &vdrmock.VDRegistry{ diff --git a/pkg/doc/vc/statustype/common.go b/pkg/doc/vc/statustype/common.go index f6dcd52ae..58471da24 100644 --- a/pkg/doc/vc/statustype/common.go +++ b/pkg/doc/vc/statustype/common.go @@ -6,9 +6,26 @@ SPDX-License-Identifier: Apache-2.0 package statustype +import "github.com/trustbloc/vc-go/verifiable" + type credentialSubject struct { ID string `json:"id"` Type string `json:"type"` StatusPurpose string `json:"statusPurpose,omitempty"` EncodedList string `json:"encodedList"` } + +func toVerifiableSubject(subject credentialSubject) []verifiable.Subject { + vcSub := verifiable.Subject{ + ID: subject.ID, + CustomFields: verifiable.CustomFields{ + "type": subject.Type, + "encodedList": subject.EncodedList, + }, + } + if subject.StatusPurpose != "" { + vcSub.CustomFields["statusPurpose"] = subject.StatusPurpose + } + + return []verifiable.Subject{vcSub} +} diff --git a/pkg/doc/vc/statustype/revocationlist2020.go b/pkg/doc/vc/statustype/revocationlist2020.go index fd77d5a84..d7340b6a9 100644 --- a/pkg/doc/vc/statustype/revocationlist2020.go +++ b/pkg/doc/vc/statustype/revocationlist2020.go @@ -105,15 +105,15 @@ func (s *revocationList2020Processor) GetVCContext() string { // CreateVC returns *verifiable.Credential appropriate for RevocationList2020. func (s *revocationList2020Processor) CreateVC(vcID string, listSize int, //nolint:dupl profile *vcapi.Signer) (*verifiable.Credential, error) { - credential := &verifiable.Credential{} - credential.Context = []string{vcutil.DefVCContext, RevocationList2020Context} + vcc := verifiable.CredentialContents{} + vcc.Context = + vcutil.AppendSignatureTypeContext( + []string{vcutil.DefVCContext, RevocationList2020Context}, profile.SignatureType) - vcutil.UpdateSignatureTypeContext(credential, profile.SignatureType) - - credential.ID = vcID - credential.Types = []string{vcType, revocationList2020VCType} - credential.Issuer = verifiable.Issuer{ID: profile.DID} - credential.Issued = utiltime.NewTime(time.Now().UTC()) + vcc.ID = vcID + vcc.Types = []string{vcType, revocationList2020VCType} + vcc.Issuer = &verifiable.Issuer{ID: profile.DID} + vcc.Issued = utiltime.NewTime(time.Now().UTC()) size := listSize @@ -126,11 +126,11 @@ func (s *revocationList2020Processor) CreateVC(vcID string, listSize int, //noli return nil, err } - credential.Subject = &credentialSubject{ - ID: credential.ID + "#list", + vcc.Subject = toVerifiableSubject(credentialSubject{ + ID: vcc.ID + "#list", Type: revocationList2020VCSubjectType, EncodedList: encodeBits, - } + }) - return credential, nil + return verifiable.CreateCredential(vcc, nil) } diff --git a/pkg/doc/vc/statustype/revocationlist2020_test.go b/pkg/doc/vc/statustype/revocationlist2020_test.go index 2e1aa3ed5..ed7c2e56d 100644 --- a/pkg/doc/vc/statustype/revocationlist2020_test.go +++ b/pkg/doc/vc/statustype/revocationlist2020_test.go @@ -98,22 +98,23 @@ func Test_revocationList2020Processor_CreateVC(t *testing.T) { DID: "did:example:123", SignatureType: vcsverifiable.JSONWebSignature2020, }) + vcc := vc.Contents() require.NoError(t, err) - require.Equal(t, "vcID1", vc.ID) + require.Equal(t, "vcID1", vcc.ID) require.Equal(t, []string{ vcutil.DefVCContext, RevocationList2020Context, - "https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json"}, vc.Context) - require.Equal(t, []string{vcType, revocationList2020VCType}, vc.Types) - require.Equal(t, verifiable.Issuer{ID: "did:example:123"}, vc.Issuer) + "https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json"}, vcc.Context) + require.Equal(t, []string{vcType, revocationList2020VCType}, vcc.Types) + require.Equal(t, &verifiable.Issuer{ID: "did:example:123"}, vcc.Issuer) encodeBits, err := bitstring.NewBitString(bitStringSize).EncodeBits() require.NoError(t, err) - require.Equal(t, &credentialSubject{ + require.Equal(t, toVerifiableSubject(credentialSubject{ ID: "vcID1#list", Type: "RevocationList2020", EncodedList: encodeBits, - }, vc.Subject) + }), vcc.Subject) } func Test_revocationList2020Processor_CreateVCStatus(t *testing.T) { diff --git a/pkg/doc/vc/statustype/revocationlist2021.go b/pkg/doc/vc/statustype/revocationlist2021.go index a1341076f..eda5ec0e8 100644 --- a/pkg/doc/vc/statustype/revocationlist2021.go +++ b/pkg/doc/vc/statustype/revocationlist2021.go @@ -109,15 +109,15 @@ func (s *revocationList2021Processor) GetVCContext() string { // CreateVC returns *verifiable.Credential appropriate for StatusList2021v001. func (s *revocationList2021Processor) CreateVC(vcID string, listSize int, //nolint:dupl profile *vcapi.Signer) (*verifiable.Credential, error) { - credential := &verifiable.Credential{} - credential.Context = []string{vcutil.DefVCContext, RevocationList2021Context} + vcc := verifiable.CredentialContents{} + vcc.Context = + vcutil.AppendSignatureTypeContext( + []string{vcutil.DefVCContext, RevocationList2021Context}, profile.SignatureType) - vcutil.UpdateSignatureTypeContext(credential, profile.SignatureType) - - credential.ID = vcID - credential.Types = []string{vcType, statusList2021VCType} - credential.Issuer = verifiable.Issuer{ID: profile.DID} - credential.Issued = utiltime.NewTime(time.Now().UTC()) + vcc.ID = vcID + vcc.Types = []string{vcType, statusList2021VCType} + vcc.Issuer = &verifiable.Issuer{ID: profile.DID} + vcc.Issued = utiltime.NewTime(time.Now().UTC()) size := listSize @@ -130,11 +130,11 @@ func (s *revocationList2021Processor) CreateVC(vcID string, listSize int, //noli return nil, err } - credential.Subject = &credentialSubject{ - ID: credential.ID + "#list", + vcc.Subject = toVerifiableSubject(credentialSubject{ + ID: vcc.ID + "#list", Type: revocationList2021VCSubjectType, EncodedList: encodeBits, - } + }) - return credential, nil + return verifiable.CreateCredential(vcc, nil) } diff --git a/pkg/doc/vc/statustype/revocationlist2021_test.go b/pkg/doc/vc/statustype/revocationlist2021_test.go index b1fbb2c66..dc2f7aedb 100644 --- a/pkg/doc/vc/statustype/revocationlist2021_test.go +++ b/pkg/doc/vc/statustype/revocationlist2021_test.go @@ -98,23 +98,24 @@ func Test_revocationList2021Processor_CreateVC(t *testing.T) { DID: "did:example:123", SignatureType: vcsverifiable.JSONWebSignature2020, }) - require.NoError(t, err) - require.Equal(t, "vcID1", vc.ID) + + vcc := vc.Contents() + require.Equal(t, "vcID1", vcc.ID) require.Equal(t, []string{ vcutil.DefVCContext, "https://w3c-ccg.github.io/vc-revocation-list-2021/contexts/v1.jsonld", "https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json", - }, vc.Context) - require.Equal(t, []string{vcType, statusList2021VCType}, vc.Types) - require.Equal(t, verifiable.Issuer{ID: "did:example:123"}, vc.Issuer) + }, vcc.Context) + require.Equal(t, []string{vcType, statusList2021VCType}, vcc.Types) + require.Equal(t, &verifiable.Issuer{ID: "did:example:123"}, vcc.Issuer) encodeBits, err := bitstring.NewBitString(bitStringSize).EncodeBits() require.NoError(t, err) - require.Equal(t, &credentialSubject{ + require.Equal(t, toVerifiableSubject(credentialSubject{ ID: "vcID1#list", Type: "RevocationList2021", EncodedList: encodeBits, - }, vc.Subject) + }), vcc.Subject) } func Test_revocationList2021Processor_CreateVCStatus(t *testing.T) { diff --git a/pkg/doc/vc/statustype/statuslist2021.go b/pkg/doc/vc/statustype/statuslist2021.go index 5a3b48271..2e72f6117 100644 --- a/pkg/doc/vc/statustype/statuslist2021.go +++ b/pkg/doc/vc/statustype/statuslist2021.go @@ -118,15 +118,15 @@ func (s *statusList2021Processor) GetVCContext() string { // CreateVC returns *verifiable.Credential appropriate for StatusList2021. func (s *statusList2021Processor) CreateVC(vcID string, listSize int, profile *vcapi.Signer) (*verifiable.Credential, error) { - credential := &verifiable.Credential{} - credential.Context = []string{vcutil.DefVCContext, StatusList2021Context} + vcc := verifiable.CredentialContents{} + vcc.Context = + vcutil.AppendSignatureTypeContext( + []string{vcutil.DefVCContext, StatusList2021Context}, profile.SignatureType) - vcutil.UpdateSignatureTypeContext(credential, profile.SignatureType) - - credential.ID = vcID - credential.Types = []string{vcType, statusList2021VCType} - credential.Issuer = verifiable.Issuer{ID: profile.DID} - credential.Issued = utiltime.NewTime(time.Now().UTC()) + vcc.ID = vcID + vcc.Types = []string{vcType, statusList2021VCType} + vcc.Issuer = &verifiable.Issuer{ID: profile.DID} + vcc.Issued = utiltime.NewTime(time.Now().UTC()) size := listSize @@ -139,12 +139,12 @@ func (s *statusList2021Processor) CreateVC(vcID string, listSize int, return nil, err } - credential.Subject = &credentialSubject{ - ID: credential.ID + "#list", + vcc.Subject = toVerifiableSubject(credentialSubject{ + ID: vcc.ID + "#list", Type: StatusList2021VCSubjectType, StatusPurpose: "revocation", EncodedList: encodeBits, - } + }) - return credential, nil + return verifiable.CreateCredential(vcc, nil) } diff --git a/pkg/doc/vc/statustype/statuslist2021_test.go b/pkg/doc/vc/statustype/statuslist2021_test.go index c053658dd..0be02726e 100644 --- a/pkg/doc/vc/statustype/statuslist2021_test.go +++ b/pkg/doc/vc/statustype/statuslist2021_test.go @@ -114,23 +114,26 @@ func Test_statusList2021Processor_CreateVC(t *testing.T) { DID: "did:example:123", SignatureType: vcsverifiable.JSONWebSignature2020, }) + vcc := vc.Contents() require.NoError(t, err) - require.Equal(t, "vcID1", vc.ID) + require.Equal(t, "vcID1", vcc.ID) require.Equal(t, []string{ vcutil.DefVCContext, StatusList2021Context, - "https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json"}, vc.Context) - require.Equal(t, []string{vcType, statusList2021VCType}, vc.Types) - require.Equal(t, verifiable.Issuer{ID: "did:example:123"}, vc.Issuer) + "https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json"}, vcc.Context) + require.Equal(t, []string{vcType, statusList2021VCType}, vcc.Types) + require.Equal(t, &verifiable.Issuer{ID: "did:example:123"}, vcc.Issuer) encodeBits, err := bitstring.NewBitString(bitStringSize).EncodeBits() require.NoError(t, err) - require.Equal(t, &credentialSubject{ - ID: "vcID1#list", - Type: "StatusList2021", - StatusPurpose: "revocation", - EncodedList: encodeBits, - }, vc.Subject) + require.Equal(t, []verifiable.Subject{{ + ID: "vcID1#list", + CustomFields: map[string]interface{}{ + "type": "StatusList2021", + "statusPurpose": "revocation", + "encodedList": encodeBits, + }, + }}, vcc.Subject) } func Test_statusList2021Processor_CreateVCStatus(t *testing.T) { diff --git a/pkg/doc/vc/validate.go b/pkg/doc/vc/validate.go index 57fe311e0..ec3f84ae7 100644 --- a/pkg/doc/vc/validate.go +++ b/pkg/doc/vc/validate.go @@ -13,12 +13,10 @@ import ( "time" jsonld "github.com/piprate/json-gold/ld" - docjsonld "github.com/trustbloc/did-go/doc/ld/validator" "github.com/trustbloc/logutil-go/pkg/log" "github.com/trustbloc/vc-go/jwt" "github.com/trustbloc/vc-go/verifiable" - "github.com/trustbloc/vcs/internal/logfields" vcsverifiable "github.com/trustbloc/vcs/pkg/doc/verifiable" "github.com/trustbloc/vcs/pkg/restapi/resterr" ) @@ -50,7 +48,9 @@ func ValidateCredential( return nil, resterr.NewValidationError(resterr.InvalidValue, "credential", err) } - if checkExpiration && credential.Expired != nil && time.Now().UTC().After(credential.Expired.Time) { + credentialContents := credential.Contents() + + if checkExpiration && credentialContents.Expired != nil && time.Now().UTC().After(credentialContents.Expired.Time) { return nil, resterr.NewValidationError(resterr.InvalidValue, "credential", errors.New("credential expired")) } @@ -59,23 +59,21 @@ func ValidateCredential( // strict credential validation can only be applied to LDP or unsecured JWT. // Means, that in case first argument in verifiable.ParseCredential() is a JWS - // variable externalJWT will not be empty and validation will be skipped. - // So to apply strict validation against JWT/JWS - needs to remove - // credential.JWT field, then convert to bytes and explicitly call validation func. if enforceStrictValidation && isJWT(cred) { // If it's SDJWT - if credential.SDJWTHashAlg != "" { + if credentialContents.SDJWTHashAlg != nil { return validateSDJWTCredential(ctx, credential, documentLoader) } - jwtRepresentation := credential.JWT - credential.JWT = "" - - err = validateCredentialClaims(ctx, credential, documentLoader) + // TODO: should it be only json ld validation as was originally, or also schema validation. + // By default for json-ld we will have both. + err = credential.ValidateCredential( + verifiable.WithJSONLDDocumentLoader(documentLoader), + verifiable.WithStrictValidation(), + verifiable.WithJSONLDValidation()) if err != nil { return nil, fmt.Errorf("failed to validate JWT credential claims: %w", err) } - - credential.JWT = jwtRepresentation } return credential, nil @@ -91,7 +89,10 @@ func validateSDJWTCredential( return nil, fmt.Errorf("failed to create display credential: %w", err) } - err = validateCredentialClaims(ctx, displayCredential, documentLoader) + err = displayCredential.ValidateCredential( + verifiable.WithJSONLDDocumentLoader(documentLoader), + verifiable.WithStrictValidation(), + verifiable.WithJSONLDValidation()) if err != nil { return nil, fmt.Errorf("failed to validate SDJWT credential claims: %w", err) } @@ -99,39 +100,6 @@ func validateSDJWTCredential( return credential, nil } -func validateCredentialClaims( - ctx context.Context, - credential *verifiable.Credential, - documentLoader jsonld.DocumentLoader, -) error { - if logger.IsEnabled(log.DEBUG) { - var claimsKeys []string - for k := range credential.CustomFields { - claimsKeys = append(claimsKeys, k) - } - - logger.Debugc(ctx, "strict validation check", - logfields.WithClaimKeys(claimsKeys), - logfields.WithCredentialID(credential.ID), - ) - } - - credentialBytes, err := credential.MarshalJSON() - if err != nil { - return fmt.Errorf("unable to marshal credential: %w", err) - } - - err = docjsonld.ValidateJSONLD(string(credentialBytes), - docjsonld.WithDocumentLoader(documentLoader), - docjsonld.WithStrictValidation(true), - docjsonld.WithStrictContextURIPosition(baseContext)) - if err != nil { - return fmt.Errorf("crdential validation failed: %w", err) - } - - return nil -} - func isJWT(cred interface{}) bool { str, isStr := cred.(string) diff --git a/pkg/doc/vc/validate_test.go b/pkg/doc/vc/validate_test.go index 7d8392aa6..a1766e181 100644 --- a/pkg/doc/vc/validate_test.go +++ b/pkg/doc/vc/validate_test.go @@ -230,10 +230,13 @@ func TestValidateCredential(t *testing.T) { cred, err := verifiable.ParseCredential([]byte(sampleVCJWT), verifiable.WithDisabledProofCheck(), verifiable.WithJSONLDDocumentLoader(testutil.DocumentLoader(t))) require.NoError(t, err) - claims, err := cred.JWTClaims(false) + + jwsVC, err := cred.CreateSignedJWTVC( + false, verifiable.EdDSA, &signer{privKey}, + cred.Contents().Issuer.ID+"#keys-1") require.NoError(t, err) - jws, err := claims.MarshalJWS(verifiable.EdDSA, &signer{privKey}, cred.Issuer.ID+"#keys-1") + jws, err := jwsVC.ToJWTString() require.NoError(t, err) return jws @@ -250,17 +253,12 @@ func TestValidateCredential(t *testing.T) { cred, err := verifiable.ParseCredential([]byte(sampleVCJWT), verifiable.WithDisabledProofCheck(), verifiable.WithJSONLDDocumentLoader(testutil.DocumentLoader(t))) require.NoError(t, err) - claims, err := cred.JWTClaims(false) - require.NoError(t, err) - jws, err := claims.MarshalJWS(verifiable.EdDSA, &signer{privKey}, cred.Issuer.ID+"#keys-1") + jwsCred, err := cred.CreateSignedJWTVC(false, + verifiable.EdDSA, &signer{privKey}, cred.Contents().Issuer.ID+"#keys-1") require.NoError(t, err) - cred, err = verifiable.ParseCredential([]byte(jws), verifiable.WithDisabledProofCheck(), - verifiable.WithJSONLDDocumentLoader(testutil.DocumentLoader(t))) - require.NoError(t, err) - - return cred + return jwsCred }, wantErr: false, }, @@ -313,9 +311,10 @@ func TestValidateCredential(t *testing.T) { verifiable.WithJSONLDDocumentLoader(testutil.DocumentLoader(t))) require.NoError(t, err) - cred.CustomFields["referenceNumber"] = "11223" + cred.SetCustomField("referenceNumber", "11223") - sdjwt, err := cred.MakeSDJWT(afgojwt.NewEd25519Signer(privKey), cred.Issuer.ID+"#keys-1") + sdjwt, err := cred.MakeSDJWT(afgojwt.NewEd25519Signer(privKey), + cred.Contents().Issuer.ID+"#keys-1") require.NoError(t, err) return sdjwt @@ -354,8 +353,20 @@ func TestValidateCredential(t *testing.T) { t.Errorf("ValidateCredential() error = %v, wantErr %v", err, tt.wantErr) return } + + if err != nil { + return + } + wantVC := tt.want(t) - if !reflect.DeepEqual(got, wantVC) { + + gotObj, err := got.ToUniversalForm() + require.NoError(t, err) + + wantVCObj, err := wantVC.ToUniversalForm() + require.NoError(t, err) + + if !reflect.DeepEqual(gotObj, wantVCObj) { t.Errorf("ValidateCredential() got = %v, want %v", got, wantVC) } }) @@ -398,7 +409,7 @@ func Test_validateSDJWTCredential(t *testing.T) { verifiable.WithJSONLDDocumentLoader(testutil.DocumentLoader(t))) require.NoError(t, err) - cred.CustomFields["referenceNumber"] = "11223" + cred.SetCustomField("referenceNumber", "11223") return cred }, @@ -416,7 +427,7 @@ func Test_validateSDJWTCredential(t *testing.T) { verifiable.WithJSONLDDocumentLoader(testutil.DocumentLoader(t))) require.NoError(t, err) - cred.JWT = "abc" + cred.JWTEnvelope.JWT = "abc" return cred }, diff --git a/pkg/doc/vc/vcutil/vcutil.go b/pkg/doc/vc/vcutil/vcutil.go index 58ecbe39c..f5075ba98 100644 --- a/pkg/doc/vc/vcutil/vcutil.go +++ b/pkg/doc/vc/vcutil/vcutil.go @@ -92,33 +92,37 @@ func DecodeTypedIDFromJSONRaw(typedIDBytes json.RawMessage) ([]verifiable.TypedI return nil, err } -// UpdateIssuer overrides credential issuer for profile if profile.OverwriteIssuer=true or credential issuer is missing. +// CreateIssuer creates credential issuer for profile if profile.OverwriteIssuer=true or credential issuer is missing. // Credential issuer will always be DID. -func UpdateIssuer(credential *verifiable.Credential, issuerDID, issuerName string, overwriteIssuer bool) { - if overwriteIssuer || credential.Issuer.ID == "" { - credential.Issuer = verifiable.Issuer{ - ID: issuerDID, - CustomFields: verifiable.CustomFields{"name": issuerName}, - } +func CreateIssuer(issuerDID, issuerName string) *verifiable.Issuer { + return &verifiable.Issuer{ + ID: issuerDID, + CustomFields: verifiable.CustomFields{"name": issuerName}, } + } -// UpdateSignatureTypeContext updates context for JSONWebSignature2020 and BbsBlsSignature2020. -func UpdateSignatureTypeContext(credential *verifiable.Credential, signatureType vcsverifiable.SignatureType) { +// AppendSignatureTypeContext appends context for JSONWebSignature2020 and BbsBlsSignature2020. +func AppendSignatureTypeContext(context []string, signatureType vcsverifiable.SignatureType, +) []string { if signatureType == vcsverifiable.JSONWebSignature2020 { - credential.Context = append(credential.Context, jsonWebSignature2020Context) + return append(context, jsonWebSignature2020Context) } if signatureType == vcsverifiable.BbsBlsSignature2020 { - credential.Context = append(credential.Context, bbsBlsSignature2020Context) + return append(context, bbsBlsSignature2020Context) } + + return context } // PrependCredentialPrefix prepends prefix to credential.ID. -func PrependCredentialPrefix(credential *verifiable.Credential, prefix string) { - if strings.HasPrefix(credential.ID, prefix) { - return +func PrependCredentialPrefix(credential *verifiable.Credential, prefix string) *verifiable.Credential { + contents := credential.Contents() + + if strings.HasPrefix(contents.ID, prefix) { + return credential } - credential.ID = fmt.Sprintf("%s%s", prefix, credential.ID) + return credential.WithModifiedID(fmt.Sprintf("%s%s", prefix, contents.ID)) } diff --git a/pkg/doc/vc/vcutil/vcutil_test.go b/pkg/doc/vc/vcutil/vcutil_test.go index 7fc8b9a81..0565475c2 100644 --- a/pkg/doc/vc/vcutil/vcutil_test.go +++ b/pkg/doc/vc/vcutil/vcutil_test.go @@ -171,45 +171,24 @@ func TestDecodeTypedIDFromJSONRaw(t *testing.T) { }) } -func TestUpdateIssuer(t *testing.T) { +func TestCreateIssuer(t *testing.T) { issuerDID := "did:example" issuerName := "sample-profile" - // no issuer in credential - vc := &verifiable.Credential{} - - UpdateIssuer(vc, issuerDID, issuerName, false) - require.NotEmpty(t, vc.Issuer) - require.Equal(t, vc.Issuer.ID, issuerDID) - require.Equal(t, vc.Issuer.CustomFields["name"], issuerName) - - // issuer in credential - vc = &verifiable.Credential{Issuer: verifiable.Issuer{ - ID: "sample-issuer-id", - }} - - UpdateIssuer(vc, issuerDID, issuerName, false) - require.NotEmpty(t, vc.Issuer) - require.Equal(t, vc.Issuer.ID, "sample-issuer-id") - require.Empty(t, vc.Issuer.CustomFields) - - // issuer in credential + profile overwrites issuer - UpdateIssuer(vc, issuerDID, issuerName, true) - require.NotEmpty(t, vc.Issuer) - require.Equal(t, vc.Issuer.ID, issuerDID) - require.Equal(t, vc.Issuer.CustomFields["name"], issuerName) + issuer := CreateIssuer(issuerDID, issuerName) + require.NotEmpty(t, issuer) + require.Equal(t, issuer.ID, issuerDID) + require.Equal(t, issuer.CustomFields["name"], issuerName) } -func TestUpdateSignatureTypeContext(t *testing.T) { - vc := &verifiable.Credential{Context: []string{DefVCContext}} +func TestAppendSignatureTypeContext(t *testing.T) { + context := []string{DefVCContext} - require.Len(t, vc.Context, 1) + context = AppendSignatureTypeContext(context, vcsverifiable.JSONWebSignature2020) + require.Len(t, context, 2) - UpdateSignatureTypeContext(vc, vcsverifiable.JSONWebSignature2020) - require.Len(t, vc.Context, 2) - - UpdateSignatureTypeContext(vc, vcsverifiable.BbsBlsSignature2020) - require.Len(t, vc.Context, 3) + context = AppendSignatureTypeContext(context, vcsverifiable.BbsBlsSignature2020) + require.Len(t, context, 3) } func stringToRaw(s string) json.RawMessage { @@ -217,10 +196,13 @@ func stringToRaw(s string) json.RawMessage { } func TestPrependCredentialPrefix(t *testing.T) { - credential := &verifiable.Credential{ID: "did:example:ebfeb1f712ebc6f1c276e12ec21"} + credential, err := verifiable.CreateCredential( + verifiable.CredentialContents{ID: "did:example:ebfeb1f712ebc6f1c276e12ec21"}, + nil) + require.NoError(t, err) - PrependCredentialPrefix(credential, "prefix_") - PrependCredentialPrefix(credential, "prefix_") + credential = PrependCredentialPrefix(credential, "prefix_") + credential = PrependCredentialPrefix(credential, "prefix_") - require.Equal(t, "prefix_did:example:ebfeb1f712ebc6f1c276e12ec21", credential.ID) + require.Equal(t, "prefix_did:example:ebfeb1f712ebc6f1c276e12ec21", credential.Contents().ID) } diff --git a/pkg/internal/testutil/credential.go b/pkg/internal/testutil/credential.go index 755375ce9..e303b521a 100644 --- a/pkg/internal/testutil/credential.go +++ b/pkg/internal/testutil/credential.go @@ -100,9 +100,6 @@ func proveVC( }, jsonld.WithDocumentLoader(loader)) require.NoError(t, err) case vcsverifiable.Jwt: - claims, err := credential.JWTClaims(false) - require.NoError(t, err) - jwsAlgo, err := verifiable.KeyTypeToJWSAlgo(kt) require.NoError(t, err) @@ -124,10 +121,9 @@ func proveVC( credential = vcParsed } else { - jws, err := claims.MarshalJWS(jwsAlgo, suite.NewCryptoSigner(customCrypto, kh), didDoc.VerificationMethod[0].ID) + credential, err = credential.CreateSignedJWTVC( + false, jwsAlgo, suite.NewCryptoSigner(customCrypto, kh), didDoc.VerificationMethod[0].ID) require.NoError(t, err) - - credential.JWT = jws } } diff --git a/pkg/kms/key/creator.go b/pkg/kms/key/creator.go index ef73902bf..624364c38 100644 --- a/pkg/kms/key/creator.go +++ b/pkg/kms/key/creator.go @@ -17,7 +17,7 @@ import ( "github.com/btcsuite/btcd/btcec" jose2 "github.com/go-jose/go-jose/v3" - "github.com/trustbloc/kms-go/crypto/primitive/bbs12381g2pub" + "github.com/trustbloc/bbs-signature-go/bbs12381g2pub" "github.com/trustbloc/kms-go/doc/jose/jwk" "github.com/trustbloc/kms-go/doc/jose/jwk/jwksupport" "github.com/trustbloc/kms-go/doc/util/jwkkid" diff --git a/pkg/kms/key/creator_test.go b/pkg/kms/key/creator_test.go index 1195945b9..378cda13a 100644 --- a/pkg/kms/key/creator_test.go +++ b/pkg/kms/key/creator_test.go @@ -16,8 +16,8 @@ import ( "github.com/trustbloc/kms-go/kms/localkms" "github.com/trustbloc/kms-go/secretlock/noop" + "github.com/trustbloc/bbs-signature-go/bbs12381g2pub" "github.com/trustbloc/did-go/legacy/mem" - "github.com/trustbloc/kms-go/crypto/primitive/bbs12381g2pub" mockkms "github.com/trustbloc/kms-go/mock/kms" "github.com/trustbloc/kms-go/spi/kms" diff --git a/pkg/observability/tracing/wrappers/verifycredential/verifycredential_wrapper.go b/pkg/observability/tracing/wrappers/verifycredential/verifycredential_wrapper.go index ecf41ae58..fbd636301 100644 --- a/pkg/observability/tracing/wrappers/verifycredential/verifycredential_wrapper.go +++ b/pkg/observability/tracing/wrappers/verifycredential/verifycredential_wrapper.go @@ -51,7 +51,7 @@ func (w *Wrapper) VerifyCredential(ctx context.Context, credential *verifiable.C } func (w *Wrapper) ValidateCredentialProof(ctx context.Context, - vcByte []byte, proofChallenge, proofDomain string, vcInVPValidation, isJWT bool) error { + vc *verifiable.Credential, proofChallenge, proofDomain string, vcInVPValidation, isJWT bool) error { ctx, span := w.tracer.Start(ctx, "verifycredential.ValidateCredentialProof") defer span.End() @@ -60,15 +60,15 @@ func (w *Wrapper) ValidateCredentialProof(ctx context.Context, span.SetAttributes(attribute.Bool("vc_in_vp_validation", vcInVPValidation)) span.SetAttributes(attribute.Bool("is_jwt", isJWT)) - return w.svc.ValidateCredentialProof(ctx, vcByte, proofChallenge, proofDomain, vcInVPValidation, isJWT) + return w.svc.ValidateCredentialProof(ctx, vc, proofChallenge, proofDomain, vcInVPValidation, isJWT) } -func (w *Wrapper) ValidateVCStatus(ctx context.Context, vcStatus *verifiable.TypedID, issuer string) error { +func (w *Wrapper) ValidateVCStatus(ctx context.Context, vcStatus *verifiable.TypedID, issuer *verifiable.Issuer) error { ctx, span := w.tracer.Start(ctx, "verifycredential.ValidateCredentialProof") defer span.End() span.SetAttributes(attributeutil.JSON("vc_status", vcStatus)) - span.SetAttributes(attribute.String("issuer", issuer)) + span.SetAttributes(attributeutil.JSON("issuer", issuer)) return w.svc.ValidateVCStatus(ctx, vcStatus, issuer) } diff --git a/pkg/observability/tracing/wrappers/verifycredential/verifycredential_wrapper_test.go b/pkg/observability/tracing/wrappers/verifycredential/verifycredential_wrapper_test.go index c06844e26..70b234df1 100644 --- a/pkg/observability/tracing/wrappers/verifycredential/verifycredential_wrapper_test.go +++ b/pkg/observability/tracing/wrappers/verifycredential/verifycredential_wrapper_test.go @@ -38,11 +38,11 @@ func TestWrapper_ValidateCredentialProof(t *testing.T) { ctrl := gomock.NewController(t) svc := NewMockService(ctrl) - svc.EXPECT().ValidateCredentialProof(gomock.Any(), []byte(""), "proofChallenge", "proofDomain", true, true).Times(1) + svc.EXPECT().ValidateCredentialProof(gomock.Any(), &verifiable.Credential{}, "proofChallenge", "proofDomain", true, true).Times(1) w := Wrap(svc, trace.NewNoopTracerProvider().Tracer("")) - err := w.ValidateCredentialProof(context.Background(), []byte(""), "proofChallenge", "proofDomain", true, true) + err := w.ValidateCredentialProof(context.Background(), &verifiable.Credential{}, "proofChallenge", "proofDomain", true, true) require.NoError(t, err) } @@ -50,11 +50,11 @@ func TestWrapper_ValidateVCStatus(t *testing.T) { ctrl := gomock.NewController(t) svc := NewMockService(ctrl) - svc.EXPECT().ValidateVCStatus(gomock.Any(), &verifiable.TypedID{}, "issuer").Times(1) + svc.EXPECT().ValidateVCStatus(gomock.Any(), &verifiable.TypedID{}, &verifiable.Issuer{ID: "issuer"}).Times(1) w := Wrap(svc, trace.NewNoopTracerProvider().Tracer("")) - err := w.ValidateVCStatus(context.Background(), &verifiable.TypedID{}, "issuer") + err := w.ValidateVCStatus(context.Background(), &verifiable.TypedID{}, &verifiable.Issuer{ID: "issuer"}) require.NoError(t, err) } diff --git a/pkg/restapi/v1/issuer/controller.go b/pkg/restapi/v1/issuer/controller.go index 6cc11c0c8..2791bd3cd 100644 --- a/pkg/restapi/v1/issuer/controller.go +++ b/pkg/restapi/v1/issuer/controller.go @@ -173,7 +173,10 @@ func (c *Controller) issueCredential( enforceStrictValidation = credentialTemplate.Checks.Strict - finalCredentials = c.buildCredentialsFromTemplate(credentialTemplate, profile, body) + finalCredentials, err = c.buildCredentialsFromTemplate(credentialTemplate, profile, body) + if err != nil { + return nil, err + } } credentialParsed, err := c.parseCredential(ctx, finalCredentials, enforceStrictValidation, profile.VCConfig.Format) @@ -228,30 +231,31 @@ func (c *Controller) buildCredentialsFromTemplate( credentialTemplate *profileapi.CredentialTemplate, profile *profileapi.Issuer, body *IssueCredentialData, -) *verifiable.Credential { +) (*verifiable.Credential, error) { contexts := credentialTemplate.Contexts if len(contexts) == 0 { contexts = []string{defaultCtx} } - vcc := &verifiable.Credential{ + vcc := verifiable.CredentialContents{ Context: contexts, ID: uuid.New().URN(), Types: []string{"VerifiableCredential", credentialTemplate.Type}, - Issuer: verifiable.Issuer{ID: profile.SigningDID.DID}, - Subject: verifiable.Subject{ + Issuer: &verifiable.Issuer{ID: profile.SigningDID.DID}, + Subject: []verifiable.Subject{{ ID: profile.SigningDID.DID, CustomFields: *body.Claims, - }, - Issued: utiltime.NewTime(time.Now()), - CustomFields: map[string]interface{}{}, + }}, + Issued: utiltime.NewTime(time.Now()), } + customFields := map[string]interface{}{} + if lo.FromPtr(body.CredentialDescription) != "" { - vcc.CustomFields["description"] = *body.CredentialDescription + customFields["description"] = *body.CredentialDescription } if lo.FromPtr(body.CredentialName) != "" { - vcc.CustomFields["name"] = *body.CredentialName + customFields["name"] = *body.CredentialName } if credentialTemplate.CredentialDefaultExpirationDuration != nil { @@ -260,7 +264,7 @@ func (c *Controller) buildCredentialsFromTemplate( vcc.Expired = utiltime.NewTime(time.Now().Add(365 * 24 * time.Hour)) } - return vcc + return verifiable.CreateCredential(vcc, customFields) } func (c *Controller) parseCredential( @@ -680,7 +684,7 @@ func (c *Controller) validateClaims( //nolint:gocognit credentialTemplate *profileapi.CredentialTemplate, validateJSONLD bool, ) error { - subjects, err := getCredentialSubjects(cred.Subject) + subjects, err := getCredentialSubjects(cred.Contents().Subject) if err != nil { return err } @@ -707,12 +711,12 @@ func (c *Controller) validateJSONLD( sub verifiable.Subject, ) error { var ctx []interface{} - for _, ct := range cred.Context { + for _, ct := range cred.Contents().Context { ctx = append(ctx, ct) } var types []interface{} - for _, t := range cred.Types { + for _, t := range cred.Contents().Types { types = append(types, t) } @@ -754,7 +758,7 @@ func (c *Controller) validateJSONSchema( sub verifiable.Subject, ) error { logger.Debug("Validating credential against JSON schema", - logfields.WithCredentialID(cred.ID), + logfields.WithCredentialID(cred.Contents().ID), logfields.WithCredentialTemplateID(credentialTemplate.ID), logfields.WithJSONSchemaID(credentialTemplate.JSONSchemaID), ) diff --git a/pkg/service/credentialstatus/eventhandler/eventhandler_service.go b/pkg/service/credentialstatus/eventhandler/eventhandler_service.go index 2495c9282..519d59453 100644 --- a/pkg/service/credentialstatus/eventhandler/eventhandler_service.go +++ b/pkg/service/credentialstatus/eventhandler/eventhandler_service.go @@ -102,10 +102,7 @@ func (s *Service) handleEventPayload( return fmt.Errorf("get CSL VC wrapper failed: %w", err) } - cs, ok := clsWrapper.VC.Subject.([]verifiable.Subject) - if !ok { - return fmt.Errorf("failed to cast VC subject") - } + cs := clsWrapper.VC.Contents().Subject bitString, err := bitstring.DecodeBits(cs[0].CustomFields["encodedList"].(string)) if err != nil { @@ -121,8 +118,7 @@ func (s *Service) handleEventPayload( return fmt.Errorf("bitString.EncodeBits failed: %w", err) } - // remove all proofs because we are updating VC - clsWrapper.VC.Proofs = nil + clsWrapper.VC = clsWrapper.VC.WithModifiedSubject(cs) signedCredentialBytes, err := s.signCSL(payload.ProfileID, payload.ProfileVersion, clsWrapper.VC) if err != nil { @@ -164,7 +160,7 @@ func (s *Service) signCSL(profileID, profileVersion string, csl *verifiable.Cred SDJWT: vc.SDJWT{Enable: false}, } - signOpts, err := prepareSigningOpts(signer, csl.Proofs) + signOpts, err := prepareSigningOpts(signer, csl.Proofs()) if err != nil { return nil, fmt.Errorf("prepareSigningOpts failed: %w", err) } diff --git a/pkg/service/credentialstatus/eventhandler/eventhandler_service_test.go b/pkg/service/credentialstatus/eventhandler/eventhandler_service_test.go index ae4615644..6b49a82dc 100644 --- a/pkg/service/credentialstatus/eventhandler/eventhandler_service_test.go +++ b/pkg/service/credentialstatus/eventhandler/eventhandler_service_test.go @@ -66,6 +66,51 @@ const ( "StatusList2021Credential" ] } +}` + cslWrapperBytesInvalidEncodedList = `{ + "vc": { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/vc/status-list/2021/v1" + ], + "credentialSubject": { + "encodedList": "ddddd", + "id": "` + cslURL + `#list", + "statusPurpose": "revocation", + "type": "StatusList2021" + }, + "id": "` + cslURL + `", + "issuanceDate": "2023-03-22T11:34:05.091926539Z", + "issuer": "did:test:abc", + "type": [ + "VerifiableCredential", + "StatusList2021Credential" + ] + } +}` + cslWrapperBytesInvalidProof = `{ + "vc": { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/vc/status-list/2021/v1" + ], + "credentialSubject": { + "encodedList": "H4sIAAAAAAAA_-zAgQAAAACAoP2pF6kAAAAAAAAAAAAAAAAAAACgOgAA__-N53xXgD4AAA", + "id": "` + cslURL + `#list", + "statusPurpose": "revocation", + "type": "StatusList2021" + }, + "id": "` + cslURL + `", + "issuanceDate": "2023-03-22T11:34:05.091926539Z", + "issuer": "did:test:abc", + "type": [ + "VerifiableCredential", + "StatusList2021Credential" + ], + "proof": { + "proofPurpose": 123 + } + } }` ) @@ -88,7 +133,7 @@ func TestService_HandleEvent(t *testing.T) { require.NoError(t, err) cslWrapper.VC = getVerifiedCSL(t, cslWrapper.VCByte, loader, statusBytePositionIndex, false) - err = cslStore.Upsert(ctx, cslWrapper.VC.ID, cslWrapper) + err = cslStore.Upsert(ctx, cslWrapper.VC.Contents().ID, cslWrapper) require.NoError(t, err) event := createStatusUpdatedEvent( @@ -118,7 +163,7 @@ func TestService_HandleEvent(t *testing.T) { require.NoError(t, err) cslWrapper.VC = getVerifiedCSL(t, cslWrapper.VCByte, loader, statusBytePositionIndex, false) - err = cslStore.Upsert(ctx, cslWrapper.VC.ID, cslWrapper) + err = cslStore.Upsert(ctx, cslWrapper.VC.Contents().ID, cslWrapper) require.NoError(t, err) event := createStatusUpdatedEvent( @@ -149,7 +194,7 @@ func TestService_HandleEvent(t *testing.T) { require.NoError(t, err) cslWrapper.VC = getVerifiedCSL(t, cslWrapper.VCByte, loader, statusBytePositionIndex, false) - err = cslStore.Upsert(ctx, cslWrapper.VC.ID, cslWrapper) + err = cslStore.Upsert(ctx, cslWrapper.VC.Contents().ID, cslWrapper) require.NoError(t, err) event := createStatusUpdatedEvent( @@ -193,7 +238,7 @@ func TestService_handleEventPayload(t *testing.T) { require.NoError(t, err) cslWrapper.VC = getVerifiedCSL(t, cslWrapper.VCByte, loader, statusBytePositionIndex, false) - err = cslStore.Upsert(ctx, cslWrapper.VC.ID, cslWrapper) + err = cslStore.Upsert(ctx, cslWrapper.VC.Contents().ID, cslWrapper) require.NoError(t, err) eventPayload := credentialstatus.UpdateCredentialStatusEventPayload{ @@ -251,17 +296,15 @@ func TestService_handleEventPayload(t *testing.T) { cslStore := newMockCSLVCStore() var cslWrapper *credentialstatus.CSLVCWrapper - err := json.Unmarshal([]byte(cslWrapperBytes), &cslWrapper) + err := json.Unmarshal([]byte(cslWrapperBytesInvalidEncodedList), &cslWrapper) require.NoError(t, err) - cslWrapper.VC = getVerifiedCSL(t, cslWrapper.VCByte, loader, statusBytePositionIndex, false) - cslWrapper.VC.Subject.([]verifiable.Subject)[0].CustomFields["encodedList"] = " 123" - cslBytes, err := cslWrapper.VC.MarshalJSON() + cslWrapper.VC, err = verifiable.ParseCredential(cslWrapper.VCByte, + verifiable.WithDisabledProofCheck(), + verifiable.WithJSONLDDocumentLoader(loader)) require.NoError(t, err) - cslWrapper.VCByte = cslBytes - - err = cslStore.Upsert(ctx, cslWrapper.VC.ID, cslWrapper) + err = cslStore.Upsert(ctx, cslWrapper.VC.Contents().ID, cslWrapper) require.NoError(t, err) eventPayload := credentialstatus.UpdateCredentialStatusEventPayload{ @@ -295,7 +338,7 @@ func TestService_handleEventPayload(t *testing.T) { require.NoError(t, err) cslWrapper.VC = getVerifiedCSL(t, cslWrapper.VCByte, loader, statusBytePositionIndex, false) - err = cslStore.Upsert(ctx, cslWrapper.VC.ID, cslWrapper) + err = cslStore.Upsert(ctx, cslWrapper.VC.Contents().ID, cslWrapper) require.NoError(t, err) eventPayload := credentialstatus.UpdateCredentialStatusEventPayload{ @@ -332,7 +375,7 @@ func TestService_handleEventPayload(t *testing.T) { require.NoError(t, err) cslWrapper.VC = getVerifiedCSL(t, cslWrapper.VCByte, loader, statusBytePositionIndex, false) - err = cslStore.Upsert(ctx, cslWrapper.VC.ID, cslWrapper) + err = cslStore.Upsert(ctx, cslWrapper.VC.Contents().ID, cslWrapper) require.NoError(t, err) eventPayload := credentialstatus.UpdateCredentialStatusEventPayload{ @@ -367,7 +410,7 @@ func TestService_handleEventPayload(t *testing.T) { require.NoError(t, err) cslWrapper.VC = getVerifiedCSL(t, cslWrapper.VCByte, loader, statusBytePositionIndex, false) - err = cslStore.Upsert(ctx, cslWrapper.VC.ID, cslWrapper) + err = cslStore.Upsert(ctx, cslWrapper.VC.Contents().ID, cslWrapper) require.NoError(t, err) eventPayload := credentialstatus.UpdateCredentialStatusEventPayload{ @@ -416,7 +459,7 @@ func TestService_signCSL(t *testing.T) { require.NoError(t, err) cslWrapper.VC = getVerifiedCSL(t, cslWrapper.VCByte, loader, statusBytePositionIndex, false) - err = cslStore.Upsert(ctx, cslWrapper.VC.ID, cslWrapper) + err = cslStore.Upsert(ctx, cslWrapper.VC.Contents().ID, cslWrapper) require.NoError(t, err) s := New(&Config{ @@ -463,14 +506,13 @@ func TestService_signCSL(t *testing.T) { t.Run("Error prepareSigningOpts failed", func(t *testing.T) { var cslWrapper *credentialstatus.CSLVCWrapper - err := json.Unmarshal([]byte(cslWrapperBytes), &cslWrapper) + err := json.Unmarshal([]byte(cslWrapperBytesInvalidProof), &cslWrapper) require.NoError(t, err) - cslWrapper.VC = getVerifiedCSL(t, cslWrapper.VCByte, loader, statusBytePositionIndex, false) - cslWrapper.VC.Proofs = []verifiable.Proof{ - { - "proofPurpose": 123, - }, - } + cslWrapper.VC, err = verifiable.ParseCredential(cslWrapper.VCByte, + verifiable.WithDisabledProofCheck(), + verifiable.WithCredDisableValidation(), + verifiable.WithJSONLDDocumentLoader(loader)) + s := New(&Config{ ProfileService: mockProfileSrv, KMSRegistry: mockKMSRegistry, @@ -634,8 +676,7 @@ func getVerifiedCSL( verifiable.WithJSONLDDocumentLoader(dl)) require.NoError(t, err) - credSubject, ok := csl.Subject.([]verifiable.Subject) - require.True(t, ok) + credSubject := csl.Contents().Subject require.NotEmpty(t, credSubject[0].CustomFields["encodedList"].(string)) bitString, err := bitstring.DecodeBits(credSubject[0].CustomFields["encodedList"].(string)) require.NoError(t, err) diff --git a/pkg/service/didconfiguration/didconfiguration_service.go b/pkg/service/didconfiguration/didconfiguration_service.go index 63f8d1367..4bca490b8 100644 --- a/pkg/service/didconfiguration/didconfiguration_service.go +++ b/pkg/service/didconfiguration/didconfiguration_service.go @@ -96,7 +96,7 @@ func (s *Service) DidConfig( profileID string, profileVersion string, ) (*DidConfiguration, error) { - cred := s.getBaseCredentials() + credentialContents := s.getBaseCredentialContents() var format vcsverifiable.Format var signer *vc.Signer @@ -118,13 +118,15 @@ func (s *Service) DidConfig( format = profile.Checks.Credential.Format[0] } - cred.Issuer = verifiable.Issuer{ + credentialContents.Issuer = &verifiable.Issuer{ ID: profile.SigningDID.DID, } - cred.Subject = map[string]interface{}{ - "id": profile.SigningDID.DID, - "origin": profile.URL, - } + credentialContents.Subject = []verifiable.Subject{{ + ID: profile.SigningDID.DID, + CustomFields: map[string]interface{}{ + "origin": profile.URL, + }, + }} kms, err := s.kmsRegistry.GetKeyManager(profile.KMSConfig) @@ -148,13 +150,15 @@ func (s *Service) DidConfig( } format = profile.VCConfig.Format - cred.Issuer = verifiable.Issuer{ + credentialContents.Issuer = &verifiable.Issuer{ ID: profile.SigningDID.DID, } - cred.Subject = map[string]interface{}{ - "id": profile.SigningDID.DID, - "origin": profile.URL, - } + credentialContents.Subject = []verifiable.Subject{{ + ID: profile.SigningDID.DID, + CustomFields: map[string]interface{}{ + "origin": profile.URL, + }, + }} kms, err := s.kmsRegistry.GetKeyManager(profile.KMSConfig) if err != nil { @@ -176,7 +180,12 @@ func (s *Service) DidConfig( return nil, resterr.NewValidationError(resterr.InvalidValue, "profileType", errors.New("profileType should be verifier or issuer")) } - cred, err := s.vcCrypto.SignCredential(signer, cred, []crypto.SigningOpts{}...) + unsignedVC, err := verifiable.CreateCredential(credentialContents, nil) + if err != nil { + return nil, err + } + + cred, err := s.vcCrypto.SignCredential(signer, unsignedVC, []crypto.SigningOpts{}...) if err != nil { return nil, err @@ -187,7 +196,7 @@ func (s *Service) DidConfig( } if format == vcsverifiable.Jwt { - resp.LinkedDiDs = append(resp.LinkedDiDs, cred.JWT) + resp.LinkedDiDs = append(resp.LinkedDiDs, cred.JWTEnvelope.JWT) } else { resp.LinkedDiDs = append(resp.LinkedDiDs, cred) } @@ -195,8 +204,8 @@ func (s *Service) DidConfig( return resp, nil } -func (s *Service) getBaseCredentials() *verifiable.Credential { - return &verifiable.Credential{ +func (s *Service) getBaseCredentialContents() verifiable.CredentialContents { + return verifiable.CredentialContents{ Context: []string{ w3CredentialsURL, didConfigurationContextURL, diff --git a/pkg/service/didconfiguration/didconfiguration_service_test.go b/pkg/service/didconfiguration/didconfiguration_service_test.go index 3c9495002..3f48614fc 100644 --- a/pkg/service/didconfiguration/didconfiguration_service_test.go +++ b/pkg/service/didconfiguration/didconfiguration_service_test.go @@ -157,20 +157,23 @@ func TestDidConfiguration(t *testing.T) { assert.Equal(t, testCase.expectedSigner.KeyType, signer.KeyType) assert.NotNil(t, signer.KMS) + contents := credential.Contents() + assert.Equal(t, []string{ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/.well-known/did-configuration/v1", - }, credential.Context) + }, contents.Context) assert.Equal(t, []string{ "VerifiableCredential", "DomainLinkageCredential", - }, credential.Types) + }, contents.Types) - assert.Equal(t, testCase.expectedIssuer, credential.Issuer.ID) + assert.NotNil(t, contents.Issuer) + assert.Equal(t, testCase.expectedIssuer, contents.Issuer.ID) - credential.JWT = signedJwt - credential.Proofs = []verifiable.Proof{{}} + credential.JWTEnvelope = &verifiable.JWTEnvelope{JWT: signedJwt} + credential.ResetProofs([]verifiable.Proof{{}}) return credential, nil }) @@ -197,8 +200,9 @@ func TestDidConfiguration(t *testing.T) { t.Fatal(errors.New("can not map to *verifiable.Credential")) } - assert.Len(t, cred.Proofs, 1) - assert.Equal(t, testCase.expectedIssuer, cred.Issuer.ID) + assert.Len(t, cred.Proofs(), 1) + assert.NotNil(t, cred.Contents().Issuer) + assert.Equal(t, testCase.expectedIssuer, cred.Contents().Issuer.ID) case vcsverifiable.Jwt: jws, ok := resp.LinkedDiDs[0].(string) diff --git a/pkg/service/issuecredential/issuecredential_service.go b/pkg/service/issuecredential/issuecredential_service.go index f222ed6b2..21d6cf948 100644 --- a/pkg/service/issuecredential/issuecredential_service.go +++ b/pkg/service/issuecredential/issuecredential_service.go @@ -88,23 +88,27 @@ func (s *Service) IssueCredential( var statusListEntry *credentialstatus.StatusListEntry // update credential prefix. - vcutil.PrependCredentialPrefix(credential, defaultCredentialPrefix) + credential = vcutil.PrependCredentialPrefix(credential, defaultCredentialPrefix) + credentialContext := credential.Contents().Context if !profile.VCConfig.Status.Disable { - statusListEntry, err = s.vcStatusManager.CreateStatusListEntry(ctx, profile.ID, profile.Version, credential.ID) + statusListEntry, err = s.vcStatusManager.CreateStatusListEntry( + ctx, profile.ID, profile.Version, credential.Contents().ID) if err != nil { return nil, fmt.Errorf("add credential status: %w", err) } - credential.Context = append(credential.Context, statusListEntry.Context) - credential.Status = statusListEntry.TypedID + credentialContext = append(credentialContext, statusListEntry.Context) + credential = credential. + WithModifiedStatus(statusListEntry.TypedID) } // update context - vcutil.UpdateSignatureTypeContext(credential, profile.VCConfig.SigningAlgorithm) + credentialContext = vcutil.AppendSignatureTypeContext(credentialContext, profile.VCConfig.SigningAlgorithm) + credential = credential.WithModifiedContext(credentialContext) // update credential issuer - vcutil.UpdateIssuer(credential, profile.SigningDID.DID, profile.Name, true) + credential = credential.WithModifiedIssuer(vcutil.CreateIssuer(profile.SigningDID.DID, profile.Name)) // sign the credential signedVC, err := s.crypto.SignCredential(signer, credential, issuerSigningOpts...) diff --git a/pkg/service/issuecredential/issuecredential_service_test.go b/pkg/service/issuecredential/issuecredential_service_test.go index 21e238254..350a327e5 100644 --- a/pkg/service/issuecredential/issuecredential_service_test.go +++ b/pkg/service/issuecredential/issuecredential_service_test.go @@ -126,7 +126,7 @@ func TestService_IssueCredential(t *testing.T) { verifiableCredentials, err := service.IssueCredential( ctx, - getVC(), + getVC(t), nil, &profileapi.Issuer{ VCConfig: &profileapi.VCConfig{ @@ -191,7 +191,7 @@ func TestService_IssueCredential(t *testing.T) { verifiableCredentials, err := service.IssueCredential( ctx, - getVC(), + getVC(t), nil, &profileapi.Issuer{ VCConfig: &profileapi.VCConfig{ @@ -329,24 +329,28 @@ func TestService_IssueCredential(t *testing.T) { }) } -func getVC() *verifiable.Credential { - return &verifiable.Credential{ +func getVC(t *testing.T) *verifiable.Credential { + t.Helper() + + vc, err := verifiable.CreateCredential(verifiable.CredentialContents{ ID: "http://example.edu/credentials/1872", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, - Subject: "did:example:76e12ec712ebc6f1c221ebfeb1f", + Subject: []verifiable.Subject{{ID: "did:example:76e12ec712ebc6f1c221ebfeb1f"}}, Issued: &util.TimeWrapper{ Time: time.Now(), }, - Issuer: verifiable.Issuer{ + Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, - CustomFields: map[string]interface{}{ - "first_name": "First name", - "last_name": "Last name", - "info": "Info", - }, - } + }, map[string]interface{}{ + "first_name": "First name", + "last_name": "Last name", + "info": "Info", + }) + require.NoError(t, err) + + return vc } func validateVC( @@ -355,34 +359,35 @@ func validateVC( sigRepresentation verifiable.SignatureRepresentation, vcFormat vcs.Format) { t.Helper() - require.NotNil(t, vc) - require.NotNil(t, vc.Issuer) - require.Equal(t, "did:trustblock:abc", vc.Issuer.ID) - require.True(t, strings.HasPrefix(vc.ID, "urn:uuid:")) + + vcc := vc.Contents() + require.NotNil(t, vcc.Issuer) + require.Equal(t, "did:trustblock:abc", vcc.Issuer.ID) + require.True(t, strings.HasPrefix(vcc.ID, "urn:uuid:")) if vcFormat == vcs.Jwt { - require.NotEmpty(t, vc.JWT) + require.True(t, vc.IsJWT()) return } - require.Len(t, vc.Proofs, 1) - verificationMethod, ok := vc.Proofs[0]["verificationMethod"] + require.Len(t, vc.Proofs(), 1) + verificationMethod, ok := vc.Proofs()[0]["verificationMethod"] require.True(t, ok) require.Equal(t, verificationMethod, did.VerificationMethod[0].ID) switch sigRepresentation { case verifiable.SignatureProofValue: - proofValue, ok := vc.Proofs[0]["proofValue"] + proofValue, ok := vc.Proofs()[0]["proofValue"] require.True(t, ok) require.NotEmpty(t, proofValue) - jws, ok := vc.Proofs[0]["jws"] + jws, ok := vc.Proofs()[0]["jws"] require.False(t, ok) require.Empty(t, jws) case verifiable.SignatureJWS: - proofValue, ok := vc.Proofs[0]["proofValue"] + proofValue, ok := vc.Proofs()[0]["proofValue"] require.False(t, ok) require.Empty(t, proofValue) - jws, ok := vc.Proofs[0]["jws"] + jws, ok := vc.Proofs()[0]["jws"] require.True(t, ok) require.NotEmpty(t, jws) } diff --git a/pkg/service/oidc4ci/oidc4ci_service.go b/pkg/service/oidc4ci/oidc4ci_service.go index 8a4b38457..7c1628a67 100644 --- a/pkg/service/oidc4ci/oidc4ci_service.go +++ b/pkg/service/oidc4ci/oidc4ci_service.go @@ -464,33 +464,34 @@ func (s *Service) PrepareCredential( } // prepare credential for signing - vc := &verifiable.Credential{ - Context: contexts, - ID: uuid.New().URN(), - Types: []string{"VerifiableCredential", tx.CredentialTemplate.Type}, - Issuer: verifiable.Issuer{ID: tx.DID}, - Issued: util.NewTime(time.Now()), - CustomFields: map[string]interface{}{}, + vcc := verifiable.CredentialContents{ + Context: contexts, + ID: uuid.New().URN(), + Types: []string{"VerifiableCredential", tx.CredentialTemplate.Type}, + Issuer: &verifiable.Issuer{ID: tx.DID}, + Issued: util.NewTime(time.Now()), } + customFields := map[string]interface{}{} + if tx.CredentialDescription != "" { - vc.CustomFields["description"] = tx.CredentialDescription + customFields["description"] = tx.CredentialDescription } if tx.CredentialName != "" { - vc.CustomFields["name"] = tx.CredentialName + customFields["name"] = tx.CredentialName } if tx.CredentialExpiresAt != nil { - vc.Expired = util.NewTime(*tx.CredentialExpiresAt) + vcc.Expired = util.NewTime(*tx.CredentialExpiresAt) } if claimData != nil { - vc.Subject = verifiable.Subject{ + vcc.Subject = []verifiable.Subject{{ ID: req.DID, CustomFields: claimData, - } + }} } else { - vc.Subject = verifiable.Subject{ID: req.DID} + vcc.Subject = []verifiable.Subject{{ID: req.DID}} } tx.State = TransactionStateCredentialsIssued @@ -504,10 +505,15 @@ func (s *Service) PrepareCredential( return nil, errSendEvent } + cred, err := verifiable.CreateCredential(vcc, customFields) + if err != nil { + return nil, fmt.Errorf("create cred: %w", err) + } + return &PrepareCredentialResult{ ProfileID: tx.ProfileID, ProfileVersion: tx.ProfileVersion, - Credential: vc, + Credential: cred, Format: tx.CredentialFormat, OidcFormat: tx.OIDCCredentialFormat, Retry: false, diff --git a/pkg/service/oidc4ci/oidc4ci_service_test.go b/pkg/service/oidc4ci/oidc4ci_service_test.go index 8657210ad..bba51a696 100644 --- a/pkg/service/oidc4ci/oidc4ci_service_test.go +++ b/pkg/service/oidc4ci/oidc4ci_service_test.go @@ -1321,7 +1321,7 @@ func TestService_PrepareCredential(t *testing.T) { }, check: func(t *testing.T, resp *oidc4ci.PrepareCredentialResult, err error) { assert.Equal(t, time.Now().UTC().Add(55*time.Hour).Truncate(time.Hour*24), - resp.Credential.Expired.Time.Truncate(time.Hour*24)) + resp.Credential.Contents().Expired.Time.Truncate(time.Hour*24)) require.NoError(t, err) require.NotNil(t, resp) @@ -1379,11 +1379,11 @@ func TestService_PrepareCredential(t *testing.T) { }, check: func(t *testing.T, resp *oidc4ci.PrepareCredentialResult, err error) { assert.Equal(t, time.Now().UTC().Add(55*time.Hour).Truncate(time.Hour*24), - resp.Credential.Expired.Time.Truncate(time.Hour*24)) + resp.Credential.Contents().Expired.Time.Truncate(time.Hour*24)) - require.Equal(t, resp.Credential.CustomFields["description"], + require.Equal(t, resp.Credential.CustomField("description"), "awesome-description") - require.Equal(t, resp.Credential.CustomFields["name"], + require.Equal(t, resp.Credential.CustomField("name"), "awesome-credential") require.NoError(t, err) require.NotNil(t, resp) diff --git a/pkg/service/oidc4vp/api.go b/pkg/service/oidc4vp/api.go index 0622952be..9136e17aa 100644 --- a/pkg/service/oidc4vp/api.go +++ b/pkg/service/oidc4vp/api.go @@ -34,7 +34,7 @@ type CredentialMetadata struct { Format vcsverifiable.Format `json:"format"` Type []string `json:"type"` SubjectData interface{} `json:"subjectData"` - Issuer verifiable.Issuer `json:"issuer"` + Issuer interface{} `json:"issuer"` IssuanceDate *util.TimeWrapper `json:"issuanceDate,omitempty"` ExpirationDate *util.TimeWrapper `json:"expirationDate,omitempty"` } diff --git a/pkg/service/oidc4vp/oidc4vp_service.go b/pkg/service/oidc4vp/oidc4vp_service.go index 42417b6ba..a71ab8abf 100644 --- a/pkg/service/oidc4vp/oidc4vp_service.go +++ b/pkg/service/oidc4vp/oidc4vp_service.go @@ -413,7 +413,7 @@ func (s *Service) RetrieveClaims(ctx context.Context, tx *Transaction) map[strin for _, cred := range tx.ReceivedClaims.Credentials { credType := vcsverifiable.Ldp - if cred.JWT != "" { + if cred.IsJWT() { credType = vcsverifiable.Jwt } @@ -426,15 +426,29 @@ func (s *Service) RetrieveClaims(ctx context.Context, tx *Transaction) map[strin logger.Debugc(ctx, "RetrieveClaims - failed to CreateDisplayCredential", log.WithError(err)) continue } + credContents := cred.Contents() - result[cred.ID] = CredentialMetadata{ + //TODO: review this code change. This code shouldn't be dependent on how vc-go serialize + // issuer and subject into credential. It has complicated logic like serialize as just string if issuer + // have only id. Any changes or extension of how vc works will affect some internal code, that should be + // isolated from this kind of changes. + subject := lo.Map(credContents.Subject, func(subj verifiable.Subject, index int) verifiable.JSONObject { + return verifiable.SubjectToJSON(subj) + }) + + credMeta := CredentialMetadata{ Format: credType, - Type: cred.Types, - SubjectData: cred.Subject, - Issuer: cred.Issuer, - IssuanceDate: cred.Issued, - ExpirationDate: cred.Expired, + Type: credContents.Types, + SubjectData: subject, + IssuanceDate: credContents.Issued, + ExpirationDate: credContents.Expired, + } + + if credContents.Issuer != nil { + credMeta.Issuer = verifiable.IssuerToJSON(*credContents.Issuer) } + + result[credContents.ID] = credMeta } logger.Debugc(ctx, "RetrieveClaims succeed") @@ -528,15 +542,15 @@ func (s *Service) extractClaimData( } func checkVCSubject(cred *verifiable.Credential, token *ProcessedVPToken) error { - subjectID, err := verifiable.SubjectID(cred.Subject) + subjectID, err := verifiable.SubjectID(cred.Contents().Subject) if err != nil { return fmt.Errorf("fail to parse credential as jwt: %w", err) } - if cred.JWT != "" { + if cred.IsJWT() { // We use this strange code, because cred.JWTClaims(false) not take to account "sub" claim from jwt _, rawClaims, credErr := jwt.Parse( - cred.JWT, + cred.JWTEnvelope.JWT, jwt.WithSignatureVerifier(&noVerifier{}), jwt.WithIgnoreClaimsMapDecoding(true), ) diff --git a/pkg/service/oidc4vp/oidc4vp_service_test.go b/pkg/service/oidc4vp/oidc4vp_service_test.go index b7276cf10..24dae6849 100644 --- a/pkg/service/oidc4vp/oidc4vp_service_test.go +++ b/pkg/service/oidc4vp/oidc4vp_service_test.go @@ -8,6 +8,7 @@ package oidc4vp_test import ( "context" + "crypto" _ "embed" "encoding/json" "errors" @@ -18,6 +19,7 @@ import ( "github.com/golang/mock/gomock" "github.com/google/uuid" "github.com/jinzhu/copier" + "github.com/samber/lo" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -703,10 +705,10 @@ func TestService_RetrieveClaims(t *testing.T) { }}}) require.NotNil(t, claims) - subjects, ok := claims["http://example.gov/credentials/3732"].SubjectData.([]verifiable.Subject) + subjects, ok := claims["http://example.gov/credentials/3732"].SubjectData.([]map[string]interface{}) require.True(t, ok) - require.Equal(t, "did:example:ebfeb1f712ebc6f1c276e12ec21", subjects[0].ID) + require.Equal(t, "did:example:ebfeb1f712ebc6f1c276e12ec21", subjects[0]["id"]) require.NotEmpty(t, claims["http://example.gov/credentials/3732"].Issuer) require.NotEmpty(t, claims["http://example.gov/credentials/3732"].IssuanceDate) @@ -726,10 +728,10 @@ func TestService_RetrieveClaims(t *testing.T) { }}}) require.NotNil(t, claims) - subjects, ok := claims["http://example.gov/credentials/3732"].SubjectData.([]verifiable.Subject) + subjects, ok := claims["http://example.gov/credentials/3732"].SubjectData.([]map[string]interface{}) require.True(t, ok) - require.Equal(t, "did:example:ebfeb1f712ebc6f1c276e12ec21", subjects[0].ID) + require.Equal(t, "did:example:ebfeb1f712ebc6f1c276e12ec21", subjects[0]["id"]) require.NotEmpty(t, claims["http://example.gov/credentials/3732"].Issuer) require.NotEmpty(t, claims["http://example.gov/credentials/3732"].IssuanceDate) @@ -737,9 +739,13 @@ func TestService_RetrieveClaims(t *testing.T) { }) t.Run("Error", func(t *testing.T) { - credential := &verifiable.Credential{ - JWT: "abc", - SDJWTHashAlg: "sha-256", + credential, err := verifiable.CreateCredential(verifiable.CredentialContents{ + SDJWTHashAlg: lo.ToPtr(crypto.SHA384), + }, nil) + require.NoError(t, err) + + credential.JWTEnvelope = &verifiable.JWTEnvelope{ + JWT: "abc", } claims := svc.RetrieveClaims(context.Background(), &oidc4vp.Transaction{ @@ -802,8 +808,8 @@ func newVPWithPD(t *testing.T, keyManager kms.KeyManager, crypto ariescrypto.Cry customType := "CustomType" - expected, issuer, pubKeyFetcher := newSignedJWTVC(t, keyManager, crypto, []string{uri}, "", "") - expected.Types = append(expected.Types, customType) + expected, issuer, pubKeyFetcher := newSignedJWTVC(t, keyManager, crypto, []string{uri}, + "", "", []string{customType}) defs := &presexch.PresentationDefinition{ InputDescriptors: []*presexch.InputDescriptor{{ @@ -828,7 +834,8 @@ func newVPWithPD(t *testing.T, keyManager kms.KeyManager, crypto ariescrypto.Cry func newVPWithPS(t *testing.T, keyManager kms.KeyManager, crypto ariescrypto.Crypto, ps *presexch.PresentationSubmission, value string) ( *verifiable.Presentation, string, vdrapi.Registry) { - expected, issuer, pubKeyFetcher := newSignedJWTVC(t, keyManager, crypto, nil, "degree", value) + expected, issuer, pubKeyFetcher := newSignedJWTVC(t, keyManager, crypto, nil, + "degree", value, []string{}) return newVP(t, ps, expected, @@ -852,18 +859,18 @@ func newVP(t *testing.T, submission *presexch.PresentationSubmission, return vp } -func newVC(issuer string, ctx []string) *verifiable.Credential { - cred := &verifiable.Credential{ +func newVC(issuer string, ctx []string, customTypes []string) verifiable.CredentialContents { + cred := verifiable.CredentialContents{ Context: []string{verifiable.ContextURI}, - Types: []string{verifiable.VCType}, + Types: append([]string{verifiable.VCType}, customTypes...), ID: "http://test.credential.com/123", - Issuer: verifiable.Issuer{ID: issuer}, + Issuer: &verifiable.Issuer{ID: issuer}, Issued: &util.TimeWrapper{ Time: time.Now(), }, - Subject: map[string]interface{}{ - "id": issuer, - }, + Subject: []verifiable.Subject{{ + ID: issuer, + }}, } if ctx != nil { @@ -873,22 +880,23 @@ func newVC(issuer string, ctx []string) *verifiable.Credential { return cred } -func newDegreeVC(issuer string, degreeType string, ctx []string) *verifiable.Credential { - cred := &verifiable.Credential{ +func newDegreeVC(issuer string, degreeType string, ctx []string, customTypes []string) verifiable.CredentialContents { + cred := verifiable.CredentialContents{ Context: []string{verifiable.ContextURI}, - Types: []string{verifiable.VCType}, + Types: append([]string{verifiable.VCType}, customTypes...), ID: uuid.New().String(), - Issuer: verifiable.Issuer{ID: issuer}, + Issuer: &verifiable.Issuer{ID: issuer}, Issued: &util.TimeWrapper{ Time: time.Now(), }, - Subject: map[string]interface{}{ - "id": issuer, - "degree": map[string]interface{}{ - "type": degreeType, - "degree": "MIT", - }, - }, + Subject: []verifiable.Subject{{ + ID: issuer, + CustomFields: map[string]interface{}{ + "degree": map[string]interface{}{ + "type": degreeType, + "degree": "MIT", + }, + }}}, } if ctx != nil { @@ -900,7 +908,7 @@ func newDegreeVC(issuer string, degreeType string, ctx []string) *verifiable.Cre func newSignedJWTVC(t *testing.T, keyManager kms.KeyManager, crypto ariescrypto.Crypto, ctx []string, - vcType string, value string) (*verifiable.Credential, string, vdrapi.Registry) { + vcType string, value string, customTypes []string) (*verifiable.Credential, string, vdrapi.Registry) { t.Helper() keyID, kh, err := keyManager.Create(kms.ED25519Type) @@ -925,28 +933,24 @@ func newSignedJWTVC(t *testing.T, return makeMockDIDResolution(issuer, verificationMethod, did.Authentication), nil }} - var vc *verifiable.Credential + var vcc verifiable.CredentialContents switch vcType { case "degree": - vc = newDegreeVC(issuer, value, ctx) + vcc = newDegreeVC(issuer, value, ctx, customTypes) default: - vc = newVC(issuer, ctx) + vcc = newVC(issuer, ctx, customTypes) } - vc.Issuer = verifiable.Issuer{ID: issuer} - - claims, err := vc.JWTClaims(false) + vc, err := verifiable.CreateCredential(vcc, nil) require.NoError(t, err) jwsAlgo, err := verifiable.KeyTypeToJWSAlgo(kms.ED25519Type) require.NoError(t, err) - jws, err := claims.MarshalJWS(jwsAlgo, signer, verMethod) + vc, err = vc.CreateSignedJWTVC(false, jwsAlgo, signer, verMethod) require.NoError(t, err) - vc.JWT = jws - return vc, issuer, didResolver } diff --git a/pkg/service/verifycredential/api.go b/pkg/service/verifycredential/api.go index cbde4e0bf..3b8c54724 100644 --- a/pkg/service/verifycredential/api.go +++ b/pkg/service/verifycredential/api.go @@ -40,12 +40,12 @@ type ServiceInterface interface { ValidateCredentialProof( ctx context.Context, - vcByte []byte, + credential *verifiable.Credential, proofChallenge, proofDomain string, vcInVPValidation, isJWT bool, ) error - ValidateVCStatus(ctx context.Context, vcStatus *verifiable.TypedID, issuer string) error + ValidateVCStatus(ctx context.Context, vcStatus *verifiable.TypedID, issuer *verifiable.Issuer) error ValidateLinkedDomain(ctx context.Context, signingDID string) error } diff --git a/pkg/service/verifycredential/verifycredential_service.go b/pkg/service/verifycredential/verifycredential_service.go index 1d9d97c75..f1ff8a869 100644 --- a/pkg/service/verifycredential/verifycredential_service.go +++ b/pkg/service/verifycredential/verifycredential_service.go @@ -10,7 +10,6 @@ package verifycredential import ( "context" - "encoding/json" "errors" "fmt" "net/http" @@ -82,12 +81,7 @@ func (s *Service) VerifyCredential(ctx context.Context, credential *verifiable.C } } if checks.Proof { - vcBytes, err := json.Marshal(credential) - if err != nil { - return nil, fmt.Errorf("unexpected error on credential marshal: %w", err) - } - - err = s.ValidateCredentialProof(ctx, vcBytes, opts.Challenge, opts.Domain, false, credential.JWT != "") + err := s.ValidateCredentialProof(ctx, credential, opts.Challenge, opts.Domain, false, credential.IsJWT()) if err != nil { result = append(result, CredentialsVerificationCheckResult{ Check: "proof", @@ -96,11 +90,13 @@ func (s *Service) VerifyCredential(ctx context.Context, credential *verifiable.C } } if checks.Status { - if credential.Status == nil { + credentialContents := credential.Contents() + + if credentialContents.Status == nil { return nil, fmt.Errorf("vc missing status list field") } - err := s.ValidateVCStatus(ctx, credential.Status, credential.Issuer.ID) + err := s.ValidateVCStatus(ctx, credentialContents.Status, credentialContents.Issuer) if err != nil { result = append(result, CredentialsVerificationCheckResult{ Check: "credentialStatus", @@ -112,10 +108,10 @@ func (s *Service) VerifyCredential(ctx context.Context, credential *verifiable.C return result, nil } -func (s *Service) parseAndVerifyVC(vcBytes []byte, isJWT bool) (*verifiable.Credential, error) { +func (s *Service) verifyVC(vc *verifiable.Credential, isJWT bool) error { diVerifier, err := s.getDataIntegrityVerifier() if err != nil { - return nil, fmt.Errorf("get data integrity verifier: %w", err) + return fmt.Errorf("get data integrity verifier: %w", err) } opts := []verifiable.CredentialOpt{ @@ -134,32 +130,33 @@ func (s *Service) parseAndVerifyVC(vcBytes []byte, isJWT bool) (*verifiable.Cred opts = append(opts, verifiable.WithStrictValidation()) } - cred, err := verifiable.ParseCredential(vcBytes, opts...) + err = vc.ValidateCredential(opts...) + if err != nil { + return fmt.Errorf("verifiable credential validation error : %w", err) + } + + err = vc.CheckProof(opts...) if err != nil { - return nil, fmt.Errorf("verifiable credential proof validation error : %w", err) + return fmt.Errorf("verifiable credential proof check error : %w", err) } - return cred, nil + return nil } // ValidateCredentialProof validate credential proof. -func (s *Service) ValidateCredentialProof(_ context.Context, vcByte []byte, proofChallenge, proofDomain string, +func (s *Service) ValidateCredentialProof(_ context.Context, credential *verifiable.Credential, proofChallenge, proofDomain string, vcInVPValidation, isJWT bool) error { // nolint: lll,gocyclo - credential, err := s.parseAndVerifyVC(vcByte, isJWT) - if err != nil { - return err - } - if len(credential.JWT) > 0 { + if credential.IsJWT() { return nil } - if len(credential.Proofs) == 0 { + if len(credential.Proofs()) == 0 { return errors.New("verifiable credential doesn't contains proof") } // TODO https://github.com/trustbloc/vcs/issues/412 figure out the process when vc has more than one proof - proof := credential.Proofs[0] + proof := credential.Proofs()[0] if !vcInVPValidation { // validate challenge @@ -185,8 +182,9 @@ func (s *Service) ValidateCredentialProof(_ context.Context, vcByte []byte, proo return err } + credentialContents := credential.Contents() // validate if issuer matches the controller of verification method - if credential.Issuer.ID != didDoc.ID { + if credentialContents.Issuer == nil || credentialContents.Issuer.ID != didDoc.ID { return fmt.Errorf("controller of verification method doesn't match the issuer") } @@ -198,7 +196,8 @@ func (s *Service) ValidateCredentialProof(_ context.Context, vcByte []byte, proo return nil } -func (s *Service) ValidateVCStatus(ctx context.Context, vcStatus *verifiable.TypedID, issuer string) error { +func (s *Service) ValidateVCStatus(ctx context.Context, vcStatus *verifiable.TypedID, + issuer *verifiable.Issuer) error { vcStatusProcessor, err := s.vcStatusProcessorGetter(vc.StatusType(vcStatus.Type)) if err != nil { return err @@ -223,12 +222,16 @@ func (s *Service) ValidateVCStatus(ctx context.Context, vcStatus *verifiable.Typ return err } - if statusListVC.Issuer.ID != issuer { + statusListVCC := statusListVC.Contents() + + // TODO: check this on review. Previously we compared only issuer ids. So in case if both have empty issuers + // it still consider this as valid situation. Should we keep same behavior? + if statusListVCC.Issuer != nil && issuer != nil && statusListVCC.Issuer.ID != issuer.ID { return fmt.Errorf("issuer of the credential do not match status list vc issuer") } - credSubject, ok := statusListVC.Subject.([]verifiable.Subject) - if !ok { + credSubject := statusListVCC.Subject + if len(credSubject) == 0 { return fmt.Errorf("invalid subject field structure") } diff --git a/pkg/service/verifycredential/verifycredential_service_test.go b/pkg/service/verifycredential/verifycredential_service_test.go index 81fa7a0ba..3824880be 100644 --- a/pkg/service/verifycredential/verifycredential_service_test.go +++ b/pkg/service/verifycredential/verifycredential_service_test.go @@ -74,7 +74,7 @@ func TestService_VerifyCredential(t *testing.T) { loader := testutil.DocumentLoader(t) mockStatusListVCGetter := NewMockStatusListVCResolver(gomock.NewController(t)) mockStatusListVCGetter.EXPECT().Resolve(context.Background(), gomock.Any()).AnyTimes().Return( - &verifiable.Credential{ + createVC(t, verifiable.CredentialContents{ Subject: []verifiable.Subject{{ ID: "", CustomFields: map[string]interface{}{ @@ -83,10 +83,10 @@ func TestService_VerifyCredential(t *testing.T) { "encodedList": "H4sIAAAAAAAA_2IABAAA__-N7wLSAQAAAA", }, }}, - Issuer: verifiable.Issuer{ + Issuer: &verifiable.Issuer{ ID: "did:trustblock:abc", }, - }, nil) + }), nil) tests := []struct { name string @@ -210,7 +210,7 @@ func TestService_VerifyCredential(t *testing.T) { mockStatusListVCGetter := NewMockStatusListVCResolver(gomock.NewController(t)) mockStatusListVCGetter.EXPECT().Resolve( context.Background(), gomock.Any()).AnyTimes().Return( - &verifiable.Credential{ + createVC(t, verifiable.CredentialContents{ Subject: []verifiable.Subject{{ ID: "", CustomFields: map[string]interface{}{ @@ -219,10 +219,10 @@ func TestService_VerifyCredential(t *testing.T) { "encodedList": "H4sIAAAAAAAA_2IABAAA__-N7wLSAQAAAA", }, }}, - Issuer: verifiable.Issuer{ + Issuer: &verifiable.Issuer{ ID: "did:trustblock:abc", }, - }, nil) + }), nil) mockStatusProcessorGetter := &status.MockStatusProcessorGetter{ StatusProcessor: &status.MockVCStatusProcessor{ @@ -253,7 +253,7 @@ func TestService_VerifyCredential(t *testing.T) { failedStatusListGetter := NewMockStatusListVCResolver(gomock.NewController(t)) failedStatusListGetter.EXPECT().Resolve( context.Background(), gomock.Any()).AnyTimes().Return( - &verifiable.Credential{ + createVC(t, verifiable.CredentialContents{ Subject: []verifiable.Subject{{ ID: "", CustomFields: map[string]interface{}{ @@ -262,10 +262,10 @@ func TestService_VerifyCredential(t *testing.T) { "encodedList": "H4sIAAAAAAAA_2ICBAAA__-hjgw8AQAAAA", }, }}, - Issuer: verifiable.Issuer{ + Issuer: &verifiable.Issuer{ ID: "did:trustblock:abc", }, - }, nil) + }), nil) mockStatusProcessorGetter := &status.MockStatusProcessorGetter{ StatusProcessor: &status.MockVCStatusProcessor{ @@ -308,7 +308,7 @@ func TestService_checkVCStatus(t *testing.T) { } type args struct { getVcStatus func() *verifiable.TypedID - issuer string + issuer *verifiable.Issuer } tests := []struct { name string @@ -322,19 +322,20 @@ func TestService_checkVCStatus(t *testing.T) { getStatusListVCGetter: func() statusListVCURIResolver { mockStatusListVCGetter := NewMockStatusListVCResolver(gomock.NewController(t)) mockStatusListVCGetter.EXPECT().Resolve(context.Background(), - "https://example.com/status/1").AnyTimes().Return(&verifiable.Credential{ - Subject: []verifiable.Subject{{ - ID: "", - CustomFields: map[string]interface{}{ - "statusListIndex": "1", - "statusPurpose": "2", - "encodedList": "H4sIAAAAAAAA_2IABAAA__-N7wLSAQAAAA", + "https://example.com/status/1").AnyTimes().Return( + createVC(t, verifiable.CredentialContents{ + Subject: []verifiable.Subject{{ + ID: "", + CustomFields: map[string]interface{}{ + "statusListIndex": "1", + "statusPurpose": "2", + "encodedList": "H4sIAAAAAAAA_2IABAAA__-N7wLSAQAAAA", + }, + }}, + Issuer: &verifiable.Issuer{ + ID: "did:trustblock:abc", }, - }}, - Issuer: verifiable.Issuer{ - ID: "did:trustblock:abc", - }, - }, nil) + }), nil) return mockStatusListVCGetter }, @@ -353,7 +354,7 @@ func TestService_checkVCStatus(t *testing.T) { getVcStatus: func() *verifiable.TypedID { return validVCStatus }, - issuer: "did:trustblock:abc", + issuer: &verifiable.Issuer{ID: "did:trustblock:abc"}, }, wantErr: false, }, @@ -421,7 +422,7 @@ func TestService_checkVCStatus(t *testing.T) { getVcStatus: func() *verifiable.TypedID { return &verifiable.TypedID{} }, - issuer: "did:trustblock:abc", + issuer: &verifiable.Issuer{ID: "did:trustblock:abc"}, }, wantErr: true, }, @@ -445,7 +446,7 @@ func TestService_checkVCStatus(t *testing.T) { getVcStatus: func() *verifiable.TypedID { return &verifiable.TypedID{} }, - issuer: "did:trustblock:abc", + issuer: &verifiable.Issuer{ID: "did:trustblock:abc"}, }, wantErr: true, }, @@ -470,7 +471,7 @@ func TestService_checkVCStatus(t *testing.T) { getVcStatus: func() *verifiable.TypedID { return validVCStatus }, - issuer: "did:trustblock:abc", + issuer: &verifiable.Issuer{ID: "did:trustblock:abc"}, }, wantErr: true, }, @@ -481,12 +482,12 @@ func TestService_checkVCStatus(t *testing.T) { mockStatusListVCGetter := NewMockStatusListVCResolver(gomock.NewController(t)) mockStatusListVCGetter.EXPECT().Resolve( context.Background(), gomock.Any()).AnyTimes().Return( - &verifiable.Credential{ + createVC(t, verifiable.CredentialContents{ Subject: []verifiable.Subject{}, - Issuer: verifiable.Issuer{ + Issuer: &verifiable.Issuer{ ID: "did:trustblock:123", }, - }, nil) + }), nil) return mockStatusListVCGetter }, @@ -502,7 +503,7 @@ func TestService_checkVCStatus(t *testing.T) { getVcStatus: func() *verifiable.TypedID { return validVCStatus }, - issuer: "did:trustblock:abc", + issuer: &verifiable.Issuer{ID: "did:trustblock:abc"}, }, wantErr: true, }, @@ -512,12 +513,12 @@ func TestService_checkVCStatus(t *testing.T) { getStatusListVCGetter: func() statusListVCURIResolver { mockStatusListVCGetter := NewMockStatusListVCResolver(gomock.NewController(t)) mockStatusListVCGetter.EXPECT().Resolve(context.Background(), gomock.Any()).AnyTimes().Return( - &verifiable.Credential{ - Subject: verifiable.Subject{}, - Issuer: verifiable.Issuer{ + createVC(t, verifiable.CredentialContents{ + Subject: []verifiable.Subject{}, + Issuer: &verifiable.Issuer{ ID: "did:trustblock:abc", }, - }, nil) + }), nil) return mockStatusListVCGetter }, @@ -533,7 +534,7 @@ func TestService_checkVCStatus(t *testing.T) { getVcStatus: func() *verifiable.TypedID { return validVCStatus }, - issuer: "did:trustblock:abc", + issuer: &verifiable.Issuer{ID: "did:trustblock:abc"}, }, wantErr: true, }, @@ -543,7 +544,7 @@ func TestService_checkVCStatus(t *testing.T) { getStatusListVCGetter: func() statusListVCURIResolver { mockStatusListVCGetter := NewMockStatusListVCResolver(gomock.NewController(t)) mockStatusListVCGetter.EXPECT().Resolve(context.Background(), gomock.Any()).AnyTimes().Return( - &verifiable.Credential{ + createVC(t, verifiable.CredentialContents{ Subject: []verifiable.Subject{{ ID: "", CustomFields: map[string]interface{}{ @@ -552,10 +553,10 @@ func TestService_checkVCStatus(t *testing.T) { "encodedList": "", }, }}, - Issuer: verifiable.Issuer{ + Issuer: &verifiable.Issuer{ ID: "did:trustblock:abc", }, - }, nil) + }), nil) return mockStatusListVCGetter }, @@ -571,7 +572,7 @@ func TestService_checkVCStatus(t *testing.T) { getVcStatus: func() *verifiable.TypedID { return validVCStatus }, - issuer: "did:trustblock:abc", + issuer: &verifiable.Issuer{ID: "did:trustblock:abc"}, }, wantErr: true, }, @@ -581,7 +582,7 @@ func TestService_checkVCStatus(t *testing.T) { getStatusListVCGetter: func() statusListVCURIResolver { mockStatusListVCGetter := NewMockStatusListVCResolver(gomock.NewController(t)) mockStatusListVCGetter.EXPECT().Resolve(context.Background(), gomock.Any()).AnyTimes().Return( - &verifiable.Credential{ + createVC(t, verifiable.CredentialContents{ Subject: []verifiable.Subject{{ ID: "", CustomFields: map[string]interface{}{ @@ -590,10 +591,10 @@ func TestService_checkVCStatus(t *testing.T) { "encodedList": "H4sIAAAAAAAA_2IABAAA__-N7wLSAQAAAA", }, }}, - Issuer: verifiable.Issuer{ + Issuer: &verifiable.Issuer{ ID: "did:trustblock:abc", }, - }, nil) + }), nil) return mockStatusListVCGetter }, @@ -619,7 +620,7 @@ func TestService_checkVCStatus(t *testing.T) { }, } }, - issuer: "did:trustblock:abc", + issuer: &verifiable.Issuer{ID: "did:trustblock:abc"}, }, wantErr: true, }, @@ -646,7 +647,7 @@ func TestService_ValidateCredentialProof(t *testing.T) { t, []byte(sampleVCJsonLD), kmskeytypes.ED25519Type, verifiable.SignatureProofValue, vcs.Ldp, loader, crypto.AssertionMethod, false) type args struct { - getVcByte func() []byte + credential *verifiable.Credential proofChallenge string proofDomain string vcInVPValidation bool @@ -661,11 +662,7 @@ func TestService_ValidateCredentialProof(t *testing.T) { { name: "ProofChallenge invalid value", args: args{ - getVcByte: func() []byte { - vc := *signedVC - b, _ := vc.MarshalJSON() - return b - }, + credential: signedVC, proofChallenge: "some value", vcInVPValidation: false, }, @@ -674,11 +671,7 @@ func TestService_ValidateCredentialProof(t *testing.T) { { name: "ProofDomain invalid value", args: args{ - getVcByte: func() []byte { - vc := *signedVC - b, _ := vc.MarshalJSON() - return b - }, + credential: signedVC, proofChallenge: crypto.Challenge, proofDomain: "some value", vcInVPValidation: false, @@ -688,24 +681,7 @@ func TestService_ValidateCredentialProof(t *testing.T) { { name: "ProofDomain JWT invalid value", args: args{ - getVcByte: func() []byte { - vc := *signedVC - b, _ := vc.MarshalJSON() - return b - }, - proofChallenge: crypto.Challenge, - proofDomain: "some value", - vcInVPValidation: false, - isJWT: true, - }, - wantErr: true, - }, - { - name: "Invalid credentials", - args: args{ - getVcByte: func() []byte { - return []byte(`{..`) - }, + credential: signedVC, proofChallenge: crypto.Challenge, proofDomain: "some value", vcInVPValidation: false, @@ -722,7 +698,7 @@ func TestService_ValidateCredentialProof(t *testing.T) { } if err := s.ValidateCredentialProof( context.Background(), - tt.args.getVcByte(), + tt.args.credential, tt.args.proofChallenge, tt.args.proofDomain, tt.args.vcInVPValidation, @@ -811,9 +787,6 @@ func Test_DataIntegrity_SignVerify(t *testing.T) { err = vcParsed.AddDataIntegrityProof(signContext, diSigner) require.NoError(t, err) - vcBytes, e := vcParsed.MarshalJSON() - require.NoError(t, e) - t.Run("success", func(t *testing.T) { s := &Service{ documentLoader: docLoader, @@ -822,7 +795,7 @@ func Test_DataIntegrity_SignVerify(t *testing.T) { if err = s.ValidateCredentialProof( context.Background(), - vcBytes, + vcParsed, "mock-challenge", "mock-domain", false, @@ -867,3 +840,9 @@ func createKMS(t *testing.T) *localkms.LocalKMS { return k } +func createVC(t *testing.T, vcc verifiable.CredentialContents) *verifiable.Credential { + vc, err := verifiable.CreateCredential(vcc, nil) + require.NoError(t, err) + + return vc +} diff --git a/pkg/service/verifypresentation/lazy.go b/pkg/service/verifypresentation/lazy.go deleted file mode 100644 index 74dadf3ba..000000000 --- a/pkg/service/verifypresentation/lazy.go +++ /dev/null @@ -1,45 +0,0 @@ -/* -Copyright SecureKey Technologies Inc. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package verifypresentation - -import ( - "encoding/json" - "sync" -) - -type LazyCredential struct { - raw interface{} - serialized []byte - mut sync.Mutex -} - -func NewLazyCredential(raw interface{}) *LazyCredential { - return &LazyCredential{ - raw: raw, - mut: sync.Mutex{}, - } -} - -func (l *LazyCredential) Serialized() ([]byte, error) { - l.mut.Lock() - defer l.mut.Unlock() - if l.serialized != nil { - return l.serialized, nil - } - - vcBytes, err := json.Marshal(l.raw) - if err != nil { - return nil, err - } - - l.serialized = vcBytes - return vcBytes, nil -} - -func (l *LazyCredential) Raw() interface{} { - return l.raw -} diff --git a/pkg/service/verifypresentation/testdata/valid_vp.jsonld b/pkg/service/verifypresentation/testdata/valid_vp.jsonld index 3d0f445c7..fcc1c826b 100644 --- a/pkg/service/verifypresentation/testdata/valid_vp.jsonld +++ b/pkg/service/verifypresentation/testdata/valid_vp.jsonld @@ -12,7 +12,8 @@ { "@context": [ "https://www.w3.org/2018/credentials/v1", - "https://www.w3.org/2018/credentials/examples/v1" + "https://www.w3.org/2018/credentials/examples/v1", + "https://w3id.org/vc/status-list/2021/v1" ], "id": "http://example.edu/credentials/58473", "type": ["VerifiableCredential", "UniversityDegreeCredential"], diff --git a/pkg/service/verifypresentation/verifypresentation_service.go b/pkg/service/verifypresentation/verifypresentation_service.go index d36ee5b78..d8cdc714c 100644 --- a/pkg/service/verifypresentation/verifypresentation_service.go +++ b/pkg/service/verifypresentation/verifypresentation_service.go @@ -12,7 +12,6 @@ import ( "context" "errors" "fmt" - "reflect" "time" "github.com/piprate/json-gold/ld" @@ -20,7 +19,6 @@ import ( "github.com/trustbloc/did-go/doc/ld/validator" vdrapi "github.com/trustbloc/did-go/vdr/api" "github.com/trustbloc/logutil-go/pkg/log" - jsonutil "github.com/trustbloc/vc-go/util/json" "github.com/trustbloc/vc-go/verifiable" "github.com/trustbloc/vcs/internal/logfields" @@ -30,8 +28,8 @@ import ( ) type vcVerifier interface { - ValidateCredentialProof(ctx context.Context, vcByte []byte, proofChallenge, proofDomain string, vcInVPValidation, isJWT bool) error //nolint:lll - ValidateVCStatus(ctx context.Context, vcStatus *verifiable.TypedID, issuer string) error + ValidateCredentialProof(ctx context.Context, vc *verifiable.Credential, proofChallenge, proofDomain string, vcInVPValidation, isJWT bool) error //nolint:lll + ValidateVCStatus(ctx context.Context, vcStatus *verifiable.TypedID, issuer *verifiable.Issuer) error ValidateLinkedDomain(ctx context.Context, signingDID string) error } @@ -74,11 +72,9 @@ func (s *Service) VerifyPresentation( //nolint:funlen,gocognit var result []PresentationVerificationCheckResult - var lazyCredentials []*LazyCredential + var credentials []*verifiable.Credential if presentation != nil { - for _, c := range presentation.Credentials() { - lazyCredentials = append(lazyCredentials, NewLazyCredential(c)) - } + credentials = presentation.Credentials() } var targetPresentation interface{} @@ -103,7 +99,7 @@ func (s *Service) VerifyPresentation( //nolint:funlen,gocognit } if len(profile.Checks.Credential.IssuerTrustList) > 0 { - err := s.checkIssuerTrustList(ctx, lazyCredentials, profile.Checks.Credential.IssuerTrustList) + err := s.checkIssuerTrustList(ctx, credentials, profile.Checks.Credential.IssuerTrustList) if err != nil { result = append(result, PresentationVerificationCheckResult{ Check: "issuerTrustList", @@ -112,7 +108,7 @@ func (s *Service) VerifyPresentation( //nolint:funlen,gocognit } } if profile.Checks.Credential.CredentialExpiry { - err := s.checkCredentialExpiry(ctx, lazyCredentials) + err := s.checkCredentialExpiry(ctx, credentials) if err != nil { result = append(result, PresentationVerificationCheckResult{ Check: "credentialExpiry", @@ -124,7 +120,7 @@ func (s *Service) VerifyPresentation( //nolint:funlen,gocognit if profile.Checks.Credential.Proof { st := time.Now() - err := s.validateCredentialsProof(ctx, presentation.JWT, lazyCredentials) + err := s.validateCredentialsProof(ctx, presentation.JWT, credentials) if err != nil { result = append(result, PresentationVerificationCheckResult{ Check: "credentialProof", @@ -137,7 +133,7 @@ func (s *Service) VerifyPresentation( //nolint:funlen,gocognit if profile.Checks.Credential.Status { st := time.Now() - err := s.validateCredentialsStatus(ctx, lazyCredentials) + err := s.validateCredentialsStatus(ctx, credentials) if err != nil { result = append(result, PresentationVerificationCheckResult{ Check: "credentialStatus", @@ -163,7 +159,7 @@ func (s *Service) VerifyPresentation( //nolint:funlen,gocognit if profile.Checks.Credential.Strict { st := time.Now() - err := s.checkCredentialStrict(ctx, lazyCredentials) + err := s.checkCredentialStrict(ctx, credentials) if err != nil { result = append(result, PresentationVerificationCheckResult{ Check: "credentialStrict", @@ -176,36 +172,24 @@ func (s *Service) VerifyPresentation( //nolint:funlen,gocognit return result, nil } -func (s *Service) checkCredentialStrict(ctx context.Context, lazy []*LazyCredential) error { //nolint:gocognit - for _, input := range lazy { - cred, ok := input.Raw().(*verifiable.Credential) - if !ok { - logger.Warnc(ctx, fmt.Sprintf("can not validate strict. unexpected type %v", - reflect.TypeOf(input).String())) - return nil - } +func (s *Service) checkCredentialStrict(ctx context.Context, credentials []*verifiable.Credential) error { //nolint:gocognit + for _, cred := range credentials { + //TODO: check how bug fixed will affects other code. + // previously if credential was not in format of *verifiable.Credential validations was ignored + // This happened for all json-ld credentials in verifiable.Presentation + + credContents := cred.Contents() var credMap map[string]interface{} var err error - if cred.SDJWTHashAlg != "" { + if credContents.SDJWTHashAlg != nil { credMap, err = cred.CreateDisplayCredentialMap(verifiable.DisplayAllDisclosures()) if err != nil { return err } } else { - cred.JWT = "" - var credentialBytes []byte - - credentialBytes, err = cred.MarshalJSON() - if err != nil { - return fmt.Errorf("unable to marshal credential: %w", err) - } - - credMap, err = jsonutil.ToMap(credentialBytes) - if err != nil { - return err - } + credMap = cred.ToRawJSON() } var claimKeys []string @@ -217,12 +201,12 @@ func (s *Service) checkCredentialStrict(ctx context.Context, lazy []*LazyCredent } } - s.claimKeys[cred.ID] = claimKeys + s.claimKeys[credContents.ID] = claimKeys if logger.IsEnabled(log.DEBUG) { logger.Debugc(ctx, "verifier strict validation check", logfields.WithClaimKeys(claimKeys), - logfields.WithCredentialID(cred.ID), + logfields.WithCredentialID(credContents.ID), ) } @@ -237,15 +221,11 @@ func (s *Service) checkCredentialStrict(ctx context.Context, lazy []*LazyCredent return nil } -func (s *Service) checkCredentialExpiry(ctx context.Context, lazy []*LazyCredential) error { - for _, input := range lazy { - credential, ok := input.Raw().(*verifiable.Credential) - if !ok { - logger.Warnc(ctx, fmt.Sprintf("can not validate expiry. unexpected type %v", - reflect.TypeOf(input.Raw()).String())) - return nil - } - if credential.Expired != nil && time.Now().UTC().After(credential.Expired.Time) { +func (s *Service) checkCredentialExpiry(ctx context.Context, credentials []*verifiable.Credential) error { + for _, credential := range credentials { + + vcc := credential.Contents() + if vcc.Expired != nil && time.Now().UTC().After(vcc.Expired.Time) { return errors.New("credential expired") } } @@ -255,29 +235,17 @@ func (s *Service) checkCredentialExpiry(ctx context.Context, lazy []*LazyCredent func (s *Service) checkIssuerTrustList( _ context.Context, - lazy []*LazyCredential, + credentials []*verifiable.Credential, trustList map[string]profileapi.TrustList, ) error { - for _, input := range lazy { + for _, cred := range credentials { var issuerID string var credTypes []string - switch cred := input.Raw().(type) { - case *verifiable.Credential: - issuerID = cred.Issuer.ID - credTypes = cred.Types - case map[string]interface{}: - issuerID = fmt.Sprint(cred["issuer"]) - cr, ok := cred["type"].([]interface{}) - if ok { - for _, t := range cr { - credTypes = append(credTypes, fmt.Sprint(t)) - } - } - default: - return fmt.Errorf("can not validate issuer trust list. unexpected type %v", - reflect.TypeOf(input.Raw()).String()) + if cred.Contents().Issuer != nil { + issuerID = cred.Contents().Issuer.ID } + credTypes = cred.Contents().Types var finalCredType string if len(credTypes) > 0 { @@ -375,15 +343,10 @@ func (s *Service) validateProofData(vp *verifiable.Presentation, opts *Options) func (s *Service) validateCredentialsProof( ctx context.Context, vpJWT string, - credentials []*LazyCredential, + credentials []*verifiable.Credential, ) error { for _, cred := range credentials { - vcBytes, err := cred.Serialized() - if err != nil { - return err - } - - err = s.vcVerifier.ValidateCredentialProof(ctx, vcBytes, "", "", true, vpJWT != "") + err := s.vcVerifier.ValidateCredentialProof(ctx, cred, "", "", true, vpJWT != "") if err != nil { return err } @@ -394,7 +357,7 @@ func (s *Service) validateCredentialsProof( func (s *Service) validateCredentialsStatus( ctx context.Context, - credentials []*LazyCredential, + credentials []*verifiable.Credential, ) error { for _, cred := range credentials { extractedType, issuer, err := s.extractCredentialStatus(cred) @@ -413,53 +376,14 @@ func (s *Service) validateCredentialsStatus( return nil } -func (s *Service) extractCredentialStatus(cred *LazyCredential) (*verifiable.TypedID, string, error) { +func (s *Service) extractCredentialStatus(cred *verifiable.Credential) (*verifiable.TypedID, *verifiable.Issuer, error) { if cred == nil { - return nil, "", nil + return nil, nil, nil } - if v, ok := cred.Raw().(*verifiable.Credential); ok { - return v.Status, v.Issuer.ID, nil - } - - v, ok := cred.Raw().(map[string]interface{}) - if !ok { - return nil, "", fmt.Errorf("unsupported credential type %v", reflect.TypeOf(cred.Raw()).String()) - } - - var issuerID string - switch issuerData := v["issuer"].(type) { - case map[string]interface{}: - issuerID = fmt.Sprint(issuerData["id"]) - case string: - issuerID = issuerData - } - - status, ok := v["credentialStatus"] - if !ok { - return nil, "", nil - } - - statusMap, ok := status.(map[string]interface{}) - if !ok { - return nil, "", fmt.Errorf("unsupported status list type type %v", reflect.TypeOf(status).String()) - } - - finalObj := &verifiable.TypedID{ - CustomFields: map[string]interface{}{}, - } - for k, val := range statusMap { - switch k { - case "id": - finalObj.ID = fmt.Sprint(val) - case "type": - finalObj.Type = fmt.Sprint(val) - default: - finalObj.CustomFields[k] = val - } - } + credContents := cred.Contents() - return finalObj, issuerID, nil + return credContents.Status, credContents.Issuer, nil } // GetClaimKeys returns credential claim keys. diff --git a/pkg/service/verifypresentation/verifypresentation_service_test.go b/pkg/service/verifypresentation/verifypresentation_service_test.go index 0001f6e61..4f235e83c 100644 --- a/pkg/service/verifypresentation/verifypresentation_service_test.go +++ b/pkg/service/verifypresentation/verifypresentation_service_test.go @@ -784,14 +784,11 @@ func TestService_validateCredentialsProof(t *testing.T) { documentLoader: loader, vcVerifier: tt.fields.getVcVerifier(), } - var lazy []*LazyCredential - for _, c := range tt.args.getVp().Credentials() { - lazy = append(lazy, NewLazyCredential(c)) - } + if err := s.validateCredentialsProof( context.Background(), tt.args.getVp().JWT, - lazy, + tt.args.getVp().Credentials(), ); (err != nil) != tt.wantErr { t.Errorf("validateCredentialsProof() error = %v, wantErr %v", err, tt.wantErr) } @@ -868,11 +865,8 @@ func TestService_validateCredentialsStatus(t *testing.T) { documentLoader: loader, vcVerifier: tt.fields.getVcVerifier(), } - var lazy []*LazyCredential - for _, c := range tt.args.getVp().Credentials() { - lazy = append(lazy, NewLazyCredential(c)) - } - if err := s.validateCredentialsStatus(context.Background(), lazy); (err != nil) != tt.wantErr { + if err := s.validateCredentialsStatus(context.Background(), + tt.args.getVp().Credentials()); (err != nil) != tt.wantErr { t.Errorf("validateCredentialsStatus() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -888,33 +882,10 @@ func TestExtractCredentialStatus(t *testing.T) { assert.NoError(t, err) assert.Empty(t, issuer) }) - - t.Run("invalid type", func(t *testing.T) { - v, issuer, err := s.extractCredentialStatus(NewLazyCredential(555)) - assert.Nil(t, v) - assert.ErrorContains(t, err, "unsupported credential type int") - assert.Empty(t, issuer) - }) - - t.Run("no status list", func(t *testing.T) { - v, issuer, err := s.extractCredentialStatus(NewLazyCredential(map[string]interface{}{})) - assert.Nil(t, v) - assert.NoError(t, err) - assert.Empty(t, issuer) - }) - - t.Run("wrong type of status list", func(t *testing.T) { - v, issuer, err := s.extractCredentialStatus(NewLazyCredential(map[string]interface{}{ - "credentialStatus": "aaabcd", - })) - assert.Nil(t, v) - assert.ErrorContains(t, err, "unsupported status list type type string") - assert.Empty(t, issuer) - }) } func TestCredentialStrict(t *testing.T) { - l := NewLazyCredential(&verifiable.Credential{ + l, err := verifiable.CreateCredential(verifiable.CredentialContents{ ID: "credentialID", Context: []string{ "https://www.w3.org/2018/credentials/v1", @@ -926,11 +897,15 @@ func TestCredentialStrict(t *testing.T) { Subject: []verifiable.Subject{ { CustomFields: map[string]interface{}{ - "type": []string{"VerifiedEmployee"}, + "type": []interface{}{"VerifiedEmployee"}, "degree": "abcd", }, }, }, + }, nil) + assert.NoError(t, err) + + l.JWTEnvelope = &verifiable.JWTEnvelope{ SDJWTDisclosures: []*common.DisclosureClaim{ { Name: "_sd", @@ -940,13 +915,12 @@ func TestCredentialStrict(t *testing.T) { Name: "degreeType", Value: "random", }, - }, - }) + }} s := New(&Config{ DocumentLoader: ld.NewDefaultDocumentLoader(http.DefaultClient), }) - assert.NoError(t, s.checkCredentialStrict(context.TODO(), []*LazyCredential{l})) + assert.NoError(t, s.checkCredentialStrict(context.TODO(), []*verifiable.Credential{l})) assert.ElementsMatch(t, []string{"type", "degree"}, s.GetClaimKeys()["credentialID"]) } @@ -954,38 +928,26 @@ func TestCheckTrustList(t *testing.T) { s := New(&Config{}) t.Run("from credentials v1 trust list", func(t *testing.T) { - cred := &verifiable.Credential{ + credContent := verifiable.CredentialContents{ Types: []string{ "VerifiableCredential", "UniversityDegreeCredential", }, - Issuer: verifiable.Issuer{ + Issuer: &verifiable.Issuer{ ID: "123432123", }} - err := s.checkIssuerTrustList( - context.TODO(), - []*LazyCredential{NewLazyCredential(cred)}, - map[string]profileapi.TrustList{ - "a": {}, - }, - ) - - assert.ErrorContains(t, err, "issuer with id: 123432123 is not a member of trustlist") - }) - - t.Run("invalid type", func(t *testing.T) { - cred := &verifiable.Presentation{} + cred, err := verifiable.CreateCredential(credContent, nil) + assert.NoError(t, err) - err := s.checkIssuerTrustList( + err = s.checkIssuerTrustList( context.TODO(), - []*LazyCredential{NewLazyCredential(cred)}, + []*verifiable.Credential{cred}, map[string]profileapi.TrustList{ "a": {}, }, ) - assert.ErrorContains(t, err, - "can not validate issuer trust list. unexpected type *verifiable.Presentation") + assert.ErrorContains(t, err, "issuer with id: 123432123 is not a member of trustlist") }) } diff --git a/pkg/storage/mongodb/cslindexstore/csl_index_store_test.go b/pkg/storage/mongodb/cslindexstore/csl_index_store_test.go index 5d5cb4c23..4137ac588 100644 --- a/pkg/storage/mongodb/cslindexstore/csl_index_store_test.go +++ b/pkg/storage/mongodb/cslindexstore/csl_index_store_test.go @@ -69,25 +69,25 @@ func TestWrapperStore(t *testing.T) { assert.NoError(t, err) wrapperCreated := &credentialstatus.CSLIndexWrapper{ - CSLURL: vc.ID, + CSLURL: vc.Contents().ID, UsedIndexes: []int{1}, } // Create - Find - err = store.Upsert(ctx, vc.ID, wrapperCreated) + err = store.Upsert(ctx, vc.Contents().ID, wrapperCreated) assert.NoError(t, err) - wrapperFound, err := store.Get(ctx, vc.ID) + wrapperFound, err := store.Get(ctx, vc.Contents().ID) assert.NoError(t, err) compareWrappers(t, wrapperCreated, wrapperFound) // Update - Find wrapperCreated.UsedIndexes = append(wrapperCreated.UsedIndexes, 2) - err = store.Upsert(ctx, vc.ID, wrapperCreated) + err = store.Upsert(ctx, vc.Contents().ID, wrapperCreated) assert.NoError(t, err) - wrapperFound, err = store.Get(ctx, vc.ID) + wrapperFound, err = store.Get(ctx, vc.Contents().ID) assert.NoError(t, err) compareWrappers(t, wrapperCreated, wrapperFound) @@ -100,25 +100,25 @@ func TestWrapperStore(t *testing.T) { assert.NoError(t, err) wrapperCreated := &credentialstatus.CSLIndexWrapper{ - CSLURL: vc.ID, + CSLURL: vc.Contents().ID, UsedIndexes: []int{1}, } // Create - Find - err = store.Upsert(ctx, vc.ID, wrapperCreated) + err = store.Upsert(ctx, vc.Contents().ID, wrapperCreated) assert.NoError(t, err) - wrapperFound, err := store.Get(ctx, vc.ID) + wrapperFound, err := store.Get(ctx, vc.Contents().ID) assert.NoError(t, err) compareWrappers(t, wrapperCreated, wrapperFound) // Update - Find wrapperCreated.UsedIndexes = append(wrapperCreated.UsedIndexes, 2) - err = store.Upsert(ctx, vc.ID, wrapperCreated) + err = store.Upsert(ctx, vc.Contents().ID, wrapperCreated) assert.NoError(t, err) - wrapperFound, err = store.Get(ctx, vc.ID) + wrapperFound, err = store.Get(ctx, vc.Contents().ID) assert.NoError(t, err) compareWrappers(t, wrapperCreated, wrapperFound) diff --git a/pkg/storage/mongodb/cslvcstore/csl_vc_store_test.go b/pkg/storage/mongodb/cslvcstore/csl_vc_store_test.go index 37a884bdc..b2faf7325 100644 --- a/pkg/storage/mongodb/cslvcstore/csl_vc_store_test.go +++ b/pkg/storage/mongodb/cslvcstore/csl_vc_store_test.go @@ -73,16 +73,18 @@ func TestCSLStore(t *testing.T) { } // Create - Find - err = store.Upsert(ctx, vc.ID, wrapperCreated) + err = store.Upsert(ctx, vc.Contents().ID, wrapperCreated) assert.NoError(t, err) - wrapperFound, err := store.Get(ctx, vc.ID) + wrapperFound, err := store.Get(ctx, vc.Contents().ID) assert.NoError(t, err) compareWrappers(t, wrapperCreated, wrapperFound) // Update - Find - vc.Issuer.ID += "_123" + vc = vc.WithModifiedIssuer( + &verifiable.Issuer{ID: vc.Contents().Issuer.ID + "_123"}, + ) vcUpdateBytes, err := vc.MarshalJSON() assert.NoError(t, err) @@ -90,10 +92,10 @@ func TestCSLStore(t *testing.T) { VCByte: vcUpdateBytes, } - err = store.Upsert(ctx, vc.ID, wrapperUpdated) + err = store.Upsert(ctx, vc.Contents().ID, wrapperUpdated) assert.NoError(t, err) - wrapperFound, err = store.Get(ctx, vc.ID) + wrapperFound, err = store.Get(ctx, vc.Contents().ID) assert.NoError(t, err) compareWrappers(t, wrapperUpdated, wrapperFound) @@ -110,16 +112,19 @@ func TestCSLStore(t *testing.T) { } // Create - Find - err = store.Upsert(ctx, vc.ID, wrapperCreated) + err = store.Upsert(ctx, vc.Contents().ID, wrapperCreated) assert.NoError(t, err) - wrapperFound, err := store.Get(ctx, vc.ID) + wrapperFound, err := store.Get(ctx, vc.Contents().ID) assert.NoError(t, err) compareWrappers(t, wrapperCreated, wrapperFound) // Update - Find - vc.Issuer.ID += "_123" + // Update - Find + vc = vc.WithModifiedIssuer( + &verifiable.Issuer{ID: vc.Contents().Issuer.ID + "_123"}, + ) claims, err := vc.JWTClaims(false) assert.NoError(t, err) @@ -132,10 +137,10 @@ func TestCSLStore(t *testing.T) { VCByte: vcBytes, } - err = store.Upsert(ctx, vc.ID, wrapperUpdated) + err = store.Upsert(ctx, vc.Contents().ID, wrapperUpdated) assert.NoError(t, err) - wrapperFound, err = store.Get(ctx, vc.ID) + wrapperFound, err = store.Get(ctx, vc.Contents().ID) assert.NoError(t, err) compareWrappers(t, wrapperUpdated, wrapperFound) diff --git a/pkg/storage/mongodb/vcstatusstore/vc_status_store_test.go b/pkg/storage/mongodb/vcstatusstore/vc_status_store_test.go index aeb2b80c3..583471b30 100644 --- a/pkg/storage/mongodb/vcstatusstore/vc_status_store_test.go +++ b/pkg/storage/mongodb/vcstatusstore/vc_status_store_test.go @@ -67,23 +67,25 @@ func TestVCStatusStore(t *testing.T) { verifiable.WithDisabledProofCheck()) assert.NoError(t, err) + vccExpected := vcExpected.Contents() + ctx := context.Background() // Create. - err = store.Put(ctx, testProfile, testProfileVersion10, vcExpected.ID, vcExpected.Status) + err = store.Put(ctx, testProfile, testProfileVersion10, vccExpected.ID, vccExpected.Status) assert.NoError(t, err) // Find by same profile version. - statusFound, err := store.Get(ctx, testProfile, testProfileVersion10, vcExpected.ID) + statusFound, err := store.Get(ctx, testProfile, testProfileVersion10, vccExpected.ID) assert.NoError(t, err) - if !assert.Equal(t, vcExpected.Status, statusFound) { + if !assert.Equal(t, vccExpected.Status, statusFound) { t.Errorf("VC Status got = %v, want %v", - vcExpected.Status, statusFound) + vccExpected.Status, statusFound) } // Find by different profile version. - statusFound, err = store.Get(ctx, testProfile, testProfileVersion11, vcExpected.ID) + statusFound, err = store.Get(ctx, testProfile, testProfileVersion11, vccExpected.ID) assert.Error(t, err) assert.Empty(t, statusFound) }) diff --git a/pkg/storage/s3/cslvcstore/csl_vc_store_test.go b/pkg/storage/s3/cslvcstore/csl_vc_store_test.go index de02b0eea..e20c4d60d 100644 --- a/pkg/storage/s3/cslvcstore/csl_vc_store_test.go +++ b/pkg/storage/s3/cslvcstore/csl_vc_store_test.go @@ -128,13 +128,14 @@ func TestWrapperStore(t *testing.T) { VCByte: vcBytes, VC: vc, } + vcc := vc.Contents() // Create - Find - err = store.Upsert(ctx, vc.ID, wrapperCreated) + err = store.Upsert(ctx, vcc.ID, wrapperCreated) assert.NoError(t, err) var wrapperFound *credentialstatus.CSLVCWrapper - wrapperFound, err = store.Get(ctx, vc.ID) + wrapperFound, err = store.Get(ctx, vcc.ID) assert.NoError(t, err) compareWrappers(t, wrapperCreated, wrapperFound) @@ -143,10 +144,10 @@ func TestWrapperStore(t *testing.T) { VCByte: vcBytes, } - err = store.Upsert(ctx, vc.ID, wrapperUpdated) + err = store.Upsert(ctx, vcc.ID, wrapperUpdated) assert.NoError(t, err) - wrapperFound, err = store.Get(ctx, vc.ID) + wrapperFound, err = store.Get(ctx, vcc.ID) assert.NoError(t, err) compareWrappers(t, wrapperUpdated, wrapperFound) @@ -155,10 +156,14 @@ func TestWrapperStore(t *testing.T) { t.Run("Unexpected error from s3 client on upsert CSL", func(t *testing.T) { errClient := &mockS3Uploader{m: map[string]*s3.PutObjectInput{}, t: t, putErr: errors.New("some error")} + + vc, err := verifiable.CreateCredential(verifiable.CredentialContents{ID: ""}, nil) + require.NoError(t, err) + wrapperCreated := &credentialstatus.CSLVCWrapper{ - VC: &verifiable.Credential{ID: ""}, + VC: vc, } - err := NewStore(errClient, bucket, region, hostName). + err = NewStore(errClient, bucket, region, hostName). Upsert(context.Background(), "", wrapperCreated) assert.Error(t, err) diff --git a/test/bdd/go.mod b/test/bdd/go.mod index 7510024e0..0211f5660 100644 --- a/test/bdd/go.mod +++ b/test/bdd/go.mod @@ -18,9 +18,9 @@ require ( github.com/samber/lo v1.38.1 github.com/tidwall/gjson v1.14.4 github.com/trustbloc/cmdutil-go v0.0.0-20221125151303-09d42adcc811 - github.com/trustbloc/did-go v1.0.0 + github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 github.com/trustbloc/logutil-go v1.0.0-rc1 - github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 + github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 github.com/trustbloc/vcs v0.1.9-0.20230210204445-f2870a36f0ea github.com/trustbloc/vcs/component/wallet-cli v0.0.0-20230710195911-02aad4f0fcec github.com/trustbloc/vcs/test/stress v0.0.0-00010101000000-000000000000 @@ -58,7 +58,6 @@ require ( github.com/cucumber/gherkin-go/v19 v19.0.3 // indirect github.com/cucumber/messages-go/v16 v16.0.1 // indirect github.com/dave/jennifer v1.6.1 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/deepmap/oapi-codegen v1.11.0 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect @@ -88,7 +87,6 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/henvic/httpretty v0.1.0 // indirect github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 // indirect - github.com/hyperledger/ursa-wrapper-go v0.3.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kawamuray/jsonpath v0.0.0-20201211160320-7483bafabd7e // indirect @@ -122,7 +120,6 @@ require ( github.com/pelletier/go-toml/v2 v2.0.9 // indirect github.com/piprate/json-gold v0.5.1-0.20230111113000-6ddbe6e6f19f // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pquerna/cachecontrol v0.1.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect @@ -135,14 +132,14 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.16.0 // indirect github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693 // indirect - github.com/stretchr/testify v1.8.4 // indirect github.com/subosito/gotenv v1.4.2 // indirect github.com/syndtr/goleveldb v1.0.0 // indirect github.com/teserakt-io/golang-ed25519 v0.0.0-20210104091850-3888c087a4c8 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect - github.com/trustbloc/kms-go v1.0.0 // indirect + github.com/trustbloc/bbs-signature-go v1.0.0 // indirect + github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 // indirect github.com/trustbloc/sidetree-core-go v1.0.0 // indirect github.com/trustbloc/vcs/component/oidc/fosite v0.0.0-20230724110323-79c5330617d6 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect diff --git a/test/bdd/go.sum b/test/bdd/go.sum index 94136f554..6d525994e 100644 --- a/test/bdd/go.sum +++ b/test/bdd/go.sum @@ -407,8 +407,6 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 h1:B1Nt8hKb//KvgGRprk0h1t4lCnwhE9/ryb1WqfZbV+M= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2/go.mod h1:X+DIyUsaTmalOpmpQfIvFZjKHQedrURQ5t4YqquX7lE= -github.com/hyperledger/ursa-wrapper-go v0.3.1 h1:Do+QrVNniY77YK2jTIcyWqj9rm/Yb5SScN0bqCjiibA= -github.com/hyperledger/ursa-wrapper-go v0.3.1/go.mod h1:nPSAuMasIzSVciQo22PedBk4Opph6bJ6ia3ms7BH/mk= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= @@ -690,18 +688,20 @@ github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhso github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/trustbloc/bbs-signature-go v1.0.0 h1:JOKmPRTpjbbGODt71i3wJyiEBcu5XEoeSMQaM0WHR7Q= +github.com/trustbloc/bbs-signature-go v1.0.0/go.mod h1:8xptu/lbVUDACQW10yiHtqATzC2kpTKQk5mKsKTD85Y= github.com/trustbloc/cmdutil-go v0.0.0-20221125151303-09d42adcc811 h1:0e1d1w9o662+e7ZnJvRYJH8yblcBXngme8qbsjTvhQc= github.com/trustbloc/cmdutil-go v0.0.0-20221125151303-09d42adcc811/go.mod h1:o/v7C1z6d/5UrjaC6GAUc1hk0XVuE3M4tpyvsMMUw5k= -github.com/trustbloc/did-go v1.0.0 h1:emrE2iG7/sQ2ZIPg60FnNIfe1dTAVG3A/Ls0i8jHO10= -github.com/trustbloc/did-go v1.0.0/go.mod h1:+A6OLKYBSh5cGjc6qk3KZ1DXOAlfIjdUwqz+tzcjOKM= -github.com/trustbloc/kms-go v1.0.0 h1:uV4J95DXKgpcxEQtRLJ6Aa9nk1CY8cLSUHgSwwzqJIQ= -github.com/trustbloc/kms-go v1.0.0/go.mod h1:1rvrHRuIRT7qLapB0lSpFgy1CjFunx85EyEzcZpIxG8= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 h1:UA6QlD58VZnSd2EpFJCi9XctBY3naKouBOtjMss4ewc= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9/go.mod h1:qqTm9zd5rGhHSOtC8jjadqM01Od9zcDbUiUYLv+M6ls= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 h1:nNmYk/CX3UrLe4a7qCaMjsc+IWcQdZlJGvY5D2gsewE= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30/go.mod h1:7arOSG9GewtV1WiqYZ23dSZ6haamosSABwyG//cRaXQ= github.com/trustbloc/logutil-go v1.0.0-rc1 h1:rRJbvgQfrlUfyej+mY0nuQJymGqjRW4oZEwKi544F4c= github.com/trustbloc/logutil-go v1.0.0-rc1/go.mod h1:JlxT0oZfNKgIlSNtgc001WEeDMxlnAvOM43gNm8DQVc= github.com/trustbloc/sidetree-core-go v1.0.0 h1:kzfKZOJ0sgDy9D1AYNcoR3JHutqtMtKvF2P9UwUcDjU= github.com/trustbloc/sidetree-core-go v1.0.0/go.mod h1:jdxAFuorlIwFOGVW6O455/lZqxg2mZkRHNTEolcZdDI= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 h1:FG8enh3pfxjxedtKdI7gOMrUQeKMhUlpuXR3O8kGwvg= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269/go.mod h1:047WbpZu3QQ/mRqMO4JBDMUtY9M/LaEHwBJNo7XxdTY= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 h1:GizDlcTPMuOh8HHifl8qp+ohaGMhiIT7k4+NcI/CA/I= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468/go.mod h1:6I4D1Hlf5CpSXBbfOIf58ZPtheyT8ZdsorN2kef2ZxU= github.com/trustbloc/vcs/component/oidc/fosite v0.0.0-20230724110323-79c5330617d6 h1:iqqHGeoI6fXZbjtjvV9OCql7XQtr8P4LQBE9d2j9Ll8= github.com/trustbloc/vcs/component/oidc/fosite v0.0.0-20230724110323-79c5330617d6/go.mod h1:D/dD0ld+XRAt/MjhKnrpaVbaKTe5Zq9uAXONf5c4OxU= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= diff --git a/test/bdd/pkg/v1/oidc4vc/oidc4ci.go b/test/bdd/pkg/v1/oidc4vc/oidc4ci.go index 4cf3c3af5..2dddd61af 100644 --- a/test/bdd/pkg/v1/oidc4vc/oidc4ci.go +++ b/test/bdd/pkg/v1/oidc4vc/oidc4ci.go @@ -548,14 +548,14 @@ func (s *Steps) checkVC(vc *verifiable.Credential) error { } func (s *Steps) checkJWT(vc *verifiable.Credential) error { - if vc.JWT == "" { + if !vc.IsJWT() { return errors.New("JWT is empty") } - if (vc.SDJWTHashAlg == "") == s.issuerProfile.VCConfig.SDJWT.Enable { + if (vc.Contents().SDJWTHashAlg == nil) == s.issuerProfile.VCConfig.SDJWT.Enable { return errors.New("vc.SDJWTHashAlg is empty") } - if (len(vc.SDJWTDisclosures) == 0) == s.issuerProfile.VCConfig.SDJWT.Enable { + if (len(vc.SDJWTDisclosures()) == 0) == s.issuerProfile.VCConfig.SDJWT.Enable { return errors.New("vc.SDJWTDisclosures is empty") } @@ -563,18 +563,18 @@ func (s *Steps) checkJWT(vc *verifiable.Credential) error { } func (s *Steps) checkSignatureHolder(vc *verifiable.Credential) error { - if len(vc.Proofs) < 1 { + if len(vc.Proofs()) < 1 { return errors.New("unexpected proofs amount") } switch s.issuerProfile.VCConfig.SignatureRepresentation { case verifiable.SignatureJWS: - _, found := vc.Proofs[0]["jws"] + _, found := vc.Proofs()[0]["jws"] if !found { return fmt.Errorf("unable to find jws in proof") } case verifiable.SignatureProofValue: - _, found := vc.Proofs[0]["proofValue"] + _, found := vc.Proofs()[0]["proofValue"] if !found { return fmt.Errorf("unable to find proofValue in proof") } @@ -596,16 +596,16 @@ func (s *Steps) initiateCredentialIssuanceWithError(errorContains string) error } func checkCredentialStatusType(vc *verifiable.Credential, expected string) error { - if vc.Status.Type != expected { - return bddutil.ExpectedStringError(expected, vc.Status.Type) + if vc.Contents().Status.Type != expected { + return bddutil.ExpectedStringError(expected, vc.Contents().Status.Type) } return nil } func checkIssuer(vc *verifiable.Credential, expected string) error { - if vc.Issuer.CustomFields["name"] != expected { - return bddutil.ExpectedStringError(expected, vc.Issuer.CustomFields["name"].(string)) + if vc.Contents().Issuer.CustomFields["name"] != expected { + return bddutil.ExpectedStringError(expected, vc.Contents().Issuer.CustomFields["name"].(string)) } return nil diff --git a/test/bdd/pkg/v1/oidc4vc/oidc4vp.go b/test/bdd/pkg/v1/oidc4vc/oidc4vp.go index 9bd751eca..babd6b4bc 100644 --- a/test/bdd/pkg/v1/oidc4vc/oidc4vp.go +++ b/test/bdd/pkg/v1/oidc4vc/oidc4vp.go @@ -195,7 +195,7 @@ func (s *Steps) validateRetrievedInteractionsClaim(claimsBytes []byte) error { return fmt.Errorf("parse credential from wallet: %w", err) } - issuedVCID[vcParsed.ID] = struct{}{} + issuedVCID[vcParsed.Contents().ID] = struct{}{} } for retrievedVCID := range claims { diff --git a/test/bdd/pkg/v1/oidc4vp/oidc4vp.go b/test/bdd/pkg/v1/oidc4vp/oidc4vp.go index b81e71bf1..66f2f9d0e 100644 --- a/test/bdd/pkg/v1/oidc4vp/oidc4vp.go +++ b/test/bdd/pkg/v1/oidc4vp/oidc4vp.go @@ -157,7 +157,7 @@ func (e *Steps) validateRetrievedInteractionsClaim(claimsBytes []byte) error { return err } - issuedVCID[issuedVC.ID] = struct{}{} + issuedVCID[issuedVC.Contents().ID] = struct{}{} } for retrievedVCID := range claims { diff --git a/test/bdd/pkg/v1/vc/credential.go b/test/bdd/pkg/v1/vc/credential.go index b8ad07fd6..af049027c 100644 --- a/test/bdd/pkg/v1/vc/credential.go +++ b/test/bdd/pkg/v1/vc/credential.go @@ -17,6 +17,7 @@ import ( "github.com/google/uuid" "github.com/trustbloc/vc-go/verifiable" + "github.com/trustbloc/vcs/component/wallet-cli/pkg/walletrunner/vcprovider" vcsverifiable "github.com/trustbloc/vcs/pkg/doc/verifiable" "github.com/trustbloc/vcs/test/bdd/pkg/bddutil" @@ -52,9 +53,7 @@ func (e *Steps) issueVC(credential, profileVersionedID string) error { return err } - cred.JWT = "" - - credBytes, err = cred.MarshalJSON() + credBytes, err = cred.MarshalAsJSONLD() if err != nil { return fmt.Errorf("cred marshal error: %w", err) } @@ -90,23 +89,20 @@ func (e *Steps) createCredential( return "", err } - cred.ID = uuid.New().URN() - - subjs, ok := cred.Subject.([]verifiable.Subject) - if !ok { - return cred.ID, fmt.Errorf("cred subject has wrong type, not verifiable.Subject") - } + subjs := cred.Contents().Subject if len(e.bddContext.CredentialSubject) > didIndex && e.bddContext.CredentialSubject[didIndex] != "" { subjs[0].ID = e.bddContext.CredentialSubject[didIndex] } + cred = cred.WithModifiedID(uuid.New().URN()).WithModifiedSubject(subjs) + issuerVCFormat := e.bddContext.IssuerProfiles[fmt.Sprintf("%s/%s", profileID, profileVersion)].VCConfig.Format oidcVCFormat := vcsFormatToOIDC4CI[issuerVCFormat] reqData, err := vcprovider.GetIssueCredentialRequestData(cred, oidcVCFormat) if err != nil { - return cred.ID, fmt.Errorf("unable to get issue credential request data: %w", err) + return cred.Contents().ID, fmt.Errorf("unable to get issue credential request data: %w", err) } req := &model.IssueCredentialData{ @@ -115,7 +111,7 @@ func (e *Steps) createCredential( requestBytes, err := json.Marshal(req) if err != nil { - return cred.ID, err + return cred.Contents().ID, err } endpointURL := fmt.Sprintf(issueCredentialURLFormat, issueCredentialURL, profileID, profileVersion) @@ -123,25 +119,25 @@ func (e *Steps) createCredential( resp, err := bddutil.HTTPSDo(http.MethodPost, endpointURL, "application/json", token, //nolint: bodyclose bytes.NewBuffer(requestBytes), e.tlsConfig) if err != nil { - return cred.ID, err + return cred.Contents().ID, err } defer bddutil.CloseResponseBody(resp.Body) respBytes, err := io.ReadAll(resp.Body) if err != nil { - return cred.ID, err + return cred.Contents().ID, err } if resp.StatusCode != http.StatusOK { - return cred.ID, bddutil.ExpectedStatusCodeError(http.StatusOK, resp.StatusCode, respBytes) + return cred.Contents().ID, bddutil.ExpectedStatusCodeError(http.StatusOK, resp.StatusCode, respBytes) } e.Lock() e.bddContext.CreatedCredential = respBytes e.Unlock() - return cred.ID, nil + return cred.Contents().ID, nil } func (e *Steps) verifyVC(profileVersionedID string) error { @@ -231,7 +227,7 @@ func (e *Steps) revokeVC(profileVersionedID string) error { req := &model.UpdateCredentialStatusRequest{ ProfileID: profileID, ProfileVersion: profileVersion, - CredentialID: cred.ID, + CredentialID: cred.Contents().ID, CredentialStatus: model.CredentialStatus{ Status: "true", Type: string(e.bddContext.IssuerProfiles[profileVersionedID].VCConfig.Status.Type), diff --git a/test/bdd/testdata/crude_product.json b/test/bdd/testdata/crude_product.json index aea0fd8cd..5858fbfb1 100644 --- a/test/bdd/testdata/crude_product.json +++ b/test/bdd/testdata/crude_product.json @@ -13,6 +13,7 @@ "issuer": "did:key:z6MkiTsvjrrPNDZ1rrg9QDEYCFWCmEswT6U2cEkScb7edQ9b", "issuanceDate": "2020-05-01T00:45:04.789Z", "credentialSubject": { + "id": "did:example:b34ca6cd37bbf23", "producer": "did:v1:test:nym:z6MkfG5HTrBXzsAP8AbayNpG3ZaoyM4PCqNPrdWQRSpHDV6J", "category": "Western Canadian Select", "hsCode": "270900", diff --git a/test/stress/go.mod b/test/stress/go.mod index a03ed756d..311a9250c 100644 --- a/test/stress/go.mod +++ b/test/stress/go.mod @@ -15,7 +15,7 @@ require ( github.com/redis/go-redis/v9 v9.0.3 github.com/samber/lo v1.38.1 github.com/trustbloc/logutil-go v1.0.0-rc1 - github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 + github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 github.com/trustbloc/vcs/component/wallet-cli v0.0.0-20230710195911-02aad4f0fcec github.com/trustbloc/vcs/test/bdd v0.0.0-20230314165048-d06b1132a27b golang.org/x/oauth2 v0.7.0 @@ -50,7 +50,6 @@ require ( github.com/consensys/gnark-crypto v0.9.1 // indirect github.com/creasty/defaults v1.7.0 // indirect github.com/dave/jennifer v1.6.1 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/deepmap/oapi-codegen v1.11.0 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect @@ -81,7 +80,6 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/henvic/httpretty v0.1.0 // indirect github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 // indirect - github.com/hyperledger/ursa-wrapper-go v0.3.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kawamuray/jsonpath v0.0.0-20201211160320-7483bafabd7e // indirect @@ -115,7 +113,6 @@ require ( github.com/pelletier/go-toml/v2 v2.0.9 // indirect github.com/piprate/json-gold v0.5.1-0.20230111113000-6ddbe6e6f19f // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pquerna/cachecontrol v0.1.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-19 v0.3.2 // indirect @@ -130,7 +127,6 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.16.0 // indirect github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693 // indirect - github.com/stretchr/testify v1.8.4 // indirect github.com/subosito/gotenv v1.4.2 // indirect github.com/syndtr/goleveldb v1.0.0 // indirect github.com/teserakt-io/golang-ed25519 v0.0.0-20210104091850-3888c087a4c8 // indirect @@ -138,8 +134,9 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect - github.com/trustbloc/did-go v1.0.0 // indirect - github.com/trustbloc/kms-go v1.0.0 // indirect + github.com/trustbloc/bbs-signature-go v1.0.0 // indirect + github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 // indirect + github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 // indirect github.com/trustbloc/sidetree-core-go v1.0.0 // indirect github.com/trustbloc/vcs v0.1.9-0.20230210204445-f2870a36f0ea // indirect github.com/trustbloc/vcs/component/oidc/fosite v0.0.0-20230724110323-79c5330617d6 // indirect diff --git a/test/stress/go.sum b/test/stress/go.sum index 6476bec66..c4312ce64 100644 --- a/test/stress/go.sum +++ b/test/stress/go.sum @@ -335,8 +335,6 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 h1:B1Nt8hKb//KvgGRprk0h1t4lCnwhE9/ryb1WqfZbV+M= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2/go.mod h1:X+DIyUsaTmalOpmpQfIvFZjKHQedrURQ5t4YqquX7lE= -github.com/hyperledger/ursa-wrapper-go v0.3.1 h1:Do+QrVNniY77YK2jTIcyWqj9rm/Yb5SScN0bqCjiibA= -github.com/hyperledger/ursa-wrapper-go v0.3.1/go.mod h1:nPSAuMasIzSVciQo22PedBk4Opph6bJ6ia3ms7BH/mk= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= @@ -561,16 +559,18 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/trustbloc/did-go v1.0.0 h1:emrE2iG7/sQ2ZIPg60FnNIfe1dTAVG3A/Ls0i8jHO10= -github.com/trustbloc/did-go v1.0.0/go.mod h1:+A6OLKYBSh5cGjc6qk3KZ1DXOAlfIjdUwqz+tzcjOKM= -github.com/trustbloc/kms-go v1.0.0 h1:uV4J95DXKgpcxEQtRLJ6Aa9nk1CY8cLSUHgSwwzqJIQ= -github.com/trustbloc/kms-go v1.0.0/go.mod h1:1rvrHRuIRT7qLapB0lSpFgy1CjFunx85EyEzcZpIxG8= +github.com/trustbloc/bbs-signature-go v1.0.0 h1:JOKmPRTpjbbGODt71i3wJyiEBcu5XEoeSMQaM0WHR7Q= +github.com/trustbloc/bbs-signature-go v1.0.0/go.mod h1:8xptu/lbVUDACQW10yiHtqATzC2kpTKQk5mKsKTD85Y= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9 h1:UA6QlD58VZnSd2EpFJCi9XctBY3naKouBOtjMss4ewc= +github.com/trustbloc/did-go v1.0.2-0.20230922190208-b53738d979e9/go.mod h1:qqTm9zd5rGhHSOtC8jjadqM01Od9zcDbUiUYLv+M6ls= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30 h1:nNmYk/CX3UrLe4a7qCaMjsc+IWcQdZlJGvY5D2gsewE= +github.com/trustbloc/kms-go v1.0.1-0.20230922134356-24e819a06a30/go.mod h1:7arOSG9GewtV1WiqYZ23dSZ6haamosSABwyG//cRaXQ= github.com/trustbloc/logutil-go v1.0.0-rc1 h1:rRJbvgQfrlUfyej+mY0nuQJymGqjRW4oZEwKi544F4c= github.com/trustbloc/logutil-go v1.0.0-rc1/go.mod h1:JlxT0oZfNKgIlSNtgc001WEeDMxlnAvOM43gNm8DQVc= github.com/trustbloc/sidetree-core-go v1.0.0 h1:kzfKZOJ0sgDy9D1AYNcoR3JHutqtMtKvF2P9UwUcDjU= github.com/trustbloc/sidetree-core-go v1.0.0/go.mod h1:jdxAFuorlIwFOGVW6O455/lZqxg2mZkRHNTEolcZdDI= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269 h1:FG8enh3pfxjxedtKdI7gOMrUQeKMhUlpuXR3O8kGwvg= -github.com/trustbloc/vc-go v1.0.1-0.20230914202013-c170833f0269/go.mod h1:047WbpZu3QQ/mRqMO4JBDMUtY9M/LaEHwBJNo7XxdTY= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468 h1:GizDlcTPMuOh8HHifl8qp+ohaGMhiIT7k4+NcI/CA/I= +github.com/trustbloc/vc-go v1.0.3-0.20230927100750-6e0ff8399468/go.mod h1:6I4D1Hlf5CpSXBbfOIf58ZPtheyT8ZdsorN2kef2ZxU= github.com/trustbloc/vcs/component/oidc/fosite v0.0.0-20230724110323-79c5330617d6 h1:iqqHGeoI6fXZbjtjvV9OCql7XQtr8P4LQBE9d2j9Ll8= github.com/trustbloc/vcs/component/oidc/fosite v0.0.0-20230724110323-79c5330617d6/go.mod h1:D/dD0ld+XRAt/MjhKnrpaVbaKTe5Zq9uAXONf5c4OxU= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= diff --git a/test/stress/pkg/stress/stress_test_case.go b/test/stress/pkg/stress/stress_test_case.go index d28171465..47b19dea2 100644 --- a/test/stress/pkg/stress/stress_test_case.go +++ b/test/stress/pkg/stress/stress_test_case.go @@ -219,7 +219,7 @@ func (c *TestCase) Invoke() (string, interface{}, error) { credID := "" if credentials != nil { - credID = credentials.ID + credID = credentials.Contents().ID } if err != nil { return credID, nil, fmt.Errorf("CredId [%v]. run pre-auth issuance: %w", credID, err) @@ -255,7 +255,7 @@ func (c *TestCase) Invoke() (string, interface{}, error) { return credID, nil, fmt.Errorf("unmarshal perf info into stressTestPerfInfo: %w", err) } - if !c.disableRevokeTestCase && credentials.Status != nil && credentials.Status.Type != "" { + if !c.disableRevokeTestCase && credentials.Contents().Status != nil && credentials.Contents().Status.Type != "" { st := time.Now() if err = c.revokeVC(credentials); err != nil { return credID, nil, fmt.Errorf("CredId [%v]. can not revokeVc; %w", credID, err) @@ -269,10 +269,10 @@ func (c *TestCase) Invoke() (string, interface{}, error) { func (c *TestCase) revokeVC(cred *verifiable.Credential) error { req := &model.UpdateCredentialStatusRequest{ - CredentialID: cred.ID, + CredentialID: cred.Contents().ID, CredentialStatus: model.CredentialStatus{ Status: "true", - Type: cred.Status.Type, + Type: cred.Contents().Status.Type, }, }