Skip to content

Commit

Permalink
Update to go-did v0.11 (#2634)
Browse files Browse the repository at this point in the history
* Update to go-did v0.10.0

* copyright

* add ValidFrom to defaultCredentialValidator

* fix e2e test

* PR feedback

* fix build

* revert

* f

* Revert array compaction

* gomodtidy

* move validateAtTime to ProofOptions.ValidAt

* move validateAtTime to ProofOptions.ValidAt

---------

Co-authored-by: Gerard Snaauw <[email protected]>
  • Loading branch information
reinkrul and gerardsn authored Dec 5, 2023
1 parent c7e85d1 commit 30d3f21
Show file tree
Hide file tree
Showing 27 changed files with 148 additions and 106 deletions.
3 changes: 2 additions & 1 deletion api/ssi_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,15 @@ func Test_DIDDocumentMetadata(t *testing.T) {
}

func createVerifiableCredential() vcr.VerifiableCredential {
issuanceDate := time.Now()
return vcr.VerifiableCredential{
Context: []ssi.URI{ssi.MustParseURI("https://www.w3.org/2018/credentials/v1")},
Type: []ssi.URI{
ssi.MustParseURI("NutsOrganizationCredential"),
ssi.MustParseURI("VerifiableCredential"),
},
Issuer: ssi.MustParseURI("did:nuts:CuE3qeFGGLhEAS3gKzhMCeqd1dGa9at5JCbmCfyMU2Ey"),
IssuanceDate: time.Now(),
IssuanceDate: &issuanceDate,
CredentialSubject: []interface{}{"subject"},
Proof: []interface{}{"because"},
}
Expand Down
3 changes: 2 additions & 1 deletion auth/api/auth/v1/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -489,13 +489,14 @@ func TestWrapper_RequestAccessToken(t *testing.T) {
t.Run("happy_path", func(t *testing.T) {
ctx := createContext(t)

issuanceDate := time.Now()
credentials := []vc.VerifiableCredential{
{
Context: []ssi.URI{vc.VCContextV1URI(), credential.NutsV1ContextURI},
ID: &ssi.URI{},
Type: []ssi.URI{*credential.NutsAuthorizationCredentialTypeURI, vc.VerifiableCredentialTypeV1URI()},
Issuer: vdr.TestDIDA.URI(),
IssuanceDate: time.Now(),
IssuanceDate: &issuanceDate,
CredentialSubject: []interface{}{credential.NutsAuthorizationCredentialSubject{
ID: vdr.TestDIDB.String(),
PurposeOfUse: "eTransfer",
Expand Down
2 changes: 1 addition & 1 deletion auth/api/iam/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func TestWrapper_GetWebDID(t *testing.T) {
ID: webDID,
}
// remarshal expectedWebDIDDoc to make sure in-memory format is the same as the one returned by the API
data, _ := expectedWebDIDDoc.MarshalJSON()
data, _ := json.Marshal(expectedWebDIDDoc)
_ = expectedWebDIDDoc.UnmarshalJSON(data)

t.Run("ok", func(t *testing.T) {
Expand Down
5 changes: 3 additions & 2 deletions auth/services/oauth/relying_party_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func TestRelyingParty_RequestRFC021AccessToken(t *testing.T) {
})
t.Run("error - no matching credentials", func(t *testing.T) {
ctx := createOAuthRPContext(t)
ctx.wallet.EXPECT().List(gomock.Any(), walletDID).Return([]vcr.VerifiableCredential{}, nil)
ctx.wallet.EXPECT().List(gomock.Any(), walletDID).Return([]vc.VerifiableCredential{}, nil)

_, err := ctx.relyingParty.RequestRFC021AccessToken(context.Background(), walletDID, ctx.verifierDID, scopes)

Expand Down Expand Up @@ -257,12 +257,13 @@ func TestService_CreateJwtBearerToken(t *testing.T) {

id := vdr.TestDIDA.URI()
id.Fragment = "1"
issuanceDate := time.Now()
validCredential := vc.VerifiableCredential{
Context: []ssi.URI{vc.VCContextV1URI(), credential.NutsV1ContextURI},
ID: &id,
Type: []ssi.URI{*credential.NutsAuthorizationCredentialTypeURI, vc.VerifiableCredentialTypeV1URI()},
Issuer: vdr.TestDIDA.URI(),
IssuanceDate: time.Now(),
IssuanceDate: &issuanceDate,
CredentialSubject: []interface{}{credential.NutsAuthorizationCredentialSubject{
ID: vdr.TestDIDB.String(),
PurposeOfUse: "eTransfer",
Expand Down
2 changes: 1 addition & 1 deletion auth/services/selfsigned/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func (v *signer) createVP(ctx context.Context, s types.Session, issuanceDate tim
Context: []ssi.URI{credential.NutsV1ContextURI},
Type: []ssi.URI{ssi.MustParseURI(credentialType)},
Issuer: issuerID.URI(),
IssuanceDate: issuanceDate,
IssuanceDate: &issuanceDate,
ExpirationDate: &expirationData,
CredentialSubject: s.CredentialSubject(),
}
Expand Down
5 changes: 5 additions & 0 deletions didman/didman.go
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,11 @@ func (d *didman) updateService(ctx context.Context, id did.DID, serviceType stri

func generateIDForService(id did.DID, service did.Service) ssi.URI {
bytes, _ := json.Marshal(service)
// go-did earlier unmarshaled/marshaled the service endpoint to a map[string]interface{} ("NormalizeDocument()"), which changes the order of the keys.
// To retain the same hash given as before go-did v0.10.0, we need to mimic this behavior.
var raw map[string]interface{}
_ = json.Unmarshal(bytes, &raw)
bytes, _ = json.Marshal(raw)
shaBytes := sha256.Sum256(bytes)
d := id.URI()
d.Fragment = base58.EncodeAlphabet(shaBytes[:], base58.BTCAlphabet)
Expand Down
5 changes: 3 additions & 2 deletions discovery/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ func createCredential(issuerDID did.DID, subjectDID did.DID, credentialSubject m
vcID := did.DIDURL{DID: issuerDID}
vcID.Fragment = uuid.NewString()
vcIDURI := vcID.URI()
expirationDate := time.Now().Add(time.Hour * 24)
issuanceDate := time.Now()
expirationDate := issuanceDate.Add(time.Hour * 24)
if credentialSubject == nil {
credentialSubject = make(map[string]interface{})
}
Expand All @@ -138,7 +139,7 @@ func createCredential(issuerDID did.DID, subjectDID did.DID, credentialSubject m
ID: &vcIDURI,
Type: []ssi.URI{ssi.MustParseURI("VerifiableCredential"), ssi.MustParseURI("TestCredential")},
Issuer: issuerDID.URI(),
IssuanceDate: time.Now(),
IssuanceDate: &issuanceDate,
ExpirationDate: &expirationDate,
CredentialSubject: []interface{}{credentialSubject},
}, func(ctx context.Context, claims map[string]interface{}, headers map[string]interface{}) (string, error) {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ require (
github.com/nats-io/nats-server/v2 v2.10.6
github.com/nats-io/nats.go v1.31.0
github.com/nuts-foundation/crypto-ecies v0.0.0-20211207143025-5b84f9efce2b
github.com/nuts-foundation/go-did v0.9.0
github.com/nuts-foundation/go-did v0.11.0
github.com/nuts-foundation/go-leia/v4 v4.0.1
github.com/nuts-foundation/go-stoabs v1.9.0
// check the oapi-codegen tool version in the makefile when upgrading the runtime
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -448,8 +448,8 @@ github.com/nightlyone/lockfile v1.0.0/go.mod h1:rywoIealpdNse2r832aiD9jRk8ErCatR
github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk=
github.com/nuts-foundation/crypto-ecies v0.0.0-20211207143025-5b84f9efce2b h1:80icUxWHwE1MrIOOEK5rxrtyKOgZeq5Iu1IjAEkggTY=
github.com/nuts-foundation/crypto-ecies v0.0.0-20211207143025-5b84f9efce2b/go.mod h1:6YUioYirD6/8IahZkoS4Ypc8xbeJW76Xdk1QKcziNTM=
github.com/nuts-foundation/go-did v0.9.0 h1:JBz1cYaMxplKZ31QyWierrR3Yt2RIpaxZTt8KFm4Ph4=
github.com/nuts-foundation/go-did v0.9.0/go.mod h1:L39mh6SBsuenqeZw2JxARx4a/bwdARwchG2x3zPMTjc=
github.com/nuts-foundation/go-did v0.11.0 h1:RTem1MlVoOOoLa/Y2miYRy70Jex0/kJBTCPH5RtUmrY=
github.com/nuts-foundation/go-did v0.11.0/go.mod h1:2e2H2Hqk0SWrrGZEg97dbK/ZFIkkFB65hNWdOSbylrg=
github.com/nuts-foundation/go-leia/v4 v4.0.1 h1:+Sbk3Bew1QnRUqRXSOwomMw3nIZgncmTX425J7U5Q34=
github.com/nuts-foundation/go-leia/v4 v4.0.1/go.mod h1:eaZuWIolpU61TMvTMcen85+SOEOnHiALdg5SxqLXzz8=
github.com/nuts-foundation/go-stoabs v1.9.0 h1:zK+ugfolaJYyBvGwsRuavLVdycXk4Yw/1gI+tz17lWQ=
Expand Down
7 changes: 4 additions & 3 deletions vcr/api/vcr/v2/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,14 @@ func Test_Marshalling(t *testing.T) {
assert.IsType(t, make(map[string]interface{}, 0), result["credentialSubject"]) // single entry should not end up as slice
})
t.Run("CreateVP200JSONResponse", func(t *testing.T) {
r := CreateVP200JSONResponse{
issuanceDate := time.Now()
r := CreateVP200JSONResponse(VerifiablePresentation{
VerifiableCredential: []VerifiableCredential{
{
IssuanceDate: time.Now(),
IssuanceDate: &issuanceDate,
},
},
}
})
data, _ := json.Marshal(r)
result := make(map[string]interface{}, 0)
err := json.Unmarshal(data, &result)
Expand Down
3 changes: 2 additions & 1 deletion vcr/credential/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@ import (

func ValidNutsAuthorizationCredential() *vc.VerifiableCredential {
id := stringToURI(vdr.TestDIDA.String() + "#38E90E8C-F7E5-4333-B63A-F9DD155A0272")
issuanceDate := time.Now()
return &vc.VerifiableCredential{
Context: []ssi.URI{vc.VCContextV1URI(), NutsV1ContextURI},
ID: &id,
Type: []ssi.URI{*NutsAuthorizationCredentialTypeURI, vc.VerifiableCredentialTypeV1URI()},
Issuer: stringToURI(vdr.TestDIDA.String()),
IssuanceDate: time.Now(),
IssuanceDate: &issuanceDate,
CredentialSubject: []interface{}{
NutsAuthorizationCredentialSubject{
ID: vdr.TestDIDB.String(),
Expand Down
3 changes: 2 additions & 1 deletion vcr/credential/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ func (d defaultCredentialValidator) Validate(credential vc.VerifiableCredential)
return failure("'ID' is required")
}

if credential.IssuanceDate.IsZero() {
if (credential.IssuanceDate == nil || credential.IssuanceDate.IsZero()) &&
(credential.ValidFrom == nil || credential.ValidFrom.IsZero()) {
return failure("'issuanceDate' is required")
}

Expand Down
30 changes: 30 additions & 0 deletions vcr/credential/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"testing"
"time"
)

func init() {
Expand Down Expand Up @@ -419,6 +420,17 @@ func TestDefaultCredentialValidator(t *testing.T) {
assert.NoError(t, err)
})

t.Run("ok - ValidFrom instead of IssuanceDate", func(t *testing.T) {
v := ValidNutsOrganizationCredential(t)
v.IssuanceDate, v.ValidFrom = v.ValidFrom, v.IssuanceDate

err := validator.Validate(v)

assert.Nil(t, v.IssuanceDate)
assert.NotEmpty(t, v.ValidFrom)
assert.NoError(t, err)
})

t.Run("failed - missing ID", func(t *testing.T) {
v := ValidNutsOrganizationCredential(t)
v.ID = nil
Expand Down Expand Up @@ -454,4 +466,22 @@ func TestDefaultCredentialValidator(t *testing.T) {

assert.EqualError(t, err, "validation failed: type 'VerifiableCredential' is required")
})

t.Run("failed - issuanceDate and validFrom both missing", func(t *testing.T) {
v := ValidNutsOrganizationCredential(t)
v.IssuanceDate = nil

err := validator.Validate(v)

assert.EqualError(t, err, "validation failed: 'issuanceDate' is required")
})

t.Run("failed - issuanceDate is zero", func(t *testing.T) {
v := ValidNutsOrganizationCredential(t)
v.IssuanceDate = new(time.Time)

err := validator.Validate(v)

assert.EqualError(t, err, "validation failed: 'issuanceDate' is required")
})
}
7 changes: 4 additions & 3 deletions vcr/issuer/issuer.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,9 @@ func (i issuer) buildVC(ctx context.Context, template vc.VerifiableCredential, o
ExpirationDate: template.ExpirationDate,
IssuanceDate: template.IssuanceDate,
}
if unsignedCredential.IssuanceDate.IsZero() {
unsignedCredential.IssuanceDate = TimeFunc()
if unsignedCredential.IssuanceDate == nil {
issuanceDate := TimeFunc()
unsignedCredential.IssuanceDate = &issuanceDate
}
if !unsignedCredential.ContainsContext(vc.VCContextV1URI()) {
unsignedCredential.Context = append(unsignedCredential.Context, vc.VCContextV1URI())
Expand Down Expand Up @@ -246,7 +247,7 @@ func (i issuer) buildJSONLDCredential(ctx context.Context, unsignedCredential vc
b, _ := json.Marshal(unsignedCredential)
_ = json.Unmarshal(b, &credentialAsMap)

proofOptions := proof.ProofOptions{Created: unsignedCredential.IssuanceDate}
proofOptions := proof.ProofOptions{Created: *unsignedCredential.IssuanceDate}

webSig := signature.JSONWebSignature2020{ContextLoader: i.jsonldManager.DocumentLoader(), Signer: i.keyStore}
signingResult, err := proof.NewLDProof(proofOptions).Sign(ctx, credentialAsMap, webSig, key)
Expand Down
7 changes: 4 additions & 3 deletions vcr/issuer/issuer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func Test_issuer_buildVC(t *testing.T) {
Context: []ssi.URI{schemaOrgContext},
Type: []ssi.URI{credentialType},
Issuer: issuerID,
IssuanceDate: issuance,
IssuanceDate: &issuance,
ExpirationDate: &expirationDate,
CredentialSubject: []interface{}{map[string]interface{}{
"id": subjectDID,
Expand Down Expand Up @@ -137,7 +137,7 @@ func Test_issuer_buildVC(t *testing.T) {
// Assert JWT
require.NotNil(t, result.JWT())
assert.Equal(t, subjectDID, result.JWT().Subject())
assert.Equal(t, result.IssuanceDate, result.JWT().NotBefore())
assert.Equal(t, *result.IssuanceDate, result.JWT().NotBefore())
assert.Equal(t, *result.ExpirationDate, result.JWT().Expiration())
assert.Equal(t, result.ID.String(), result.JWT().JwtID())
})
Expand All @@ -151,11 +151,12 @@ func Test_issuer_buildVC(t *testing.T) {
jsonldManager := jsonld.NewTestJSONLDManager(t)
sut := issuer{keyResolver: keyResolverMock, jsonldManager: jsonldManager, keyStore: keyStore}

issuanceDate := time.Now()
template := vc.VerifiableCredential{
Context: []ssi.URI{vc.VCContextV1URI()},
Type: []ssi.URI{credentialType},
Issuer: issuerID,
IssuanceDate: time.Now(),
IssuanceDate: &issuanceDate,
}

result, err := sut.buildVC(ctx, template, CredentialOptions{})
Expand Down
2 changes: 1 addition & 1 deletion vcr/issuer/network_publisher.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (p networkPublisher) PublishCredential(ctx context.Context, verifiableCrede

payload, _ := json.Marshal(verifiableCredential)
tx := network.TransactionTemplate(types.VcDocumentType, payload, key).
WithTimestamp(verifiableCredential.IssuanceDate).
WithTimestamp(*verifiableCredential.IssuanceDate).
WithAdditionalPrevs(meta.SourceTransactions).
WithPrivate(participants)

Expand Down
12 changes: 9 additions & 3 deletions vcr/issuer/network_publisher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,10 @@ func Test_networkPublisher_PublishCredential(t *testing.T) {

sut := networkPublisher{keyResolver: mockKeyResolver, didResolver: mockDidResolver, networkTx: mockNetwork}

issuanceDate := time.Now()
credentialToPublish := vc.VerifiableCredential{
Issuer: issuerID,
IssuanceDate: &issuanceDate,
CredentialSubject: []interface{}{credential.BaseCredentialSubject{ID: subjectID.String()}},
}
payload, _ := json.Marshal(credentialToPublish)
Expand All @@ -120,7 +122,7 @@ func Test_networkPublisher_PublishCredential(t *testing.T) {
Payload: payload,
Type: types.VcDocumentType,
AttachKey: false,
Timestamp: time.Time{},
Timestamp: issuanceDate,
AdditionalPrevs: nil,
Participants: []did.DID{},
}
Expand All @@ -145,8 +147,10 @@ func Test_networkPublisher_PublishCredential(t *testing.T) {
serviceResolver: mockServiceResolver,
}

issuanceDate := time.Now()
credentialToPublish := vc.VerifiableCredential{
Issuer: issuerID,
IssuanceDate: &issuanceDate,
CredentialSubject: []interface{}{credential.BaseCredentialSubject{ID: subjectID.String()}},
}
payload, _ := json.Marshal(credentialToPublish)
Expand All @@ -165,7 +169,7 @@ func Test_networkPublisher_PublishCredential(t *testing.T) {
Payload: payload,
Type: types.VcDocumentType,
AttachKey: false,
Timestamp: time.Time{},
Timestamp: issuanceDate,
AdditionalPrevs: nil,
Participants: []did.DID{*issuerDID, *subjectDID},
}
Expand Down Expand Up @@ -258,8 +262,10 @@ func Test_networkPublisher_PublishCredential(t *testing.T) {

sut := networkPublisher{keyResolver: mockKeyResolver, didResolver: mockDidResolver, networkTx: mockNetwork}

issuanceDate := time.Now()
credentialToPublish := vc.VerifiableCredential{
Issuer: issuerID,
IssuanceDate: &issuanceDate,
CredentialSubject: []interface{}{credential.BaseCredentialSubject{ID: subjectID.String()}},
}
payload, _ := json.Marshal(credentialToPublish)
Expand All @@ -273,7 +279,7 @@ func Test_networkPublisher_PublishCredential(t *testing.T) {
Payload: payload,
Type: types.VcDocumentType,
AttachKey: false,
Timestamp: time.Time{},
Timestamp: issuanceDate,
AdditionalPrevs: nil,
Participants: make([]did.DID, 0),
}
Expand Down
14 changes: 14 additions & 0 deletions vcr/signature/proof/jsonld.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ type ProofOptions struct {
ProofPurpose string `json:"proofPurpose"`
}

// ValidAt checks if the proof is valid at a certain given time.
func (o ProofOptions) ValidAt(at time.Time, maxSkew time.Duration) bool {
// check if issuanceDate is before validAt
if o.Created.After(at.Add(maxSkew)) {
return false
}

// check if expirationDate is after validAt
if o.Expires != nil && o.Expires.Add(maxSkew).Before(at) {
return false
}
return true
}

// LDProof contains the fields of the Proof data model: https://w3c-ccg.github.io/data-integrity-spec/#proofs
type LDProof struct {
ProofOptions
Expand Down
Loading

0 comments on commit 30d3f21

Please sign in to comment.