Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

Commit

Permalink
feat: wallet.Issue supports jwtvc, verifiable.Credential can hold a j…
Browse files Browse the repository at this point in the history
…wtvc

Signed-off-by: Filip Burlacu <filip.burlacu@securekey.com>
  • Loading branch information
Filip Burlacu committed Aug 23, 2022
1 parent aab94d2 commit dfc9d56
Show file tree
Hide file tree
Showing 10 changed files with 206 additions and 20 deletions.
41 changes: 31 additions & 10 deletions pkg/doc/verifiable/credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ type Credential struct {
Evidence Evidence
TermsOfUse []TypedID
RefreshService []TypedID
JWT string

CustomFields CustomFields
}
Expand All @@ -528,6 +529,7 @@ type rawCredential struct {
Evidence Evidence `json:"evidence,omitempty"`
TermsOfUse json.RawMessage `json:"termsOfUse,omitempty"`
RefreshService json.RawMessage `json:"refreshService,omitempty"`
JWT string `json:"jwt,omitempty"`

// All unmapped fields are put here.
CustomFields `json:"-"`
Expand Down Expand Up @@ -794,7 +796,7 @@ func ParseCredential(vcData []byte, opts ...CredentialOpt) (*Credential, error)
vcOpts := getCredentialOpts(opts)

// Decode credential (e.g. from JWT).
vcDataDecoded, err := decodeRaw(vcData, vcOpts)
vcDataDecoded, externalJWT, err := decodeRaw(vcData, vcOpts)
if err != nil {
return nil, fmt.Errorf("decode new credential: %w", err)
}
Expand All @@ -817,6 +819,8 @@ func ParseCredential(vcData []byte, opts ...CredentialOpt) (*Credential, error)
return nil, err
}

vc.JWT = externalJWT

return vc, nil
}

Expand Down Expand Up @@ -987,6 +991,7 @@ func newCredential(raw *rawCredential) (*Credential, error) {
Evidence: raw.Evidence,
TermsOfUse: termsOfUse,
RefreshService: refreshService,
JWT: raw.JWT,
CustomFields: raw.CustomFields,
}, nil
}
Expand All @@ -1013,33 +1018,48 @@ func parseTypedID(bytes json.RawMessage) ([]TypedID, error) {
return nil, err
}

func decodeRaw(vcData []byte, vcOpts *credentialOpts) ([]byte, error) {
type externalJWTVC struct {
JWT string `json:"jwt,omitempty"`
}

func decodeRaw(vcData []byte, vcOpts *credentialOpts) ([]byte, string, error) {
vcStr := string(vcData)
externalVCStr := vcStr

jwtHolder := &externalJWTVC{}
err := json.Unmarshal(vcData, jwtHolder)

hasJWT := err == nil && jwtHolder.JWT != ""
if hasJWT {
externalVCStr = jwtHolder.JWT
}

if jwt.IsJWS(vcStr) { // External proof, is checked by JWS.
if jwt.IsJWS(externalVCStr) { // External proof, is checked by JWS.
if vcOpts.publicKeyFetcher == nil && !vcOpts.disabledProofCheck {
return nil, errors.New("public key fetcher is not defined")
return nil, "", errors.New("public key fetcher is not defined")
}

vcDecodedBytes, err := decodeCredJWS(vcStr, !vcOpts.disabledProofCheck, vcOpts.publicKeyFetcher)
vcDecodedBytes, err := decodeCredJWS(externalVCStr, !vcOpts.disabledProofCheck, vcOpts.publicKeyFetcher)
if err != nil {
return nil, fmt.Errorf("JWS decoding: %w", err)
return nil, "", fmt.Errorf("JWS decoding: %w", err)
}

return vcDecodedBytes, nil
return vcDecodedBytes, externalVCStr, nil
}

if jwt.IsJWTUnsecured(vcStr) { // Embedded proof.
vcDecodedBytes, err := decodeCredJWTUnsecured(vcStr)
if err != nil {
return nil, fmt.Errorf("unsecured JWT decoding: %w", err)
return nil, "", fmt.Errorf("unsecured JWT decoding: %w", err)
}

return checkEmbeddedProof(vcDecodedBytes, getEmbeddedProofCheckOpts(vcOpts))
vc, err := checkEmbeddedProof(vcDecodedBytes, getEmbeddedProofCheckOpts(vcOpts))
return vc, "", err
}

// Embedded proof.
return checkEmbeddedProof(vcData, getEmbeddedProofCheckOpts(vcOpts))
vc, err := checkEmbeddedProof(vcData, getEmbeddedProofCheckOpts(vcOpts))
return vc, "", err
}

func getEmbeddedProofCheckOpts(vcOpts *credentialOpts) *embeddedProofCheckOpts {
Expand Down Expand Up @@ -1432,6 +1452,7 @@ func (vc *Credential) raw() (*rawCredential, error) {
TermsOfUse: rawTermsOfUse,
Issued: vc.Issued,
Expired: vc.Expired,
JWT: vc.JWT,
CustomFields: vc.CustomFields,
}

Expand Down
3 changes: 3 additions & 0 deletions pkg/doc/verifiable/credential_jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ func newJWTCredClaims(vc *Credential, minimizeVC bool) (*JWTCredClaims, error) {
return nil, err
}

// If a Credential was parsed from JWT, we don't want the original JWT included when marshaling back to JWT claims.
raw.JWT = ""

vcMap, err := jsonutil.MergeCustomFields(raw, raw.CustomFields)
if err != nil {
return nil, err
Expand Down
9 changes: 9 additions & 0 deletions pkg/doc/verifiable/credential_jwt_proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ func TestParseCredentialFromJWS(t *testing.T) {
vc, err := parseTestCredential(t, testCred)
require.NoError(t, err)

require.NotEqual(t, "", vcFromJWT.JWT)
vcFromJWT.JWT = ""

require.Equal(t, vc, vcFromJWT)
})

Expand All @@ -80,6 +83,9 @@ func TestParseCredentialFromJWS(t *testing.T) {
vc, err := parseTestCredential(t, testCred)
require.NoError(t, err)

require.NotEqual(t, "", vcFromJWT.JWT)
vcFromJWT.JWT = ""

require.Equal(t, vc, vcFromJWT)
})

Expand Down Expand Up @@ -140,6 +146,9 @@ func TestParseCredentialFromJWS_EdDSA(t *testing.T) {
WithPublicKeyFetcher(SingleKey(signer.PublicKeyBytes(), kms.ED25519)))
require.NoError(t, err)

require.NotEqual(t, "", vcFromJWS.JWT)
vcFromJWS.JWT = ""

// unmarshalled credential must be the same as original one
require.Equal(t, vc, vcFromJWS)
}
Expand Down
4 changes: 4 additions & 0 deletions pkg/doc/verifiable/credential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1871,6 +1871,10 @@ func TestParseUnverifiedCredential(t *testing.T) {
WithDisabledProofCheck())
require.NoError(t, err)
require.NotNil(t, vcUnverified)

require.Equal(t, jws, vcUnverified.JWT)
vcUnverified.JWT = ""

require.Equal(t, vc, vcUnverified)
})

Expand Down
2 changes: 2 additions & 0 deletions pkg/doc/verifiable/embedded_proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ func checkEmbeddedProof(docBytes []byte, opts *embeddedProofCheckOpts) ([]byte,
return nil, fmt.Errorf("embedded proof is not JSON: %w", err)
}

delete(jsonldDoc, "jwt")

proofElement, ok := jsonldDoc["proof"]
if !ok || proofElement == nil {
// do not make a check if there is no proof defined as proof presence is not mandatory
Expand Down
12 changes: 10 additions & 2 deletions pkg/doc/verifiable/example_credential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ func ExampleCredential_embedding() {
panic(fmt.Errorf("failed to encode VC from JWS: %w", err))
}

// When parsing a verifiable.Credential from JWS, Credential.JWT is set to the raw JWS value.
// This allows the user to save the Credential and verify it later.

vcBytesFromJWS, err := vcParsed.MarshalJSON()
if err != nil {
panic(fmt.Errorf("failed to marshal VC: %w", err))
Expand All @@ -147,7 +150,7 @@ func ExampleCredential_embedding() {
// Output:
// {"@context":["https://www.w3.org/2018/credentials/v1","https://www.w3.org/2018/credentials/examples/v1"],"credentialSubject":{"degree":{"type":"BachelorDegree","university":"MIT"},"id":"did:example:ebfeb1f712ebc6f1c276e12ec21","name":"Jayden Doe","spouse":"did:example:c276e12ec21ebfeb1f712ebc6f1"},"expirationDate":"2020-01-01T19:23:24Z","id":"http://example.edu/credentials/1872","issuanceDate":"2010-01-01T19:23:24Z","issuer":{"id":"did:example:76e12ec712ebc6f1c221ebfeb1f","name":"Example University"},"referenceNumber":83294847,"type":["VerifiableCredential","UniversityDegreeCredential"]}
// eyJhbGciOiJFZERTQSIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCYWNoZWxvckRlZ3JlZSIsInVuaXZlcnNpdHkiOiJNSVQifSwiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJuYW1lIjoiSmF5ZGVuIERvZSIsInNwb3VzZSI6ImRpZDpleGFtcGxlOmMyNzZlMTJlYzIxZWJmZWIxZjcxMmViYzZmMSJ9LCJpc3N1ZXIiOnsibmFtZSI6IkV4YW1wbGUgVW5pdmVyc2l0eSJ9LCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiVW5pdmVyc2l0eURlZ3JlZUNyZWRlbnRpYWwiXX19.7He-0-kAUCgjgMUSI-BmH-9MjI-ixuMV6NUnJCtfLpoOJIkdK0Tf1iU6SWGSURpv67Mi91H-pzQCmW6jzEUABQ
// {"@context":["https://www.w3.org/2018/credentials/v1","https://www.w3.org/2018/credentials/examples/v1"],"credentialSubject":{"degree":{"type":"BachelorDegree","university":"MIT"},"id":"did:example:ebfeb1f712ebc6f1c276e12ec21","name":"Jayden Doe","spouse":"did:example:c276e12ec21ebfeb1f712ebc6f1"},"expirationDate":"2020-01-01T19:23:24Z","id":"http://example.edu/credentials/1872","issuanceDate":"2010-01-01T19:23:24Z","issuer":{"id":"did:example:76e12ec712ebc6f1c221ebfeb1f","name":"Example University"},"type":["VerifiableCredential","UniversityDegreeCredential"]}
// {"@context":["https://www.w3.org/2018/credentials/v1","https://www.w3.org/2018/credentials/examples/v1"],"credentialSubject":{"degree":{"type":"BachelorDegree","university":"MIT"},"id":"did:example:ebfeb1f712ebc6f1c276e12ec21","name":"Jayden Doe","spouse":"did:example:c276e12ec21ebfeb1f712ebc6f1"},"expirationDate":"2020-01-01T19:23:24Z","id":"http://example.edu/credentials/1872","issuanceDate":"2010-01-01T19:23:24Z","issuer":{"id":"did:example:76e12ec712ebc6f1c221ebfeb1f","name":"Example University"},"jwt":"eyJhbGciOiJFZERTQSIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCYWNoZWxvckRlZ3JlZSIsInVuaXZlcnNpdHkiOiJNSVQifSwiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJuYW1lIjoiSmF5ZGVuIERvZSIsInNwb3VzZSI6ImRpZDpleGFtcGxlOmMyNzZlMTJlYzIxZWJmZWIxZjcxMmViYzZmMSJ9LCJpc3N1ZXIiOnsibmFtZSI6IkV4YW1wbGUgVW5pdmVyc2l0eSJ9LCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiVW5pdmVyc2l0eURlZ3JlZUNyZWRlbnRpYWwiXX19.7He-0-kAUCgjgMUSI-BmH-9MjI-ixuMV6NUnJCtfLpoOJIkdK0Tf1iU6SWGSURpv67Mi91H-pzQCmW6jzEUABQ","type":["VerifiableCredential","UniversityDegreeCredential"]}
}

func ExampleCredential_extraFields() {
Expand Down Expand Up @@ -214,6 +217,8 @@ func ExampleCredential_extraFields() {
panic(fmt.Errorf("failed to encode VC from JWS: %w", err))
}

vcParsed.JWT = ""

vcBytesFromJWS, err := vcParsed.MarshalJSON()
if err != nil {
panic(fmt.Errorf("failed to marshal VC: %w", err))
Expand Down Expand Up @@ -282,6 +287,9 @@ func ExampleParseCredential() {
panic(fmt.Errorf("failed to decode VC JWS: %w", err))
}

// When parsing a verifiable.Credential from JWS, Credential.JWT is set to the raw JWS value.
// This allows the user to save the Credential and verify it later.

vcDecodedBytes, err := vcParsed.MarshalJSON()
if err != nil {
panic(fmt.Errorf("failed to marshal VC: %w", err))
Expand All @@ -290,7 +298,7 @@ func ExampleParseCredential() {
// The Holder then e.g. can save the credential to her personal verifiable credential wallet.
fmt.Println(string(vcDecodedBytes))

// Output: {"@context":["https://www.w3.org/2018/credentials/v1","https://www.w3.org/2018/credentials/examples/v1"],"credentialSubject":{"degree":{"type":"BachelorDegree","university":"MIT"},"id":"did:example:ebfeb1f712ebc6f1c276e12ec21","name":"Jayden Doe","spouse":"did:example:c276e12ec21ebfeb1f712ebc6f1"},"expirationDate":"2020-01-01T19:23:24Z","id":"http://example.edu/credentials/1872","issuanceDate":"2010-01-01T19:23:24Z","issuer":{"id":"did:example:76e12ec712ebc6f1c221ebfeb1f","name":"Example University"},"referenceNumber":83294847,"type":["VerifiableCredential","UniversityDegreeCredential"]}
// Output: {"@context":["https://www.w3.org/2018/credentials/v1","https://www.w3.org/2018/credentials/examples/v1"],"credentialSubject":{"degree":{"type":"BachelorDegree","university":"MIT"},"id":"did:example:ebfeb1f712ebc6f1c276e12ec21","name":"Jayden Doe","spouse":"did:example:c276e12ec21ebfeb1f712ebc6f1"},"expirationDate":"2020-01-01T19:23:24Z","id":"http://example.edu/credentials/1872","issuanceDate":"2010-01-01T19:23:24Z","issuer":{"id":"did:example:76e12ec712ebc6f1c221ebfeb1f","name":"Example University"},"jwt":"eyJhbGciOiJFZERTQSIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Nzc5MDY2MDQsImlhdCI6MTI2MjM3MzgwNCwiaXNzIjoiZGlkOmV4YW1wbGU6NzZlMTJlYzcxMmViYzZmMWMyMjFlYmZlYjFmIiwianRpIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzE4NzIiLCJuYmYiOjEyNjIzNzM4MDQsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvZXhhbXBsZXMvdjEiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGVncmVlIjp7InR5cGUiOiJCYWNoZWxvckRlZ3JlZSIsInVuaXZlcnNpdHkiOiJNSVQifSwiaWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEiLCJuYW1lIjoiSmF5ZGVuIERvZSIsInNwb3VzZSI6ImRpZDpleGFtcGxlOmMyNzZlMTJlYzIxZWJmZWIxZjcxMmViYzZmMSJ9LCJpc3N1ZXIiOnsibmFtZSI6IkV4YW1wbGUgVW5pdmVyc2l0eSJ9LCJyZWZlcmVuY2VOdW1iZXIiOjguMzI5NDg0N2UrMDcsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJVbml2ZXJzaXR5RGVncmVlQ3JlZGVudGlhbCJdfX0.a5yKMPmDnEXvM-fG3BaOqfdkqdvU4s2rzeZuOzLmkTH1y9sJT-mgTe7map5E9x7abrNVpyYbaH7JaAb9Yhr1DQ","referenceNumber":83294847,"type":["VerifiableCredential","UniversityDegreeCredential"]}
}

func ExampleCredential_JWTClaims() {
Expand Down
10 changes: 6 additions & 4 deletions pkg/doc/verifiable/presentation.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,13 +476,15 @@ func decodeCredentials(rawCred interface{}, opts *presentationOpts) ([]interface
return nil, nil
}

marshalSingleCredFn := func(cred interface{}) (interface{}, error) {
unmarshalSingleCredFn := func(cred interface{}) (interface{}, error) {
// Check the case when VC is defined in string format (e.g. JWT).
// Decode credential and keep result of decoding.
if sCred, ok := cred.(string); ok {
bCred := []byte(sCred)

credDecoded, err := decodeRaw(bCred, mapOpts(opts))
// TODO: check if JWT VPs require the raw JWT for their JWT VCs
// if so, save the raw JWT strings returned from decodeRaw()
credDecoded, _, err := decodeRaw(bCred, mapOpts(opts))
if err != nil {
return nil, fmt.Errorf("decode credential of presentation: %w", err)
}
Expand All @@ -505,7 +507,7 @@ func decodeCredentials(rawCred interface{}, opts *presentationOpts) ([]interface
creds := make([]interface{}, len(cred))

for i := range cred {
c, err := marshalSingleCredFn(cred[i])
c, err := unmarshalSingleCredFn(cred[i])
if err != nil {
return nil, err
}
Expand All @@ -516,7 +518,7 @@ func decodeCredentials(rawCred interface{}, opts *presentationOpts) ([]interface
return creds, nil
default:
// single credential
c, err := marshalSingleCredFn(cred)
c, err := unmarshalSingleCredFn(cred)
if err != nil {
return nil, err
}
Expand Down
18 changes: 17 additions & 1 deletion pkg/wallet/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,20 @@ type QueryParams struct {
Query []json.RawMessage `json:"credentialQuery"`
}

// ProofFormat determines whether a credential or presentation should be signed with an external JWT proof
// (wrapping the credential to form a JWT-VC) or with an embedded LD proof.
type ProofFormat string

const (
// ExternalJWTProofFormat indicates that a credential or presentation should be signed with an external JWT proof.
ExternalJWTProofFormat = "ExternalJWTProofFormat"
// EmbeddedLDProofFormat indicates that a credential or presentation should be signed with an embedded LD proof.
EmbeddedLDProofFormat = "EmbeddedLDProofFormat"
)

// ProofOptions model
//
// Options for adding linked data proofs to a verifiable credential or a verifiable presentation.
// Options for adding JWT or linked data proofs to a verifiable credential or a verifiable presentation.
// To be used as options for issue/prove wallet features.
//
type ProofOptions struct {
Expand All @@ -38,6 +49,11 @@ type ProofOptions struct {
// Created date of the proof.
// Optional, current system time will be used.
Created *time.Time `json:"created,omitempty"`
// ProofFormat determines whether a credential or presentation should be signed with an external JWT proof
// (wrapping the credential to form a JWT-VC) or with an embedded LD proof.
//
// Optional: If empty, defaults to EmbeddedLDProofFormat.
ProofFormat ProofFormat `json:"proofFormat,omitempty"`
// Domain is operational domain of a digital proof.
// Optional, by default domain will not be part of proof.
Domain string `json:"domain,omitempty"`
Expand Down
44 changes: 41 additions & 3 deletions pkg/wallet/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,9 +438,43 @@ func (c *Wallet) Issue(authToken string, credential json.RawMessage,
return nil, fmt.Errorf("failed to prepare proof: %w", err)
}

err = c.addLinkedDataProof(authToken, vc, options, purpose)
if err != nil {
return nil, fmt.Errorf("failed to issue credential: %w", err)
switch options.ProofFormat {
case ExternalJWTProofFormat:
claims, err := vc.JWTClaims(false)
if err != nil {
return nil, fmt.Errorf("failed to generate JWT claims for VC: %w", err)
}

s, err := newKMSSigner(authToken, c.walletCrypto, options)

var alg verifiable.JWSAlgorithm

switch s.keyType {
case kms.ED25519Type:
alg = verifiable.EdDSA
case kms.ECDSAP256TypeIEEEP1363:
alg = verifiable.ECDSASecp256r1
case kms.ECDSAP384TypeIEEEP1363:
alg = verifiable.ECDSASecp384r1
case kms.ECDSAP521TypeIEEEP1363:
alg = verifiable.ECDSASecp521r1
default:
return nil, fmt.Errorf("unsupported keytype for JWT VC issuance")
}

jws, err := claims.MarshalJWS(alg, s, options.VerificationMethod)
if err != nil {
return nil, fmt.Errorf("failed to sign JWS for JWTVC: %w", err)
}

vc.JWT = jws
case EmbeddedLDProofFormat:
fallthrough
default:
err = c.addLinkedDataProof(authToken, vc, options, purpose)
if err != nil {
return nil, fmt.Errorf("failed to issue credential: %w", err)
}
}

return vc, nil
Expand Down Expand Up @@ -817,6 +851,10 @@ func (c *Wallet) validateProofOption(authToken string, opts *ProofOptions, metho
return err
}

if opts.ProofFormat == "" {
opts.ProofFormat = EmbeddedLDProofFormat
}

if opts.ProofRepresentation == nil {
opts.ProofRepresentation = &defaultSignatureRepresentation
}
Expand Down
Loading

0 comments on commit dfc9d56

Please sign in to comment.