From 89c1e47839a3d905d30af21d902b0be5acd2cd42 Mon Sep 17 00:00:00 2001 From: gabe Date: Wed, 31 May 2023 14:10:31 -0700 Subject: [PATCH 1/9] rename verfiers to validators --- credential/exchange/verification.go | 8 +- credential/exchange/verification_test.go | 4 +- credential/jwt.go | 4 +- credential/signature.go | 19 +++-- credential/signature_test.go | 2 +- credential/status/statuslist2021.go | 2 +- credential/validation/validation.go | 73 +++++++++++++++++ .../validation_test.go} | 80 +++++++++---------- .../verifiers.go => validation/validators.go} | 36 ++++----- credential/verification/verification.go | 73 ----------------- crypto/jwx/jwt.go | 2 +- cryptosuite/bbs/bbsplussignatureproofsuite.go | 4 +- cryptosuite/bbs/bbsplussignaturesuite.go | 2 +- cryptosuite/jws2020/jsonwebkey2020.go | 2 +- cryptosuite/jws2020/jwssignaturesuite.go | 4 +- cryptosuite/jws2020/jwssignaturesuite_test.go | 2 +- did/ion/crypto.go | 4 +- did/key/key.go | 10 +-- did/key/resolver_test.go | 2 +- did/model.go | 2 +- did/peer/peer0.go | 2 +- did/peer/peer2.go | 2 +- did/pkh/pkh.go | 8 +- did/resolution/resolver.go | 4 +- did/util.go | 16 ++-- did/util_test.go | 8 +- did/web/web.go | 2 +- did/web/web_test.go | 2 +- example/presentation/presentation.go | 2 +- .../apartment_application.go | 2 +- example/usecase/steel_thread/steel_thread.go | 4 +- sd-jwt/example/main.go | 4 +- sd-jwt/sd_jwt.go | 2 +- 33 files changed, 199 insertions(+), 194 deletions(-) create mode 100644 credential/validation/validation.go rename credential/{verification/verification_test.go => validation/validation_test.go} (57%) rename credential/{verification/verifiers.go => validation/validators.go} (66%) delete mode 100644 credential/verification/verification.go diff --git a/credential/exchange/verification.go b/credential/exchange/verification.go index 27fa0f5b..62b1bd34 100644 --- a/credential/exchange/verification.go +++ b/credential/exchange/verification.go @@ -17,7 +17,7 @@ import ( "github.com/TBD54566975/ssi-sdk/util" ) -// VerifiedSubmissionData is the result of a successful verification of a presentation submission +// VerifiedSubmissionData is the result of a successful validation of a presentation submission // corresponds to the data that was verified, and the filtered data that was used to verify it for a given // input descriptor type VerifiedSubmissionData struct { @@ -58,7 +58,7 @@ func VerifyPresentationSubmission(ctx context.Context, verifier any, resolver re // verify the VP, which in turn verifies all credentials in it _, _, vp, err := credential.VerifyVerifiablePresentationJWT(ctx, jwtVerifier, resolver, string(submission)) if err != nil { - return nil, errors.Wrap(err, "verification of the presentation submission failed") + return nil, errors.Wrap(err, "validation of the presentation submission failed") } return VerifyPresentationSubmissionVP(def, *vp) default: @@ -67,7 +67,7 @@ func VerifyPresentationSubmission(ctx context.Context, verifier any, resolver re } // VerifyPresentationSubmissionVP verifies whether a verifiable presentation is a valid presentation submission -// for a given presentation definition. No signature verification happens here. +// for a given presentation definition. No signature validation happens here. func VerifyPresentationSubmissionVP(def PresentationDefinition, vp credential.VerifiablePresentation) ([]VerifiedSubmissionData, error) { if err := vp.IsValid(); err != nil { return nil, errors.Wrap(err, "presentation submission does not contain a valid VP") @@ -134,7 +134,7 @@ func VerifyPresentationSubmissionVP(def PresentationDefinition, vp credential.Ve submissionDescriptor.ID, submissionDescriptor.Path) } - // TODO(gabe) add in signature verification of claims here https://github.com/TBD54566975/ssi-sdk/issues/71 + // TODO(gabe) add in signature validation of claims here https://github.com/TBD54566975/ssi-sdk/issues/71 _, _, cred, err := credential.ToCredential(claim) if err != nil { return nil, errors.Wrapf(err, "getting claim as json: <%s>", claim) diff --git a/credential/exchange/verification_test.go b/credential/exchange/verification_test.go index e10a7cae..c71d45dd 100644 --- a/credential/exchange/verification_test.go +++ b/credential/exchange/verification_test.go @@ -67,7 +67,7 @@ func TestVerifyPresentationSubmission(t *testing.T) { _, verifier := getJWKSignerVerifier(tt) _, err = VerifyPresentationSubmission(context.Background(), *verifier, resolver, JWTVPTarget, def, []byte{0, 1, 2, 3}) assert.Error(tt, err) - assert.Contains(tt, err.Error(), "verification of the presentation submission failed") + assert.Contains(tt, err.Error(), "validation of the presentation submission failed") }) t.Run("Supported embed target, valid submission, invalid credential format", func(tt *testing.T) { @@ -151,7 +151,7 @@ func TestVerifyPresentationSubmission(t *testing.T) { } func TestVerifyPresentationSubmissionVP(t *testing.T) { - t.Run("Simple verification", func(tt *testing.T) { + t.Run("Simple validation", func(tt *testing.T) { def := PresentationDefinition{ ID: "test-id", InputDescriptors: []InputDescriptor{ diff --git a/credential/jwt.go b/credential/jwt.go index 6353d92e..1769dbc3 100644 --- a/credential/jwt.go +++ b/credential/jwt.go @@ -98,7 +98,7 @@ func SignVerifiableCredentialJWT(signer jwx.Signer, cred VerifiableCredential) ( // VerifyVerifiableCredentialJWT verifies the signature validity on the token and parses // the token in a verifiable credential. -// TODO(gabe) modify this to add additional verification steps such as credential status, expiration, etc. +// TODO(gabe) modify this to add additional validation steps such as credential status, expiration, etc. // related to https://github.com/TBD54566975/ssi-service/issues/122 func VerifyVerifiableCredentialJWT(verifier jwx.Verifier, token string) (jws.Headers, jwt.Token, *VerifiableCredential, error) { if err := verifier.Verify(token); err != nil { @@ -306,7 +306,7 @@ func VerifyVerifiablePresentationJWT(ctx context.Context, verifier jwx.Verifier, return nil, nil, nil, errors.Wrapf(err, "verifying credential %d", i) } if !verified { - return nil, nil, nil, errors.Errorf("credential %d failed signature verification", i) + return nil, nil, nil, errors.Errorf("credential %d failed signature validation", i) } } diff --git a/credential/signature.go b/credential/signature.go index 0c78c514..425723e5 100644 --- a/credential/signature.go +++ b/credential/signature.go @@ -31,13 +31,7 @@ func VerifyCredentialSignature(ctx context.Context, genericCred any, r resolutio if token != nil { return false, errors.New("JWT credentials must include a signature to be verified") } - if cred.IsEmpty() { - return false, errors.New("credential cannot be empty") - } - if cred.GetProof() == nil { - return false, errors.New("credential must have a proof") - } - return false, errors.New("data integrity signature verification not yet implemented") + return VerifyDataIntegrityCredential(*cred, r) case []byte: // turn it into a string and try again return VerifyCredentialSignature(ctx, string(typedCred), r) @@ -94,3 +88,14 @@ func VerifyJWTCredential(cred string, r resolution.Resolver) (bool, error) { } return true, nil } + +func VerifyDataIntegrityCredential(cred VerifiableCredential, r resolution.Resolver) (bool, error) { + if cred.IsEmpty() { + return false, errors.New("credential cannot be empty") + } + if cred.GetProof() == nil { + return false, errors.New("credential must have a proof") + } + + return false, nil +} diff --git a/credential/signature_test.go b/credential/signature_test.go index 476114d4..aed5dbbe 100644 --- a/credential/signature_test.go +++ b/credential/signature_test.go @@ -184,7 +184,7 @@ func TestVerifyJWTCredential(t *testing.T) { jwtCred := getTestJWTCredential(tt, *signer) _, err = VerifyJWTCredential(jwtCred, resolver) assert.Error(tt, err) - assert.Contains(tt, err.Error(), "has no verification methods with kid: missing") + assert.Contains(tt, err.Error(), "has no validation methods with kid: missing") }) t.Run("valid credential, bad signature", func(tt *testing.T) { diff --git a/credential/status/statuslist2021.go b/credential/status/statuslist2021.go index 89e4eb54..3c4fde99 100644 --- a/credential/status/statuslist2021.go +++ b/credential/status/statuslist2021.go @@ -250,7 +250,7 @@ func bitstringExpansion(compressedBitstring string) ([]string, error) { // ValidateCredentialInStatusList determines whether a credential is contained in a status list 2021 credential // https://w3c-ccg.github.io/vc-status-list-2021/#validate-algorithm -// NOTE: this method does not perform credential signature/proof block verification +// NOTE: this method does not perform credential signature/proof block validation func ValidateCredentialInStatusList(credentialToValidate credential.VerifiableCredential, statusCredential credential.VerifiableCredential) (bool, error) { // 1. Let credentialToValidate be a verifiable credentials containing a credentialStatus entry that is a StatusList2021Entry. statusListEntryValue, ok := toStatusList2021Entry(credentialToValidate.CredentialStatus) diff --git a/credential/validation/validation.go b/credential/validation/validation.go new file mode 100644 index 00000000..0431f677 --- /dev/null +++ b/credential/validation/validation.go @@ -0,0 +1,73 @@ +package validation + +import ( + "fmt" + + "github.com/TBD54566975/ssi-sdk/credential" + "github.com/TBD54566975/ssi-sdk/util" + "github.com/pkg/errors" +) + +type CredentialValidator struct { + validators []Validator +} + +type Validator struct { + ID string + ValidateFunc Validate +} + +type ( + // OptionKey uniquely represents an option to be used in a validator + OptionKey string +) + +// Option represents a single option that may be required for a validator +type Option struct { + ID OptionKey + Option any +} + +// GetValidationOption returns a validation option given an ID +func GetValidationOption(opts []Option, id OptionKey) (any, error) { + for _, opt := range opts { + if opt.ID == id { + return opt.Option, nil + } + } + return nil, errors.Errorf("option with id <%s> not found", id) +} + +type Validate func(cred credential.VerifiableCredential, opts ...Option) error + +// NewCredentialValidator creates a new credential validator which executes in the order of the validators provided +// The validators introspect the contents of the credential, and do not handle signature verification. +func NewCredentialValidator(validators []Validator) (*CredentialValidator, error) { + // dedupe + var deduplicatedValidators []Validator + validatorCheck := make(map[string]bool) + for _, validator := range validators { + if _, ok := validatorCheck[validator.ID]; !ok { + validatorCheck[validator.ID] = true + deduplicatedValidators = append(deduplicatedValidators, validator) + } + } + if len(deduplicatedValidators) == 0 { + return nil, errors.New("no validators provided") + } + return &CredentialValidator{validators: deduplicatedValidators}, nil +} + +// ValidateCredential validates a credential given a credential validator +func (cv *CredentialValidator) ValidateCredential(cred credential.VerifiableCredential, opts ...Option) error { + ae := util.NewAppendError() + for _, validator := range cv.validators { + if err := validator.ValidateFunc(cred, opts...); err != nil { + ae.AppendString(fmt.Sprintf("[validator: %s]: %s", validator.ID, err.Error())) + } + } + if !ae.IsEmpty() { + return fmt.Errorf("credential validation failed with <%d> error, %s", ae.NumErrors(), ae.Error().Error()) + } + return nil +} diff --git a/credential/verification/verification_test.go b/credential/validation/validation_test.go similarity index 57% rename from credential/verification/verification_test.go rename to credential/validation/validation_test.go index 8982a001..aaaac3ac 100644 --- a/credential/verification/verification_test.go +++ b/credential/validation/validation_test.go @@ -1,4 +1,4 @@ -package verification +package validation import ( "testing" @@ -9,97 +9,97 @@ import ( ) func TestVerifier(t *testing.T) { - t.Run("Test Basic Verifier", func(tt *testing.T) { - // empty verifier - _, err := NewCredentialVerifier(nil) + t.Run("Test Basic Validator", func(tt *testing.T) { + // empty validator + _, err := NewCredentialValidator(nil) assert.Error(tt, err) - assert.Contains(tt, err.Error(), "no verifiers provided") + assert.Contains(tt, err.Error(), "no validators provided") - // no op verifier - noop := Verifier{ - ID: "noop", - VerifyFunc: NoOpVerifier, + // no op validator + noop := Validator{ + ID: "noop", + ValidateFunc: NoOpValidator, } - verifier, err := NewCredentialVerifier([]Verifier{noop}) + validator, err := NewCredentialValidator([]Validator{noop}) assert.NoError(tt, err) - assert.NotEmpty(tt, verifier) + assert.NotEmpty(tt, validator) - // verify - err = verifier.VerifyCredential(credential.VerifiableCredential{}) + // validate + err = validator.ValidateCredential(credential.VerifiableCredential{}) assert.NoError(tt, err) sampleCredential := getSampleCredential() - err = verifier.VerifyCredential(sampleCredential) + err = validator.ValidateCredential(sampleCredential) assert.NoError(t, err) }) - t.Run("Expiry Verifier", func(tt *testing.T) { - // expiry verifier - expiry := Verifier{ - ID: "expiration date checking", - VerifyFunc: VerifyExpiry, + t.Run("Expiry Validator", func(tt *testing.T) { + // expiry validator + expiry := Validator{ + ID: "expiration date checking", + ValidateFunc: ValidateExpiry, } - verifier, err := NewCredentialVerifier([]Verifier{expiry}) + validator, err := NewCredentialValidator([]Validator{expiry}) assert.NoError(tt, err) - assert.NotEmpty(tt, verifier) + assert.NotEmpty(tt, validator) sampleCredential := getSampleCredential() - err = verifier.VerifyCredential(sampleCredential) + err = validator.ValidateCredential(sampleCredential) assert.Error(tt, err) assert.Contains(tt, err.Error(), "credential has expired as of 2021-01-01 00:00:00 +0000 UTC") }) - t.Run("Schema Verifier", func(tt *testing.T) { - // set up schema verifier - schema := Verifier{ - ID: "JSON Schema checking", - VerifyFunc: VerifyJSONSchema, + t.Run("Schema Validator", func(tt *testing.T) { + // set up schema validator + schema := Validator{ + ID: "JSON Schema checking", + ValidateFunc: ValidateJSONSchema, } - verifier, err := NewCredentialVerifier([]Verifier{schema}) + validator, err := NewCredentialValidator([]Validator{schema}) assert.NoError(t, err) - assert.NotEmpty(t, verifier) + assert.NotEmpty(t, validator) sampleCredential := getSampleCredential() - // verify cred with no schema, no schema passed in - err = verifier.VerifyCredential(sampleCredential) + // validate cred with no schema, no schema passed in + err = validator.ValidateCredential(sampleCredential) assert.NoError(t, err) - // verify cred with no schema, schema passed in + // validate cred with no schema, schema passed in badSchema := `{"bad":"schema"}` - err = verifier.VerifyCredential(sampleCredential, WithSchema(badSchema)) + err = validator.ValidateCredential(sampleCredential, WithSchema(badSchema)) assert.Error(tt, err) assert.Contains(tt, err.Error(), "credential does not have a credentialSchema property") - // verify cred with schema, no schema passed in + // validate cred with schema, no schema passed in sampleCredential.CredentialSchema = &credential.CredentialSchema{ ID: "did:example:MDP8AsFhHzhwUvGNuYkX7T;id=06e126d1-fa44-4882-a243-1e326fbe21db;version=1.0", Type: credschema.JSONSchema2023Type.String(), } - err = verifier.VerifyCredential(sampleCredential) + err = validator.ValidateCredential(sampleCredential) assert.Error(tt, err) assert.Contains(tt, err.Error(), "no schema provided") - // verify cred with schema, schema passed in, cred with bad data + // validate cred with schema, schema passed in, cred with bad data knownSchema := getVCJSONSchema() - err = verifier.VerifyCredential(sampleCredential, WithSchema(knownSchema)) + err = validator.ValidateCredential(sampleCredential, WithSchema(knownSchema)) assert.Error(tt, err) assert.Contains(tt, err.Error(), "missing properties: 'emailAddress'") - // verify cred with schema, schema passed in, cred with good data + // validate cred with schema, schema passed in, cred with good data sampleCredential.CredentialSubject = map[string]any{ "id": "test-vc-id", "emailAddress": "grandma@aol.com", } - err = verifier.VerifyCredential(sampleCredential, WithSchema(knownSchema)) + err = validator.ValidateCredential(sampleCredential, WithSchema(knownSchema)) assert.NoError(tt, err) }) } -func NoOpVerifier(_ credential.VerifiableCredential, _ ...Option) error { +func NoOpValidator(_ credential.VerifiableCredential, _ ...Option) error { return nil } diff --git a/credential/verification/verifiers.go b/credential/validation/validators.go similarity index 66% rename from credential/verification/verifiers.go rename to credential/validation/validators.go index a9598151..411f2b32 100644 --- a/credential/verification/verifiers.go +++ b/credential/validation/validators.go @@ -1,4 +1,4 @@ -package verification +package validation import ( "fmt" @@ -15,14 +15,14 @@ const ( SchemaOption OptionKey = "schema" ) -// VerifyValidCredential verifies a credential's object model depending on the struct tags used on VerifiableCredential -func VerifyValidCredential(cred credential.VerifiableCredential, _ ...Option) error { +// ValidateCredential verifies a credential's object model depending on the struct tags used on VerifiableCredential +func ValidateCredential(cred credential.VerifiableCredential, _ ...Option) error { return cred.IsValid() } -// VerifyExpiry verifies a credential's expiry date is not in the past. We assume the date is parseable as +// ValidateExpiry verifies a credential's expiry date is not in the past. We assume the date is parseable as // an RFC3339 date time value. -func VerifyExpiry(cred credential.VerifiableCredential, _ ...Option) error { +func ValidateExpiry(cred credential.VerifiableCredential, _ ...Option) error { if cred.ExpirationDate == "" { return nil } @@ -36,7 +36,7 @@ func VerifyExpiry(cred credential.VerifiableCredential, _ ...Option) error { return nil } -// WithSchema provides a schema as a verification option +// WithSchema provides a schema as a validation option func WithSchema(schema string) Option { return Option{ ID: SchemaOption, @@ -44,18 +44,18 @@ func WithSchema(schema string) Option { } } -// VerifyJSONSchema verifies a credential's data against a Verifiable Credential JSON Schema: +// ValidateJSONSchema verifies a credential's data against a Verifiable Credential JSON Schema: // https://w3c-ccg.github.io/vc-json-schemas/v2/index.html#credential_schema_definition // There is a required single option which is a string JSON value representing the Credential Schema Object -func VerifyJSONSchema(cred credential.VerifiableCredential, opts ...Option) error { +func ValidateJSONSchema(cred credential.VerifiableCredential, opts ...Option) error { hasSchemaProperty := cred.CredentialSchema != nil - schema, err := GetVerificationOption(opts, SchemaOption) + schema, err := GetValidationOption(opts, SchemaOption) if err != nil { // if the cred does not have a schema property, we cannot perform this check if !hasSchemaProperty { return nil } - return errors.Wrap(err, "cannot verify the credential against a JSON schema, no schema provided") + return errors.Wrap(err, "cannot validate the credential against a JSON schema, no schema provided") } // if the cred does not have a schema property, we cannot perform this check if !hasSchemaProperty { @@ -83,19 +83,19 @@ func optionToCredentialSchema(maybeSchema any) (*credschema.JSONSchema, error) { return &credSchema, nil } -func GetKnownVerifiers() []Verifier { - return []Verifier{ +func GetKnownVerifiers() []Validator { + return []Validator{ { - ID: "Object Validation", - VerifyFunc: VerifyValidCredential, + ID: "Data Model Validation", + ValidateFunc: ValidateCredential, }, { - ID: "Expiry Check", - VerifyFunc: VerifyExpiry, + ID: "Expiry Check", + ValidateFunc: ValidateExpiry, }, { - ID: "VC JSON Schema", - VerifyFunc: VerifyJSONSchema, + ID: "VC JSON Schema", + ValidateFunc: ValidateJSONSchema, }, } } diff --git a/credential/verification/verification.go b/credential/verification/verification.go deleted file mode 100644 index f23e0c97..00000000 --- a/credential/verification/verification.go +++ /dev/null @@ -1,73 +0,0 @@ -package verification - -import ( - "fmt" - - "github.com/TBD54566975/ssi-sdk/credential" - "github.com/TBD54566975/ssi-sdk/util" - "github.com/pkg/errors" -) - -type CredentialVerifier struct { - verifiers []Verifier -} - -type Verifier struct { - ID string - VerifyFunc Verify -} - -type ( - // OptionKey uniquely represents an option to be used in a verifier - OptionKey string -) - -// Option represents a single option that may be required for a verifier -type Option struct { - ID OptionKey - Option any -} - -// GetVerificationOption returns a verification option given an ID -func GetVerificationOption(opts []Option, id OptionKey) (any, error) { - for _, opt := range opts { - if opt.ID == id { - return opt.Option, nil - } - } - return nil, errors.Errorf("option with id <%s> not found", id) -} - -type Verify func(cred credential.VerifiableCredential, opts ...Option) error - -// NewCredentialVerifier creates a new credential verifier which executes in the order of the verifiers provided -// The verifiers introspect the contents of the credential, and do not handle signature verification. -func NewCredentialVerifier(verifiers []Verifier) (*CredentialVerifier, error) { - // dedupe - var deduplicatedVerifiers []Verifier - verifierCheck := make(map[string]bool) - for _, verifier := range verifiers { - if _, ok := verifierCheck[verifier.ID]; !ok { - verifierCheck[verifier.ID] = true - deduplicatedVerifiers = append(deduplicatedVerifiers, verifier) - } - } - if len(deduplicatedVerifiers) == 0 { - return nil, errors.New("no verifiers provided") - } - return &CredentialVerifier{verifiers: deduplicatedVerifiers}, nil -} - -// VerifyCredential verifies a credential given a credential verifier -func (cv *CredentialVerifier) VerifyCredential(cred credential.VerifiableCredential, opts ...Option) error { - ae := util.NewAppendError() - for _, verifier := range cv.verifiers { - if err := verifier.VerifyFunc(cred, opts...); err != nil { - ae.AppendString(fmt.Sprintf("[validator: %s]: %s", verifier.ID, err.Error())) - } - } - if !ae.IsEmpty() { - return fmt.Errorf("credential verification failed with <%d> error, %s", ae.NumErrors(), ae.Error().Error()) - } - return nil -} diff --git a/crypto/jwx/jwt.go b/crypto/jwx/jwt.go index 8c51752c..d36913c6 100644 --- a/crypto/jwx/jwt.go +++ b/crypto/jwx/jwt.go @@ -129,7 +129,7 @@ func jwxVerifier(id string, jwk PublicKeyJWK, key gocrypto.PublicKey) (*Verifier jwk.ALG = alg } if !IsSupportedJWXSigningVerificationAlgorithm(jwk.ALG) && !IsExperimentalJWXSigningVerificationAlgorithm(jwk.ALG) { - return nil, fmt.Errorf("unsupported signing/verification algorithm: %s", jwk.ALG) + return nil, fmt.Errorf("unsupported signing/validation algorithm: %s", jwk.ALG) } if convertedPubKey, ok := pubKeyForJWX(key); ok { key = convertedPubKey diff --git a/cryptosuite/bbs/bbsplussignatureproofsuite.go b/cryptosuite/bbs/bbsplussignatureproofsuite.go index aab2adc2..9b00f73c 100644 --- a/cryptosuite/bbs/bbsplussignatureproofsuite.go +++ b/cryptosuite/bbs/bbsplussignatureproofsuite.go @@ -273,7 +273,7 @@ func (b BBSPlusSignatureProofSuite) Verify(v cryptosuite.Verifier, p cryptosuite // make sure we set it back after we're done verifying defer p.SetProof(proof) - // remove the proof value in the proof before verification + // remove the proof value in the proof before validation signatureValue, err := decodeProofValue(gotProof.ProofValue) if err != nil { return errors.Wrap(err, "decoding proof value") @@ -430,7 +430,7 @@ func (b BBSPlusSignatureProofSuite) prepareProof(proof crypto.Proof, opts *crypt genericProof["created"] = GetRFC3339Timestamp() } - // for verification, we must replace the BBS ProofType with the Signature Type + // for validation, we must replace the BBS ProofType with the Signature Type genericProof["type"] = BBSPlusSignature2020 var contexts []any diff --git a/cryptosuite/bbs/bbsplussignaturesuite.go b/cryptosuite/bbs/bbsplussignaturesuite.go index 69127b91..f111390f 100644 --- a/cryptosuite/bbs/bbsplussignaturesuite.go +++ b/cryptosuite/bbs/bbsplussignaturesuite.go @@ -142,7 +142,7 @@ func (b BBSPlusSignatureSuite) Verify(v cryptosuite.Verifier, p cryptosuite.With // make sure we set it back after we're done verifying defer p.SetProof(proof) - // remove the proof value in the proof before verification + // remove the proof value in the proof before validation signatureValue, err := decodeProofValue(gotProof.ProofValue) if err != nil { return errors.Wrap(err, "decoding proof value") diff --git a/cryptosuite/jws2020/jsonwebkey2020.go b/cryptosuite/jws2020/jsonwebkey2020.go index 71cbd5ae..4ef60a9e 100644 --- a/cryptosuite/jws2020/jsonwebkey2020.go +++ b/cryptosuite/jws2020/jsonwebkey2020.go @@ -231,7 +231,7 @@ type JSONWebKeyVerifier struct { jwx.Verifier } -// Verify attempts to verify a `signature` against a given `message`, returning nil if the verification is successful +// Verify attempts to verify a `signature` against a given `message`, returning nil if the validation is successful // and an error should it fail. func (v JSONWebKeyVerifier) Verify(message, signature []byte) error { pubKey, err := v.PublicKeyJWK.ToPublicKey() diff --git a/cryptosuite/jws2020/jwssignaturesuite.go b/cryptosuite/jws2020/jwssignaturesuite.go index 091f6e21..220fb367 100644 --- a/cryptosuite/jws2020/jwssignaturesuite.go +++ b/cryptosuite/jws2020/jwssignaturesuite.go @@ -108,7 +108,7 @@ func (j JWSSignatureSuite) Verify(v cryptosuite.Verifier, p cryptosuite.WithEmbe proof := p.GetProof() gotProof, err := JSONWebSignatureProofFromGenericProof(*proof) if err != nil { - return errors.Wrap(err, "could not prepare proof for verification; error coercing proof into JsonWebSignature2020 proof") + return errors.Wrap(err, "could not prepare proof for validation; error coercing proof into JsonWebSignature2020 proof") } // remove proof before verifying @@ -117,7 +117,7 @@ func (j JWSSignatureSuite) Verify(v cryptosuite.Verifier, p cryptosuite.WithEmbe // make sure we set it back after we're done verifying defer p.SetProof(proof) - // remove the JWS value in the proof before verification + // remove the JWS value in the proof before validation jwsCopy := []byte(gotProof.JWS) gotProof.SetDetachedJWS("") diff --git a/cryptosuite/jws2020/jwssignaturesuite_test.go b/cryptosuite/jws2020/jwssignaturesuite_test.go index 2473187b..c90da4b4 100644 --- a/cryptosuite/jws2020/jwssignaturesuite_test.go +++ b/cryptosuite/jws2020/jwssignaturesuite_test.go @@ -153,7 +153,7 @@ func TestCredentialLDProof(t *testing.T) { }, } - // create a copy for value verification later + // create a copy for value validation later var preSigned TestCredential err := util.Copy(&knownCred, &preSigned) assert.NoError(t, err) diff --git a/did/ion/crypto.go b/did/ion/crypto.go index b6b55c2a..4435fe70 100644 --- a/did/ion/crypto.go +++ b/did/ion/crypto.go @@ -158,7 +158,7 @@ func (sv *BTCSignerVerifier) Sign(dataHash []byte) ([]byte, error) { return hex.DecodeString(r + s) } -// Verify verifies the given data according to Bitcoin's verification process +// Verify verifies the given data according to Bitcoin's validation process func (sv *BTCSignerVerifier) Verify(data, signature []byte) (bool, error) { r := new(secp256k1.ModNScalar) r.SetBytes((*[32]byte)(signature[:32])) @@ -196,7 +196,7 @@ func (sv *BTCSignerVerifier) SignJWT(data any) (string, error) { return compactJWS, nil } -// VerifyJWS verifies the given data according to the protocol's JWS verification process +// VerifyJWS verifies the given data according to the protocol's JWS validation process func (sv *BTCSignerVerifier) VerifyJWS(jws string) (bool, error) { jwsParts := strings.Split(jws, ".") if len(jwsParts) != 3 { diff --git a/did/key/key.go b/did/key/key.go index 1517034d..b1bc51e6 100644 --- a/did/key/key.go +++ b/did/key/key.go @@ -212,7 +212,7 @@ func (d DIDKey) Expand(opts ...Option) (*did.Document, error) { case cryptosuite.JSONWebKey2020Type: verificationMethod, err = did.ConstructJWKVerificationMethod(keyID, id, pubKey, cryptoKeyType) if err != nil { - return nil, errors.Wrapf(err, "could not construct %s verification method", publicKeyFormat) + return nil, errors.Wrapf(err, "could not construct %s validation method", publicKeyFormat) } case cryptosuite.MultikeyType: multiKeyType, err := did.KeyTypeToMultikeyLDType(cryptoKeyType) @@ -221,13 +221,13 @@ func (d DIDKey) Expand(opts ...Option) (*did.Document, error) { } verificationMethod, err = did.ConstructMultibaseVerificationMethod(keyID, id, pubKey, multiKeyType) if err != nil { - return nil, errors.Wrapf(err, "could not construct %s verification method", publicKeyFormat) + return nil, errors.Wrapf(err, "could not construct %s validation method", publicKeyFormat) } default: return nil, fmt.Errorf("unsupported public key format: %s", publicKeyFormat) } - // always include the first key as a verification method + // always include the first key as a validation method verificationMethodSet := []did.VerificationMethodSet{keyID} doc := did.Document{ @@ -276,11 +276,11 @@ func (d DIDKey) Expand(opts ...Option) (*did.Document, error) { } // https://w3c-ccg.github.io/did-method-key/#derive-encryption-key-algorithm - // the only case we have to consider is if the verification method is X25519 + // the only case we have to consider is if the validation method is X25519 if enableEncryptionDerivation && !isVerificationMethodX25519Key { keyAgreementVerificationMethod, keyAgreementVerificationMethodSet, err := generateKeyAgreementVerificationMethod(*verificationMethod) if err != nil { - return nil, errors.Wrap(err, "could not generate key agreement verification method") + return nil, errors.Wrap(err, "could not generate key agreement validation method") } if keyAgreementVerificationMethod != nil { doc.VerificationMethod = append(doc.VerificationMethod, *keyAgreementVerificationMethod) diff --git a/did/key/resolver_test.go b/did/key/resolver_test.go index 83222efa..ea788beb 100644 --- a/did/key/resolver_test.go +++ b/did/key/resolver_test.go @@ -52,7 +52,7 @@ func TestResolveKeyForDID(t *testing.T) { assert.NoError(tt, err) _, err = resolution.ResolveKeyForDID(context.Background(), r, didKey.String(), "test-kid") assert.Error(tt, err) - assert.Contains(tt, err.Error(), "has no verification methods with kid: test-kid") + assert.Contains(tt, err.Error(), "has no validation methods with kid: test-kid") }) t.Run("valid did; valid kid", func(tt *testing.T) { diff --git a/did/model.go b/did/model.go index b70b5e05..04864c6d 100644 --- a/did/model.go +++ b/did/model.go @@ -52,7 +52,7 @@ type VerificationMethod struct { // VerificationMethodSet is a union type supporting the `authentication`, `assertionMethod`, `keyAgreement`, // `capabilityInvocation`, and `capabilityDelegation` types. -// A set of one or more verification methods. Each verification method MAY be embedded or referenced. +// A set of one or more validation methods. Each validation method MAY be embedded or referenced. // TODO(gabe) consider changing this to a custom unmarshaler https://stackoverflow.com/a/28016508 type VerificationMethodSet any diff --git a/did/peer/peer0.go b/did/peer/peer0.go index 0961d462..61f9ca74 100644 --- a/did/peer/peer0.go +++ b/did/peer/peer0.go @@ -35,7 +35,7 @@ func (Method0) Generate(kt crypto.KeyType, publicKey gocrypto.PublicKey) (*DIDPe } // Resolve resolves a did:peer into a DID Document -// To do so, it decodes the key, constructs a verification method, and returns a DID Document .This allows Method0 +// To do so, it decodes the key, constructs a validation method, and returns a DID Document .This allows Method0 // to implement the DID Resolver interface and be used to expand the did into the DID Document. func (Method0) resolve(didDoc did.DID, _ resolution.Option) (*resolution.Result, error) { d, ok := didDoc.(DIDPeer) diff --git a/did/peer/peer2.go b/did/peer/peer2.go index 2d081b81..1a406058 100644 --- a/did/peer/peer2.go +++ b/did/peer/peer2.go @@ -74,7 +74,7 @@ func (Method2) resolve(didDoc did.DID, _ resolution.Option) (*resolution.Result, case PurposeVerificationCode: vm, err := d.buildVerificationMethod(entry[1:], string(d)) if err != nil { - return nil, errors.Wrap(err, "failed to build verification code") + return nil, errors.Wrap(err, "failed to build validation code") } doc.Authentication = append(doc.Authentication, *vm) case PurposeCapabilityInvocationCode: diff --git a/did/pkh/pkh.go b/did/pkh/pkh.go index 9a0072c9..35a095bd 100644 --- a/did/pkh/pkh.go +++ b/did/pkh/pkh.go @@ -44,7 +44,7 @@ const ( ) // GetDIDPKHContext returns a context which should be manually inserted into each did:pkh document. This will likely -// change over time as new verification methods are supported, and general-purpose methods are specified. +// change over time as new validation methods are supported, and general-purpose methods are specified. func GetDIDPKHContext() (string, error) { b, err := knownContexts.ReadFile("context/" + pkhContextFilename) return string(b), err @@ -130,7 +130,7 @@ func GetDIDPKHNetworkForDID(id string) (Network, error) { return "", fmt.Errorf("could not find network for did:pkh DID: %s", id) } -// GetVerificationTypeForNetwork returns the verification key type for a given network +// GetVerificationTypeForNetwork returns the validation key type for a given network func GetVerificationTypeForNetwork(n Network) (string, error) { switch n { case Bitcoin, Ethereum, Polygon: @@ -152,7 +152,7 @@ func (d PKH) Expand() (*did.Document, error) { verificationMethod, err := constructPKHVerificationMethod(d) if err != nil { - return nil, errors.Wrap(err, "could not construct verification method") + return nil, errors.Wrap(err, "could not construct validation method") } knownDIDPKHContextJSON, err := GetDIDPKHContext() @@ -194,7 +194,7 @@ func constructPKHVerificationMethod(didPKH PKH) (*did.VerificationMethod, error) } verificationType, err := GetVerificationTypeForNetwork(network) if err != nil { - return nil, errors.Wrap(err, "could not find verification type") + return nil, errors.Wrap(err, "could not find validation type") } suffix, err := didPKH.Suffix() diff --git a/did/resolution/resolver.go b/did/resolution/resolver.go index d1999ab5..f5c82de5 100644 --- a/did/resolution/resolver.go +++ b/did/resolution/resolver.go @@ -112,10 +112,10 @@ func ResolveKeyForDID(ctx context.Context, resolver Resolver, id, kid string) (g return nil, errors.Wrapf(err, "resolving DID: %s", id) } - // next, get the verification information (key) from the did document + // next, get the validation information (key) from the did document pubKey, err := did.GetKeyFromVerificationMethod(resolved.Document, kid) if err != nil { - return nil, errors.Wrapf(err, "getting verification information from DID Document: %s", id) + return nil, errors.Wrapf(err, "getting validation information from DID Document: %s", id) } return pubKey, err } diff --git a/did/util.go b/did/util.go index 83869a18..0abef9be 100644 --- a/did/util.go +++ b/did/util.go @@ -31,8 +31,8 @@ const ( SHA256MultiCodec = multicodec.Sha2_256 ) -// GetKeyFromVerificationMethod resolves a DID and provides a kid and public key needed for data verification -// it is possible that a DID has multiple verification methods, in which case a kid must be provided, otherwise +// GetKeyFromVerificationMethod resolves a DID and provides a kid and public key needed for data validation +// it is possible that a DID has multiple validation methods, in which case a kid must be provided, otherwise // resolution will fail. // A KID can be fully qualified (e.g. did:example:123#key-1) or just the fragment (e.g. key-1, #key-1) // Some DIDs, like did:key, use the entire DID as the KID, so we need to handle all three cases. @@ -46,17 +46,17 @@ func GetKeyFromVerificationMethod(did Document, kid string) (gocrypto.PublicKey, verificationMethods := did.VerificationMethod if len(verificationMethods) == 0 { - return nil, errors.Errorf("did<%s> has no verification methods", did.ID) + return nil, errors.Errorf("did<%s> has no validation methods", did.ID) } for _, method := range verificationMethods { - // make sure the kid matches the verification method + // make sure the kid matches the validation method if matchesKIDConstruction(did.ID, kid, method.ID) { return extractKeyFromVerificationMethod(method) } } - return nil, errors.Errorf("did<%s> has no verification methods with kid: %s", did.ID, kid) + return nil, errors.Errorf("did<%s> has no validation methods with kid: %s", did.ID, kid) } // matchesKIDConstruction checks if the targetID matches possible combinations of the did and kid @@ -97,7 +97,7 @@ func extractKeyFromVerificationMethod(method VerificationMethod) (gocrypto.Publi } return pubKey, nil } - return nil, errors.New("no public key found in verification method") + return nil, errors.New("no public key found in validation method") } // MultiBaseToPubKeyBytes converts a multibase encoded public key to public key bytes for known multibase encodings @@ -255,7 +255,7 @@ func DecodeMultibasePublicKeyWithType(data []byte) ([]byte, cryptosuite.LDKeyTyp } } -// ConstructJWKVerificationMethod builds a DID verification method with a known LD key type as a JWK +// ConstructJWKVerificationMethod builds a DID validation method with a known LD key type as a JWK func ConstructJWKVerificationMethod(id, controller string, pubKeyBytes []byte, cryptoKeyType crypto.KeyType) (*VerificationMethod, error) { pubKey, err := crypto.BytesToPubKey(pubKeyBytes, cryptoKeyType) if err != nil { @@ -275,7 +275,7 @@ func ConstructJWKVerificationMethod(id, controller string, pubKeyBytes []byte, c }, nil } -// ConstructMultibaseVerificationMethod builds a DID verification method with a known LD key type as a multibase encoded key +// ConstructMultibaseVerificationMethod builds a DID validation method with a known LD key type as a multibase encoded key func ConstructMultibaseVerificationMethod(id, controller string, pubKey []byte, keyType cryptosuite.LDKeyType) (*VerificationMethod, error) { return &VerificationMethod{ ID: id, diff --git a/did/util_test.go b/did/util_test.go index 34406f5d..b62eba95 100644 --- a/did/util_test.go +++ b/did/util_test.go @@ -23,11 +23,11 @@ func TestGetKeyFromVerificationInformation(t *testing.T) { assert.Contains(tt, err.Error(), "kid is required") }) - t.Run("doc with no verification methods", func(t *testing.T) { + t.Run("doc with no validation methods", func(t *testing.T) { doc := Document{ID: "test-did"} _, err := GetKeyFromVerificationMethod(doc, "test-kid") assert.Error(t, err) - assert.Contains(t, err.Error(), "has no verification methods") + assert.Contains(t, err.Error(), "has no validation methods") }) t.Run("doc without specified kid", func(t *testing.T) { @@ -43,7 +43,7 @@ func TestGetKeyFromVerificationInformation(t *testing.T) { } _, err := GetKeyFromVerificationMethod(doc, "test-kid") assert.Error(t, err) - assert.Contains(t, err.Error(), "no verification methods with kid: test-kid") + assert.Contains(t, err.Error(), "no validation methods with kid: test-kid") }) t.Run("doc with specified kid, bad multibase key", func(t *testing.T) { @@ -108,7 +108,7 @@ func TestGetKeyFromVerificationInformation(t *testing.T) { } _, err := GetKeyFromVerificationMethod(doc, "test-kid") assert.Error(t, err) - assert.Contains(t, err.Error(), "no public key found in verification method") + assert.Contains(t, err.Error(), "no public key found in validation method") }) t.Run("doc with unqualified kid", func(t *testing.T) { diff --git a/did/web/web.go b/did/web/web.go index 25718ce4..5541ed3b 100644 --- a/did/web/web.go +++ b/did/web/web.go @@ -60,7 +60,7 @@ func (d DIDWeb) CreateDoc(kt crypto.KeyType, publicKey []byte) (*did.Document, e verificationMethod, err := did.ConstructJWKVerificationMethod(didWebStr, keyReference, publicKey, kt) if err != nil { - return nil, fmt.Errorf("could not construct verification method for DIDWeb %+v", d) + return nil, fmt.Errorf("could not construct validation method for DIDWeb %+v", d) } verificationMethodSet := []did.VerificationMethodSet{ diff --git a/did/web/web_test.go b/did/web/web_test.go index 476409ac..d7c46106 100644 --- a/did/web/web_test.go +++ b/did/web/web_test.go @@ -117,7 +117,7 @@ func TestDIDWebCreateDoc(t *testing.T) { t.Run("Bad Public Key for JWK", func(tt *testing.T) { _, err := didWebBasic.CreateDoc(crypto.P256, nil) assert.Error(tt, err) - assert.Contains(tt, err.Error(), "could not construct verification method for DIDWeb") + assert.Contains(tt, err.Error(), "could not construct validation method for DIDWeb") }) } diff --git a/example/presentation/presentation.go b/example/presentation/presentation.go index bc77436a..a831ec65 100644 --- a/example/presentation/presentation.go +++ b/example/presentation/presentation.go @@ -76,7 +76,7 @@ func makePresentationRequest(requesterID string, presentationData exchange.Prese return nil, err } - // TODO: Add better documentation on the verification process + // TODO: Add better documentation on the validation process // Seems like needed to know more of: https://github.com/lestrrat-go/jwx/tree/develop/v2/jwt verifier, err := jws2020.NewJSONWebKeyVerifier(audience, jwk.PublicKeyJWK) if err != nil { diff --git a/example/usecase/apartment_application/apartment_application.go b/example/usecase/apartment_application/apartment_application.go index 11fe7a09..9e50bf6b 100644 --- a/example/usecase/apartment_application/apartment_application.go +++ b/example/usecase/apartment_application/apartment_application.go @@ -107,7 +107,7 @@ func main() { err = presentationDefinitionBuilder.SetInputDescriptors([]exchange.InputDescriptor{ { ID: "birthdate", - Purpose: "Age verification", + Purpose: "Age validation", Format: &exchange.ClaimFormat{ JWTVC: &exchange.JWTType{Alg: []crypto.SignatureAlgorithm{crypto.EdDSA}}, }, diff --git a/example/usecase/steel_thread/steel_thread.go b/example/usecase/steel_thread/steel_thread.go index c2fb9771..a60ca2fa 100644 --- a/example/usecase/steel_thread/steel_thread.go +++ b/example/usecase/steel_thread/steel_thread.go @@ -1,5 +1,5 @@ -// Annotated steel thread flow for calling out all signing, verification, and key management. -// This example is focused on the signing, exchange, and verification of objects. +// Annotated steel thread flow for calling out all signing, validation, and key management. +// This example is focused on the signing, exchange, and validation of objects. // We assume there are two parties: // 1 . Alice, using a wallet, applying for a credential diff --git a/sd-jwt/example/main.go b/sd-jwt/example/main.go index 4f38edad..dc36c2dc 100644 --- a/sd-jwt/example/main.go +++ b/sd-jwt/example/main.go @@ -112,7 +112,7 @@ func main() { fmt.Println(string(sdPresentation)) // Amazing! We've been able to only share pieces of information with the bar... but how does the bar know that - // this information is legitimate? Easy, let's do some verification! + // this information is legitimate? Easy, let's do some validation! // First the bar gets the *public* key from the issuer, which is part of the DID document they created. issuerKey, _ := expandedIssuerDID.VerificationMethod[0].PublicKeyJWK.ToPublicKey() @@ -125,7 +125,7 @@ func main() { IssuerKey: issuerKey, }) - // A lack of error means that verification worked! Note that this says nothing related to the truthfulness of the + // A lack of error means that validation worked! Note that this says nothing related to the truthfulness of the // claim. The bar trusts the issuer (the DMV) for this. if err != nil { fmt.Println("This should never happen") diff --git a/sd-jwt/sd_jwt.go b/sd-jwt/sd_jwt.go index 5c5cf569..51b23cda 100644 --- a/sd-jwt/sd_jwt.go +++ b/sd-jwt/sd_jwt.go @@ -424,7 +424,7 @@ type VerificationOptions struct { Alg string IssuerKey any - // The nonce and audience to check for when doing holder binding verification. + // The nonce and audience to check for when doing holder binding validation. // Needed only when HolderBindingOption == VerifyHolderBinding. DesiredNonce, DesiredAudience string From 5aa57dd7247fccd55bc59be1e7e4e6bcdb9e1a3f Mon Sep 17 00:00:00 2001 From: gabe Date: Wed, 31 May 2023 14:26:31 -0700 Subject: [PATCH 2/9] split out parsing --- credential/exchange/submission.go | 3 +- credential/exchange/submission_test.go | 9 +++--- credential/exchange/verification.go | 8 ++++-- credential/exchange/verification_test.go | 7 +++-- credential/{ => integrity}/jws.go | 11 ++++---- credential/{ => integrity}/jws_test.go | 5 ++-- credential/{ => integrity}/jwt.go | 23 +++++++-------- credential/{ => integrity}/jwt_test.go | 13 +++++---- credential/{ => integrity}/signature.go | 27 ++++++++++++------ credential/{ => integrity}/signature_test.go | 24 ++++++++++------ credential/manifest/validation.go | 2 +- credential/manifest/validation_test.go | 3 +- credential/{util.go => parsing/parsing.go} | 28 ++++++++++--------- .../{util_test.go => parsing/parsing_test.go} | 10 ++++--- credential/schema/access.go | 4 +-- .../apartment_application.go | 3 +- .../usecase/employer_university_flow/main.go | 4 +-- .../employer_university_flow/pkg/issuer.go | 5 ++-- .../employer_university_flow/pkg/verifier.go | 4 +-- 19 files changed, 113 insertions(+), 80 deletions(-) rename credential/{ => integrity}/jws.go (88%) rename credential/{ => integrity}/jws_test.go (95%) rename credential/{ => integrity}/jwt.go (93%) rename credential/{ => integrity}/jwt_test.go (95%) rename credential/{ => integrity}/signature.go (77%) rename credential/{ => integrity}/signature_test.go (92%) rename credential/{util.go => parsing/parsing.go} (82%) rename credential/{util_test.go => parsing/parsing_test.go} (94%) diff --git a/credential/exchange/submission.go b/credential/exchange/submission.go index c4c04895..68fc5c21 100644 --- a/credential/exchange/submission.go +++ b/credential/exchange/submission.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/TBD54566975/ssi-sdk/credential" + "github.com/TBD54566975/ssi-sdk/credential/integrity" "github.com/TBD54566975/ssi-sdk/crypto/jwx" "github.com/TBD54566975/ssi-sdk/util" "github.com/goccy/go-json" @@ -165,7 +166,7 @@ func BuildPresentationSubmission(signer any, requester string, def PresentationD if err != nil { return nil, errors.Wrap(err, "unable to fulfill presentation definition with given credentials") } - return credential.SignVerifiablePresentationJWT(jwtSigner, credential.JWTVVPParameters{Audience: []string{requester}}, *vpSubmission) + return integrity.SignVerifiablePresentationJWT(jwtSigner, integrity.JWTVVPParameters{Audience: []string{requester}}, *vpSubmission) default: return nil, fmt.Errorf("presentation submission embed target <%s> is not implemented", et) } diff --git a/credential/exchange/submission_test.go b/credential/exchange/submission_test.go index cfcf0ef6..99ada0de 100644 --- a/credential/exchange/submission_test.go +++ b/credential/exchange/submission_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/TBD54566975/ssi-sdk/credential/integrity" "github.com/TBD54566975/ssi-sdk/cryptosuite/jws2020" "github.com/goccy/go-json" "github.com/oliveagle/jsonpath" @@ -60,7 +61,7 @@ func TestBuildPresentationSubmission(t *testing.T) { resolver, err := resolution.NewResolver([]resolution.Resolver{key.Resolver{}}...) assert.NoError(tt, err) - _, _, _, err = credential.VerifyVerifiablePresentationJWT(context.Background(), *verifier, resolver, string(submissionBytes)) + _, _, _, err = integrity.VerifyVerifiablePresentationJWT(context.Background(), *verifier, resolver, string(submissionBytes)) assert.Error(tt, err) assert.Contains(tt, err.Error(), "credential must have a proof") }) @@ -88,7 +89,7 @@ func TestBuildPresentationSubmission(t *testing.T) { signer, verifier := getJWKSignerVerifier(tt) testVC := getTestVerifiableCredential(signer.ID, signer.ID) - credJWT, err := credential.SignVerifiableCredentialJWT(*signer, testVC) + credJWT, err := integrity.SignVerifiableCredentialJWT(*signer, testVC) assert.NoError(tt, err) assert.NotEmpty(tt, credJWT) presentationClaim := PresentationClaim{ @@ -104,7 +105,7 @@ func TestBuildPresentationSubmission(t *testing.T) { resolver, err := resolution.NewResolver([]resolution.Resolver{key.Resolver{}}...) assert.NoError(tt, err) - _, _, vp, err := credential.VerifyVerifiablePresentationJWT(context.Background(), *verifier, resolver, string(submissionBytes)) + _, _, vp, err := integrity.VerifyVerifiablePresentationJWT(context.Background(), *verifier, resolver, string(submissionBytes)) assert.NoError(tt, err) assert.NoError(tt, vp.IsValid()) @@ -339,7 +340,7 @@ func TestBuildPresentationSubmissionVP(t *testing.T) { assert.Equal(tt, "test-verifiable-credential", asVC.ID) assert.Equal(tt, "Block", asVC.CredentialSubject["company"]) - _, vcJWTToken, asVCJWT, err := credential.ParseVerifiableCredentialFromJWT(*(vp.VerifiableCredential[1].(*string))) + _, vcJWTToken, asVCJWT, err := integrity.ParseVerifiableCredentialFromJWT(*(vp.VerifiableCredential[1].(*string))) assert.NoError(tt, err) assert.NotEmpty(tt, vcJWTToken) assert.NotEmpty(tt, asVCJWT) diff --git a/credential/exchange/verification.go b/credential/exchange/verification.go index 62b1bd34..f9a6fb1a 100644 --- a/credential/exchange/verification.go +++ b/credential/exchange/verification.go @@ -5,6 +5,8 @@ import ( "fmt" "strings" + "github.com/TBD54566975/ssi-sdk/credential/integrity" + "github.com/TBD54566975/ssi-sdk/credential/parsing" "github.com/TBD54566975/ssi-sdk/crypto/jwx" "github.com/TBD54566975/ssi-sdk/did/resolution" "github.com/TBD54566975/ssi-sdk/schema" @@ -56,7 +58,7 @@ func VerifyPresentationSubmission(ctx context.Context, verifier any, resolver re return nil, fmt.Errorf("verifier<%T> is not a JWT verifier", verifier) } // verify the VP, which in turn verifies all credentials in it - _, _, vp, err := credential.VerifyVerifiablePresentationJWT(ctx, jwtVerifier, resolver, string(submission)) + _, _, vp, err := integrity.VerifyVerifiablePresentationJWT(ctx, jwtVerifier, resolver, string(submission)) if err != nil { return nil, errors.Wrap(err, "validation of the presentation submission failed") } @@ -135,7 +137,7 @@ func VerifyPresentationSubmissionVP(def PresentationDefinition, vp credential.Ve } // TODO(gabe) add in signature validation of claims here https://github.com/TBD54566975/ssi-sdk/issues/71 - _, _, cred, err := credential.ToCredential(claim) + _, _, cred, err := parsing.ToCredential(claim) if err != nil { return nil, errors.Wrapf(err, "getting claim as json: <%s>", claim) } @@ -150,7 +152,7 @@ func VerifyPresentationSubmissionVP(def PresentationDefinition, vp credential.Ve // TODO(gabe) consider enforcing limited disclosure if present // for each field we need to verify at least one path matches - credJSON, err := credential.ToCredentialJSONMap(claim) + credJSON, err := parsing.ToCredentialJSONMap(claim) if err != nil { return nil, errors.Wrapf(err, "getting credential as json: %v", cred) } diff --git a/credential/exchange/verification_test.go b/credential/exchange/verification_test.go index c71d45dd..d8f24d2b 100644 --- a/credential/exchange/verification_test.go +++ b/credential/exchange/verification_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/TBD54566975/ssi-sdk/credential/integrity" "github.com/TBD54566975/ssi-sdk/cryptosuite/jws2020" "github.com/stretchr/testify/assert" @@ -134,7 +135,7 @@ func TestVerifyPresentationSubmission(t *testing.T) { signer, verifier := getJWKSignerVerifier(tt) testVC := getTestVerifiableCredential(signer.ID, signer.ID) - credJWT, err := credential.SignVerifiableCredentialJWT(*signer, testVC) + credJWT, err := integrity.SignVerifiableCredentialJWT(*signer, testVC) assert.NoError(tt, err) presentationClaim := PresentationClaim{ Token: util.StringPtr(string(credJWT)), @@ -182,7 +183,7 @@ func TestVerifyPresentationSubmissionVP(t *testing.T) { assert.NoError(tt, err) assert.NotEmpty(tt, submissionBytes) - _, _, verifiablePresentation, err := credential.ParseVerifiablePresentationFromJWT(string(submissionBytes)) + _, _, verifiablePresentation, err := integrity.ParseVerifiablePresentationFromJWT(string(submissionBytes)) assert.NoError(tt, err) _, err = VerifyPresentationSubmissionVP(def, *verifiablePresentation) @@ -519,7 +520,7 @@ func TestVerifyPresentationSubmissionVP(t *testing.T) { } signer, _ := getJWKSignerVerifier(tt) testVC := getTestVerifiableCredential("test-issuer", "test-subject") - vcData, err := credential.SignVerifiableCredentialJWT(*signer, testVC) + vcData, err := integrity.SignVerifiableCredentialJWT(*signer, testVC) assert.NoError(tt, err) b := NewPresentationSubmissionBuilder(def.ID) assert.NoError(tt, b.SetDescriptorMap([]SubmissionDescriptor{ diff --git a/credential/jws.go b/credential/integrity/jws.go similarity index 88% rename from credential/jws.go rename to credential/integrity/jws.go index e791a801..7661cb71 100644 --- a/credential/jws.go +++ b/credential/integrity/jws.go @@ -1,6 +1,7 @@ -package credential +package integrity import ( + "github.com/TBD54566975/ssi-sdk/credential" "github.com/TBD54566975/ssi-sdk/crypto/jwx" "github.com/goccy/go-json" "github.com/lestrrat-go/jwx/v2/jwa" @@ -14,7 +15,7 @@ const ( // SignVerifiableCredentialJWS is prepared according to https://transmute-industries.github.io/vc-jws/. // This is currently an experimental. It's unstable and subject to change. Use at your own peril. -func SignVerifiableCredentialJWS(signer jwx.Signer, cred VerifiableCredential) ([]byte, error) { +func SignVerifiableCredentialJWS(signer jwx.Signer, cred credential.VerifiableCredential) ([]byte, error) { payload, err := json.Marshal(cred) if err != nil { return nil, errors.Wrap(err, "marshalling credential") @@ -38,7 +39,7 @@ func SignVerifiableCredentialJWS(signer jwx.Signer, cred VerifiableCredential) ( // ParseVerifiableCredentialFromJWS parses a JWS. Depending on the `cty` header value, it parses as a JWT or simply // decodes the payload. // This is currently an experimental. It's unstable and subject to change. Use at your own peril. -func ParseVerifiableCredentialFromJWS(token string) (*jws.Message, *VerifiableCredential, error) { +func ParseVerifiableCredentialFromJWS(token string) (*jws.Message, *credential.VerifiableCredential, error) { parsed, err := jws.Parse([]byte(token)) if err != nil { return nil, nil, errors.Wrap(err, "parsing JWS") @@ -55,7 +56,7 @@ func ParseVerifiableCredentialFromJWS(token string) (*jws.Message, *VerifiableCr return parsed, cred, err } - var cred VerifiableCredential + var cred credential.VerifiableCredential if err = json.Unmarshal(parsed.Payload(), &cred); err != nil { return nil, nil, errors.Wrap(err, "reconstructing Verifiable Credential") } @@ -66,7 +67,7 @@ func ParseVerifiableCredentialFromJWS(token string) (*jws.Message, *VerifiableCr // VerifyVerifiableCredentialJWS verifies the signature validity on the token and parses // the token in a verifiable credential. // This is currently an experimental. It's unstable and subject to change. Use at your own peril. -func VerifyVerifiableCredentialJWS(verifier jwx.Verifier, token string) (*jws.Message, *VerifiableCredential, error) { +func VerifyVerifiableCredentialJWS(verifier jwx.Verifier, token string) (*jws.Message, *credential.VerifiableCredential, error) { if err := verifier.VerifyJWS(token); err != nil { return nil, nil, errors.Wrap(err, "verifying JWS") } diff --git a/credential/jws_test.go b/credential/integrity/jws_test.go similarity index 95% rename from credential/jws_test.go rename to credential/integrity/jws_test.go index 005d2e61..2ff73c90 100644 --- a/credential/jws_test.go +++ b/credential/integrity/jws_test.go @@ -1,14 +1,15 @@ -package credential +package integrity import ( "testing" + "github.com/TBD54566975/ssi-sdk/credential" "github.com/lestrrat-go/jwx/v2/jws" "github.com/stretchr/testify/assert" ) func TestVerifiableCredentialJWS(t *testing.T) { - testCredential := VerifiableCredential{ + testCredential := credential.VerifiableCredential{ Context: []any{"https://www.w3.org/2018/credentials/v1", "https://w3id.org/security/suites/jws-2020/v1"}, Type: []any{"VerifiableCredential"}, Issuer: "did:example:123", diff --git a/credential/jwt.go b/credential/integrity/jwt.go similarity index 93% rename from credential/jwt.go rename to credential/integrity/jwt.go index 1769dbc3..39805a53 100644 --- a/credential/jwt.go +++ b/credential/integrity/jwt.go @@ -1,10 +1,11 @@ -package credential +package integrity import ( "context" "fmt" "time" + "github.com/TBD54566975/ssi-sdk/credential" "github.com/TBD54566975/ssi-sdk/crypto/jwx" "github.com/TBD54566975/ssi-sdk/did/resolution" @@ -24,7 +25,7 @@ const ( // SignVerifiableCredentialJWT is prepared according to https://w3c.github.io/vc-jwt/#version-1.1 // which will soon be deprecated by https://w3c.github.io/vc-jwt/ see: https://github.com/TBD54566975/ssi-sdk/issues/191 -func SignVerifiableCredentialJWT(signer jwx.Signer, cred VerifiableCredential) ([]byte, error) { +func SignVerifiableCredentialJWT(signer jwx.Signer, cred credential.VerifiableCredential) ([]byte, error) { if cred.IsEmpty() { return nil, errors.New("credential cannot be empty") } @@ -100,7 +101,7 @@ func SignVerifiableCredentialJWT(signer jwx.Signer, cred VerifiableCredential) ( // the token in a verifiable credential. // TODO(gabe) modify this to add additional validation steps such as credential status, expiration, etc. // related to https://github.com/TBD54566975/ssi-service/issues/122 -func VerifyVerifiableCredentialJWT(verifier jwx.Verifier, token string) (jws.Headers, jwt.Token, *VerifiableCredential, error) { +func VerifyVerifiableCredentialJWT(verifier jwx.Verifier, token string) (jws.Headers, jwt.Token, *credential.VerifiableCredential, error) { if err := verifier.Verify(token); err != nil { return nil, nil, nil, errors.Wrap(err, "verifying JWT") } @@ -111,7 +112,7 @@ func VerifyVerifiableCredentialJWT(verifier jwx.Verifier, token string) (jws.Hea // https://www.w3.org/TR/vc-data-model/#jwt-decoding // If there are any issues during decoding, an error is returned. As a result, a successfully // decoded VerifiableCredential object is returned. -func ParseVerifiableCredentialFromJWT(token string) (jws.Headers, jwt.Token, *VerifiableCredential, error) { +func ParseVerifiableCredentialFromJWT(token string) (jws.Headers, jwt.Token, *credential.VerifiableCredential, error) { parsed, err := jwt.Parse([]byte(token), jwt.WithValidate(false), jwt.WithVerify(false)) if err != nil { return nil, nil, nil, errors.Wrap(err, "parsing credential token") @@ -133,7 +134,7 @@ func ParseVerifiableCredentialFromJWT(token string) (jws.Headers, jwt.Token, *Ve } // ParseVerifiableCredentialFromToken takes a JWT object and parses it into a VerifiableCredential -func ParseVerifiableCredentialFromToken(token jwt.Token) (*VerifiableCredential, error) { +func ParseVerifiableCredentialFromToken(token jwt.Token) (*credential.VerifiableCredential, error) { // parse remaining JWT properties and set in the credential vcClaim, ok := token.Get(VCJWTProperty) if !ok { @@ -143,7 +144,7 @@ func ParseVerifiableCredentialFromToken(token jwt.Token) (*VerifiableCredential, if err != nil { return nil, errors.Wrap(err, "marshalling credential claim") } - var cred VerifiableCredential + var cred credential.VerifiableCredential if err = json.Unmarshal(vcBytes, &cred); err != nil { return nil, errors.Wrap(err, "reconstructing Verifiable Credential") } @@ -179,7 +180,7 @@ func ParseVerifiableCredentialFromToken(token jwt.Token) (*VerifiableCredential, if cred.CredentialSubject == nil { cred.CredentialSubject = make(map[string]any) } - cred.CredentialSubject[VerifiableCredentialIDProperty] = subStr + cred.CredentialSubject[credential.VerifiableCredentialIDProperty] = subStr } return &cred, nil @@ -195,7 +196,7 @@ type JWTVVPParameters struct { // SignVerifiablePresentationJWT transforms a VP into a VP JWT and signs it // According to https://w3c.github.io/vc-jwt/#version-1.1 -func SignVerifiablePresentationJWT(signer jwx.Signer, parameters JWTVVPParameters, presentation VerifiablePresentation) ([]byte, error) { +func SignVerifiablePresentationJWT(signer jwx.Signer, parameters JWTVVPParameters, presentation credential.VerifiablePresentation) ([]byte, error) { if presentation.IsEmpty() { return nil, errors.New("presentation cannot be empty") } @@ -270,7 +271,7 @@ func SignVerifiablePresentationJWT(signer jwx.Signer, parameters JWTVVPParameter // After decoding the signature of each credential in the presentation is verified. If there are any issues during // decoding or signature validation, an error is returned. As a result, a successfully decoded VerifiablePresentation // object is returned. -func VerifyVerifiablePresentationJWT(ctx context.Context, verifier jwx.Verifier, r resolution.Resolver, token string) (jws.Headers, jwt.Token, *VerifiablePresentation, error) { +func VerifyVerifiablePresentationJWT(ctx context.Context, verifier jwx.Verifier, r resolution.Resolver, token string) (jws.Headers, jwt.Token, *credential.VerifiablePresentation, error) { if r == nil { return nil, nil, nil, errors.New("r cannot be empty") } @@ -318,7 +319,7 @@ func VerifyVerifiablePresentationJWT(ctx context.Context, verifier jwx.Verifier, // https://www.w3.org/TR/vc-data-model/#jwt-decoding // If there are any issues during decoding, an error is returned. As a result, a successfully // decoded VerifiablePresentation object is returned. -func ParseVerifiablePresentationFromJWT(token string) (jws.Headers, jwt.Token, *VerifiablePresentation, error) { +func ParseVerifiablePresentationFromJWT(token string) (jws.Headers, jwt.Token, *credential.VerifiablePresentation, error) { parsed, err := jwt.Parse([]byte(token), jwt.WithValidate(false), jwt.WithVerify(false)) if err != nil { return nil, nil, nil, errors.Wrap(err, "parsing vp token") @@ -331,7 +332,7 @@ func ParseVerifiablePresentationFromJWT(token string) (jws.Headers, jwt.Token, * if err != nil { return nil, nil, nil, errors.Wrap(err, "could not marshalling vp claim") } - var pres VerifiablePresentation + var pres credential.VerifiablePresentation if err = json.Unmarshal(vpBytes, &pres); err != nil { return nil, nil, nil, errors.Wrap(err, "reconstructing Verifiable Presentation") } diff --git a/credential/jwt_test.go b/credential/integrity/jwt_test.go similarity index 95% rename from credential/jwt_test.go rename to credential/integrity/jwt_test.go index dd88bf80..44aa0fc5 100644 --- a/credential/jwt_test.go +++ b/credential/integrity/jwt_test.go @@ -1,10 +1,11 @@ -package credential +package integrity import ( "context" "testing" "time" + "github.com/TBD54566975/ssi-sdk/credential" "github.com/TBD54566975/ssi-sdk/crypto" "github.com/TBD54566975/ssi-sdk/crypto/jwx" "github.com/TBD54566975/ssi-sdk/did/key" @@ -16,7 +17,7 @@ import ( ) func TestVerifiableCredentialJWT(t *testing.T) { - testCredential := VerifiableCredential{ + testCredential := credential.VerifiableCredential{ ID: "http://example.edu/credentials/1872", Context: []any{"https://www.w3.org/2018/credentials/v1", "https://w3id.org/security/suites/jws-2020/v1"}, Type: []string{"VerifiableCredential"}, @@ -90,7 +91,7 @@ func TestVerifiableCredentialJWT(t *testing.T) { func TestVerifiablePresentationJWT(t *testing.T) { t.Run("bad audience", func(tt *testing.T) { - testPresentation := VerifiablePresentation{ + testPresentation := credential.VerifiablePresentation{ Context: []string{"https://www.w3.org/2018/credentials/v1", "https://w3id.org/security/suites/jws-2020/v1"}, Type: []string{"VerifiablePresentation"}, @@ -118,7 +119,7 @@ func TestVerifiablePresentationJWT(t *testing.T) { }) t.Run("no VCs", func(tt *testing.T) { - testPresentation := VerifiablePresentation{ + testPresentation := credential.VerifiablePresentation{ Context: []string{"https://www.w3.org/2018/credentials/v1", "https://w3id.org/security/suites/jws-2020/v1"}, Type: []string{"VerifiablePresentation"}, @@ -175,7 +176,7 @@ func TestVerifiablePresentationJWT(t *testing.T) { subjectKID := expandedSubjectDID.VerificationMethod[0].ID assert.NotEmpty(tt, subjectKID) - testCredential := VerifiableCredential{ + testCredential := credential.VerifiableCredential{ ID: uuid.NewString(), Context: []any{"https://www.w3.org/2018/credentials/v1"}, Type: []string{"VerifiableCredential"}, @@ -192,7 +193,7 @@ func TestVerifiablePresentationJWT(t *testing.T) { signedVC, err := SignVerifiableCredentialJWT(*issuerSigner, testCredential) assert.NoError(t, err) - testPresentation := VerifiablePresentation{ + testPresentation := credential.VerifiablePresentation{ Context: []string{"https://www.w3.org/2018/credentials/v1"}, Type: []string{"VerifiablePresentation"}, Holder: subjectDID.String(), diff --git a/credential/signature.go b/credential/integrity/signature.go similarity index 77% rename from credential/signature.go rename to credential/integrity/signature.go index 425723e5..e195154c 100644 --- a/credential/signature.go +++ b/credential/integrity/signature.go @@ -1,4 +1,4 @@ -package credential +package integrity import ( "context" @@ -6,6 +6,7 @@ import ( "fmt" "reflect" + "github.com/TBD54566975/ssi-sdk/credential" "github.com/TBD54566975/ssi-sdk/crypto/jwx" "github.com/TBD54566975/ssi-sdk/did" "github.com/TBD54566975/ssi-sdk/did/resolution" @@ -23,21 +24,29 @@ func VerifyCredentialSignature(ctx context.Context, genericCred any, r resolutio return false, errors.New("resolution cannot be empty") } switch typedCred := genericCred.(type) { - case *VerifiableCredential, VerifiableCredential, map[string]any: - _, token, cred, err := ToCredential(typedCred) + case map[string]any: + typedCredBytes, err := json.Marshal(typedCred) if err != nil { - return false, errors.Wrap(err, "error converting credential from generic type") + return false, errors.Wrap(err, "marshalling credential map") } - if token != nil { - return false, errors.New("JWT credentials must include a signature to be verified") + var cred credential.VerifiableCredential + if err = json.Unmarshal(typedCredBytes, &cred); err != nil { + return false, errors.Wrap(err, "unmarshalling credential object") } - return VerifyDataIntegrityCredential(*cred, r) + if cred.IsEmpty() { + return false, errors.New("map is not a valid credential") + } + return VerifyCredentialSignature(ctx, cred, r) + case *credential.VerifiableCredential: + return VerifyDataIntegrityCredential(*typedCred, r) + case credential.VerifiableCredential: + return VerifyDataIntegrityCredential(typedCred, r) case []byte: // turn it into a string and try again return VerifyCredentialSignature(ctx, string(typedCred), r) case string: // could be a Data Integrity credential - var cred VerifiableCredential + var cred credential.VerifiableCredential if err := json.Unmarshal([]byte(typedCred), &cred); err == nil { return VerifyCredentialSignature(ctx, cred, r) } @@ -89,7 +98,7 @@ func VerifyJWTCredential(cred string, r resolution.Resolver) (bool, error) { return true, nil } -func VerifyDataIntegrityCredential(cred VerifiableCredential, r resolution.Resolver) (bool, error) { +func VerifyDataIntegrityCredential(cred credential.VerifiableCredential, r resolution.Resolver) (bool, error) { if cred.IsEmpty() { return false, errors.New("credential cannot be empty") } diff --git a/credential/signature_test.go b/credential/integrity/signature_test.go similarity index 92% rename from credential/signature_test.go rename to credential/integrity/signature_test.go index aed5dbbe..da0e1273 100644 --- a/credential/signature_test.go +++ b/credential/integrity/signature_test.go @@ -1,10 +1,11 @@ -package credential +package integrity import ( "context" "testing" "time" + "github.com/TBD54566975/ssi-sdk/credential" "github.com/goccy/go-json" "github.com/TBD54566975/ssi-sdk/crypto" @@ -46,18 +47,15 @@ func TestVerifyCredentialSignature(t *testing.T) { _, err = VerifyCredentialSignature(context.Background(), map[string]any{"a": "test"}, resolver) assert.Error(tt, err) - assert.Contains(tt, err.Error(), "converting credential from generic type: parsing generic credential as either VC or JWT") + assert.Contains(tt, err.Error(), "map is not a valid credential") }) t.Run("data integrity map credential type missing proof", func(tt *testing.T) { resolver, err := resolution.NewResolver([]resolution.Resolver{key.Resolver{}}...) assert.NoError(tt, err) - credential := getTestCredential() - credMap, err := ToCredentialJSONMap(credential) - assert.NoError(tt, err) - - _, err = VerifyCredentialSignature(context.Background(), credMap, resolver) + cred := getTestCredential() + _, err = VerifyCredentialSignature(context.Background(), cred, resolver) assert.Error(tt, err) assert.Contains(tt, err.Error(), "credential must have a proof") }) @@ -229,7 +227,7 @@ func TestVerifyJWTCredential(t *testing.T) { } func getTestJWTCredential(t *testing.T, signer jwx.Signer) string { - cred := VerifiableCredential{ + cred := credential.VerifiableCredential{ ID: uuid.NewString(), Context: []any{"https://www.w3.org/2018/credentials/v1"}, Type: []string{"VerifiableCredential"}, @@ -247,3 +245,13 @@ func getTestJWTCredential(t *testing.T, signer jwx.Signer) string { require.NotEmpty(t, signed) return string(signed) } + +func getTestCredential() credential.VerifiableCredential { + return credential.VerifiableCredential{ + Context: []any{"https://www.w3.org/2018/credentials/v1", "https://w3id.org/security/suites/jws-2020/v1"}, + Type: []string{"VerifiableCredential"}, + Issuer: "did:example:123", + IssuanceDate: "2021-01-01T19:23:24Z", + CredentialSubject: map[string]any{}, + } +} diff --git a/credential/manifest/validation.go b/credential/manifest/validation.go index f618bc70..91222598 100644 --- a/credential/manifest/validation.go +++ b/credential/manifest/validation.go @@ -4,8 +4,8 @@ import ( "fmt" "strings" - credutil "github.com/TBD54566975/ssi-sdk/credential" "github.com/TBD54566975/ssi-sdk/credential/exchange" + credutil "github.com/TBD54566975/ssi-sdk/credential/parsing" errresp "github.com/TBD54566975/ssi-sdk/error" "github.com/TBD54566975/ssi-sdk/util" "github.com/goccy/go-json" diff --git a/credential/manifest/validation_test.go b/credential/manifest/validation_test.go index 8920de8a..6cf2262d 100644 --- a/credential/manifest/validation_test.go +++ b/credential/manifest/validation_test.go @@ -5,6 +5,7 @@ import ( "github.com/TBD54566975/ssi-sdk/credential" "github.com/TBD54566975/ssi-sdk/credential/exchange" + "github.com/TBD54566975/ssi-sdk/credential/integrity" "github.com/TBD54566975/ssi-sdk/crypto" "github.com/TBD54566975/ssi-sdk/crypto/jwx" "github.com/TBD54566975/ssi-sdk/cryptosuite" @@ -413,7 +414,7 @@ func getValidTestCredManifestCredApplicationJWTCred(t *testing.T) (CredentialMan require.NoError(t, err) signer, err := jwx.NewJWXSigner("test-id", "test-kid", privKey) require.NoError(t, err) - jwt, err := credential.SignVerifiableCredentialJWT(*signer, vc) + jwt, err := integrity.SignVerifiableCredentialJWT(*signer, vc) require.NoError(t, err) require.NotEmpty(t, jwt) diff --git a/credential/util.go b/credential/parsing/parsing.go similarity index 82% rename from credential/util.go rename to credential/parsing/parsing.go index bf1db825..eb575533 100644 --- a/credential/util.go +++ b/credential/parsing/parsing.go @@ -1,9 +1,11 @@ -package credential +package parsing import ( "fmt" "reflect" + "github.com/TBD54566975/ssi-sdk/credential" + "github.com/TBD54566975/ssi-sdk/credential/integrity" "github.com/TBD54566975/ssi-sdk/crypto/jwx" "github.com/goccy/go-json" "github.com/lestrrat-go/jwx/v2/jws" @@ -12,7 +14,7 @@ import ( ) // ToCredential turn a generic cred into its known object model -func ToCredential(genericCred any) (jws.Headers, jwt.Token, *VerifiableCredential, error) { +func ToCredential(genericCred any) (jws.Headers, jwt.Token, *credential.VerifiableCredential, error) { switch typedCred := genericCred.(type) { case []byte: // could be a JWT @@ -22,24 +24,24 @@ func ToCredential(genericCred any) (jws.Headers, jwt.Token, *VerifiableCredentia } // could also be a vc - var cred VerifiableCredential + var cred credential.VerifiableCredential if err = json.Unmarshal(genericCred.([]byte), &cred); err != nil { return nil, nil, nil, errors.Wrap(err, "unmarshalling credential object") } return ToCredential(cred) - case *VerifiableCredential: + case *credential.VerifiableCredential: return nil, nil, typedCred, nil - case VerifiableCredential: + case credential.VerifiableCredential: return nil, nil, &typedCred, nil case string: // first try the case where the string is JSON of a VC object - var cred VerifiableCredential + var cred credential.VerifiableCredential if err := json.Unmarshal([]byte(typedCred), &cred); err == nil { return nil, nil, &cred, nil } // next try it as a JWT - return ParseVerifiableCredentialFromJWT(typedCred) + return integrity.ParseVerifiableCredentialFromJWT(typedCred) case map[string]any: // VC or JWTVC JSON credMapBytes, err := json.Marshal(typedCred) @@ -48,7 +50,7 @@ func ToCredential(genericCred any) (jws.Headers, jwt.Token, *VerifiableCredentia } // first try as a VC object - var cred VerifiableCredential + var cred credential.VerifiableCredential if err = json.Unmarshal(credMapBytes, &cred); err == nil && !cred.IsEmpty() { return nil, nil, &cred, nil } @@ -74,7 +76,7 @@ func ToCredentialJSONMap(genericCred any) (map[string]any, error) { } // could also be a vc - var cred VerifiableCredential + var cred credential.VerifiableCredential if err = json.Unmarshal(typedCred, &cred); err != nil { return nil, errors.Wrap(err, "unmarshalling credential object") } @@ -89,7 +91,7 @@ func ToCredentialJSONMap(genericCred any) (map[string]any, error) { } // next try it as a JWT - _, token, _, err := ParseVerifiableCredentialFromJWT(typedCred) + _, token, _, err := integrity.ParseVerifiableCredentialFromJWT(typedCred) if err != nil { return nil, errors.Wrap(err, "parsing credential from JWT") } @@ -102,7 +104,7 @@ func ToCredentialJSONMap(genericCred any) (map[string]any, error) { return nil, errors.Wrap(err, "unmarshalling credential JWT") } return credJSON, nil - case VerifiableCredential, *VerifiableCredential: + case credential.VerifiableCredential, *credential.VerifiableCredential: credJSONBytes, err := json.Marshal(typedCred) if err != nil { return nil, errors.Wrap(err, "marshalling credential object") @@ -117,7 +119,7 @@ func ToCredentialJSONMap(genericCred any) (map[string]any, error) { } // VCJWTJSONToVC converts a JSON representation of a VC JWT into a VerifiableCredential -func VCJWTJSONToVC(vcJWTJSON []byte) (jws.Headers, jwt.Token, *VerifiableCredential, error) { +func VCJWTJSONToVC(vcJWTJSON []byte) (jws.Headers, jwt.Token, *credential.VerifiableCredential, error) { // next, try to turn it into a JWT to check if it's a VC JWT token, err := jwt.Parse(vcJWTJSON, jwt.WithValidate(false), jwt.WithVerify(false)) if err != nil { @@ -130,7 +132,7 @@ func VCJWTJSONToVC(vcJWTJSON []byte) (jws.Headers, jwt.Token, *VerifiableCredent return nil, nil, nil, errors.Wrap(err, "could not get JWT headers") } - cred, err := ParseVerifiableCredentialFromToken(token) + cred, err := integrity.ParseVerifiableCredentialFromToken(token) if err != nil { return nil, nil, nil, errors.Wrap(err, "parsing credential from token") } diff --git a/credential/util_test.go b/credential/parsing/parsing_test.go similarity index 94% rename from credential/util_test.go rename to credential/parsing/parsing_test.go index d17ebec0..6ba0adbb 100644 --- a/credential/util_test.go +++ b/credential/parsing/parsing_test.go @@ -1,8 +1,10 @@ -package credential +package parsing import ( "testing" + "github.com/TBD54566975/ssi-sdk/credential" + "github.com/TBD54566975/ssi-sdk/credential/integrity" "github.com/TBD54566975/ssi-sdk/crypto/jwx" "github.com/TBD54566975/ssi-sdk/cryptosuite" "github.com/TBD54566975/ssi-sdk/cryptosuite/jws2020" @@ -128,7 +130,7 @@ func TestCredentialsFromInterface(t *testing.T) { assert.NoError(tt, err) testCred := getTestCredential() - signed, err := SignVerifiableCredentialJWT(*signer, testCred) + signed, err := integrity.SignVerifiableCredentialJWT(*signer, testCred) assert.NoError(tt, err) assert.NotEmpty(tt, signed) @@ -149,8 +151,8 @@ func TestCredentialsFromInterface(t *testing.T) { }) } -func getTestCredential() VerifiableCredential { - return VerifiableCredential{ +func getTestCredential() credential.VerifiableCredential { + return credential.VerifiableCredential{ Context: []any{"https://www.w3.org/2018/credentials/v1", "https://w3id.org/security/suites/jws-2020/v1"}, Type: []string{"VerifiableCredential"}, Issuer: "did:example:123", diff --git a/credential/schema/access.go b/credential/schema/access.go index bd61cafb..bd744a73 100644 --- a/credential/schema/access.go +++ b/credential/schema/access.go @@ -5,7 +5,7 @@ import ( "fmt" "net/http" - "github.com/TBD54566975/ssi-sdk/credential" + "github.com/TBD54566975/ssi-sdk/credential/parsing" "github.com/goccy/go-json" "github.com/pkg/errors" ) @@ -60,7 +60,7 @@ func (ra *RemoteAccess) GetVCJSONSchema(ctx context.Context, t VCJSONSchemaType, if err = json.NewDecoder(resp.Body).Decode(&schemaCred); err != nil { return nil, errors.Wrap(err, "error decoding schema to generic response") } - _, _, cred, err := credential.ToCredential(schemaCred) + _, _, cred, err := parsing.ToCredential(schemaCred) if err != nil { return nil, errors.Wrap(err, "error decoding schema from credential") } diff --git a/example/usecase/apartment_application/apartment_application.go b/example/usecase/apartment_application/apartment_application.go index 9e50bf6b..6292f1ec 100644 --- a/example/usecase/apartment_application/apartment_application.go +++ b/example/usecase/apartment_application/apartment_application.go @@ -17,6 +17,7 @@ import ( "github.com/TBD54566975/ssi-sdk/credential" "github.com/TBD54566975/ssi-sdk/credential/exchange" + "github.com/TBD54566975/ssi-sdk/credential/integrity" "github.com/TBD54566975/ssi-sdk/crypto" "github.com/TBD54566975/ssi-sdk/crypto/jwx" "github.com/TBD54566975/ssi-sdk/did/key" @@ -88,7 +89,7 @@ func main() { example.HandleExampleError(err, "Failed to make verifiable credential") example.HandleExampleError(vc.IsValid(), "Verifiable credential is not valid") - signedVCBytes, err := credential.SignVerifiableCredentialJWT(*govtSigner, *vc) + signedVCBytes, err := integrity.SignVerifiableCredentialJWT(*govtSigner, *vc) example.HandleExampleError(err, "Failed to sign vc") diff --git a/example/usecase/employer_university_flow/main.go b/example/usecase/employer_university_flow/main.go index 342f46ac..65ab6e52 100644 --- a/example/usecase/employer_university_flow/main.go +++ b/example/usecase/employer_university_flow/main.go @@ -54,10 +54,10 @@ import ( "fmt" "os" + "github.com/TBD54566975/ssi-sdk/credential/integrity" "github.com/goccy/go-json" "github.com/sirupsen/logrus" - "github.com/TBD54566975/ssi-sdk/credential" "github.com/TBD54566975/ssi-sdk/crypto/jwx" "github.com/TBD54566975/ssi-sdk/did" "github.com/TBD54566975/ssi-sdk/did/key" @@ -176,7 +176,7 @@ func main() { r, err := resolution.NewResolver([]resolution.Resolver{key.Resolver{}, peer.Resolver{}}...) example.HandleExampleError(err, "failed to create DID r") - _, _, vp, err := credential.VerifyVerifiablePresentationJWT(context.Background(), *verifier, r, string(submission)) + _, _, vp, err := integrity.VerifyVerifiablePresentationJWT(context.Background(), *verifier, r, string(submission)) example.HandleExampleError(err, "failed to verify jwt") dat, err = json.Marshal(vp) diff --git a/example/usecase/employer_university_flow/pkg/issuer.go b/example/usecase/employer_university_flow/pkg/issuer.go index 8904b9e7..fc68941f 100644 --- a/example/usecase/employer_university_flow/pkg/issuer.go +++ b/example/usecase/employer_university_flow/pkg/issuer.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/TBD54566975/ssi-sdk/credential/integrity" "github.com/TBD54566975/ssi-sdk/crypto/jwx" "github.com/goccy/go-json" @@ -61,12 +62,12 @@ func BuildExampleUniversityVC(signer jwx.Signer, universityDID, recipientDID str logrus.Debug(string(dat)) // sign the credential as a JWT - signedCred, err := credential.SignVerifiableCredentialJWT(signer, knownCred) + signedCred, err := integrity.SignVerifiableCredentialJWT(signer, knownCred) if err != nil { return "", "", err } cred = string(signedCred) - _, credToken, _, err := credential.ParseVerifiableCredentialFromJWT(string(signedCred)) + _, credToken, _, err := integrity.ParseVerifiableCredentialFromJWT(string(signedCred)) if err != nil { return "", "", err } diff --git a/example/usecase/employer_university_flow/pkg/verifier.go b/example/usecase/employer_university_flow/pkg/verifier.go index 08e1eecc..2a4e11bd 100644 --- a/example/usecase/employer_university_flow/pkg/verifier.go +++ b/example/usecase/employer_university_flow/pkg/verifier.go @@ -3,7 +3,7 @@ package pkg import ( "context" - "github.com/TBD54566975/ssi-sdk/credential" + "github.com/TBD54566975/ssi-sdk/credential/integrity" "github.com/TBD54566975/ssi-sdk/crypto/jwx" "github.com/TBD54566975/ssi-sdk/did/resolution" @@ -16,7 +16,7 @@ import ( // 2. All VCs in the VP are valid // 3. That the VC was issued by a trusted entity (implied by the presentation, according to the Presentation Definition) func ValidateAccess(verifier jwx.Verifier, r resolution.Resolver, submissionBytes []byte) error { - _, _, vp, err := credential.VerifyVerifiablePresentationJWT(context.Background(), verifier, r, string(submissionBytes)) + _, _, vp, err := integrity.VerifyVerifiablePresentationJWT(context.Background(), verifier, r, string(submissionBytes)) if err != nil { return errors.Wrap(err, "failed to validate VP signature") } From 2f0805c339a13c3f9c151b885e95abd21070c4dd Mon Sep 17 00:00:00 2001 From: gabe Date: Wed, 31 May 2023 14:26:49 -0700 Subject: [PATCH 3/9] rename --- credential/integrity/signature_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/credential/integrity/signature_test.go b/credential/integrity/signature_test.go index da0e1273..9b1b6adc 100644 --- a/credential/integrity/signature_test.go +++ b/credential/integrity/signature_test.go @@ -64,15 +64,15 @@ func TestVerifyCredentialSignature(t *testing.T) { resolver, err := resolution.NewResolver([]resolution.Resolver{key.Resolver{}}...) assert.NoError(tt, err) - credential := getTestCredential() - _, err = VerifyCredentialSignature(context.Background(), credential, resolver) + cred := getTestCredential() + _, err = VerifyCredentialSignature(context.Background(), cred, resolver) assert.Error(tt, err) - assert.Contains(tt, err.Error(), "credential must have a proof") + assert.Contains(tt, err.Error(), "cred must have a proof") // test with a pointer - _, err = VerifyCredentialSignature(context.Background(), &credential, resolver) + _, err = VerifyCredentialSignature(context.Background(), &cred, resolver) assert.Error(tt, err) - assert.Contains(tt, err.Error(), "credential must have a proof") + assert.Contains(tt, err.Error(), "cred must have a proof") }) t.Run("data integrity credential - as bytes and string", func(tt *testing.T) { From e86a81215f7495c75bd19461c4a52be2c12deba1 Mon Sep 17 00:00:00 2001 From: gabe Date: Wed, 31 May 2023 14:27:51 -0700 Subject: [PATCH 4/9] lint --- credential/integrity/signature.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/credential/integrity/signature.go b/credential/integrity/signature.go index e195154c..4a7cdd77 100644 --- a/credential/integrity/signature.go +++ b/credential/integrity/signature.go @@ -98,7 +98,9 @@ func VerifyJWTCredential(cred string, r resolution.Resolver) (bool, error) { return true, nil } -func VerifyDataIntegrityCredential(cred credential.VerifiableCredential, r resolution.Resolver) (bool, error) { +// VerifyDataIntegrityCredential verifies the signature of a Data Integrity credential +// TODO(gabe): https://github.com/TBD54566975/ssi-sdk/issues/196 +func VerifyDataIntegrityCredential(cred credential.VerifiableCredential, _ resolution.Resolver) (bool, error) { if cred.IsEmpty() { return false, errors.New("credential cannot be empty") } @@ -106,5 +108,5 @@ func VerifyDataIntegrityCredential(cred credential.VerifiableCredential, r resol return false, errors.New("credential must have a proof") } - return false, nil + return false, errors.New("not implemented") } From 81edb5f7b11ec73e988da1b330437993789fe533 Mon Sep 17 00:00:00 2001 From: gabe Date: Wed, 31 May 2023 14:39:19 -0700 Subject: [PATCH 5/9] Fix test --- credential/integrity/signature_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/credential/integrity/signature_test.go b/credential/integrity/signature_test.go index 9b1b6adc..948c7d7d 100644 --- a/credential/integrity/signature_test.go +++ b/credential/integrity/signature_test.go @@ -67,12 +67,12 @@ func TestVerifyCredentialSignature(t *testing.T) { cred := getTestCredential() _, err = VerifyCredentialSignature(context.Background(), cred, resolver) assert.Error(tt, err) - assert.Contains(tt, err.Error(), "cred must have a proof") + assert.Contains(tt, err.Error(), "credential must have a proof") // test with a pointer _, err = VerifyCredentialSignature(context.Background(), &cred, resolver) assert.Error(tt, err) - assert.Contains(tt, err.Error(), "cred must have a proof") + assert.Contains(tt, err.Error(), "credential must have a proof") }) t.Run("data integrity credential - as bytes and string", func(tt *testing.T) { From 3f6cde83f8e9bd43ff58e946143e3cb0a91f50e5 Mon Sep 17 00:00:00 2001 From: gabe Date: Wed, 31 May 2023 14:55:46 -0700 Subject: [PATCH 6/9] bad renames --- credential/exchange/verification.go | 8 ++++---- credential/exchange/verification_test.go | 2 +- credential/integrity/signature_test.go | 2 +- credential/status/statuslist2021.go | 2 +- cryptosuite/bbs/bbsplussignatureproofsuite.go | 4 ++-- cryptosuite/bbs/bbsplussignaturesuite.go | 2 +- cryptosuite/jws2020/jsonwebkey2020.go | 2 +- cryptosuite/jws2020/jwssignaturesuite.go | 4 ++-- cryptosuite/jws2020/jwssignaturesuite_test.go | 2 +- did/ion/crypto.go | 4 ++-- did/key/key.go | 8 ++++---- did/key/resolver_test.go | 2 +- did/model.go | 2 +- did/peer/peer2.go | 2 +- did/pkh/pkh.go | 8 ++++---- did/resolution/resolver.go | 4 ++-- did/util.go | 16 ++++++++-------- did/util_test.go | 6 +++--- did/web/web.go | 2 +- did/web/web_test.go | 2 +- example/presentation/presentation.go | 2 +- example/usecase/steel_thread/steel_thread.go | 4 ++-- 22 files changed, 45 insertions(+), 45 deletions(-) diff --git a/credential/exchange/verification.go b/credential/exchange/verification.go index f9a6fb1a..31141111 100644 --- a/credential/exchange/verification.go +++ b/credential/exchange/verification.go @@ -19,7 +19,7 @@ import ( "github.com/TBD54566975/ssi-sdk/util" ) -// VerifiedSubmissionData is the result of a successful validation of a presentation submission +// VerifiedSubmissionData is the result of a successful verification of a presentation submission // corresponds to the data that was verified, and the filtered data that was used to verify it for a given // input descriptor type VerifiedSubmissionData struct { @@ -60,7 +60,7 @@ func VerifyPresentationSubmission(ctx context.Context, verifier any, resolver re // verify the VP, which in turn verifies all credentials in it _, _, vp, err := integrity.VerifyVerifiablePresentationJWT(ctx, jwtVerifier, resolver, string(submission)) if err != nil { - return nil, errors.Wrap(err, "validation of the presentation submission failed") + return nil, errors.Wrap(err, "verification of the presentation submission failed") } return VerifyPresentationSubmissionVP(def, *vp) default: @@ -69,7 +69,7 @@ func VerifyPresentationSubmission(ctx context.Context, verifier any, resolver re } // VerifyPresentationSubmissionVP verifies whether a verifiable presentation is a valid presentation submission -// for a given presentation definition. No signature validation happens here. +// for a given presentation definition. No signature verification happens here. func VerifyPresentationSubmissionVP(def PresentationDefinition, vp credential.VerifiablePresentation) ([]VerifiedSubmissionData, error) { if err := vp.IsValid(); err != nil { return nil, errors.Wrap(err, "presentation submission does not contain a valid VP") @@ -136,7 +136,7 @@ func VerifyPresentationSubmissionVP(def PresentationDefinition, vp credential.Ve submissionDescriptor.ID, submissionDescriptor.Path) } - // TODO(gabe) add in signature validation of claims here https://github.com/TBD54566975/ssi-sdk/issues/71 + // get the credential from the claim _, _, cred, err := parsing.ToCredential(claim) if err != nil { return nil, errors.Wrapf(err, "getting claim as json: <%s>", claim) diff --git a/credential/exchange/verification_test.go b/credential/exchange/verification_test.go index d8f24d2b..0bbe645c 100644 --- a/credential/exchange/verification_test.go +++ b/credential/exchange/verification_test.go @@ -68,7 +68,7 @@ func TestVerifyPresentationSubmission(t *testing.T) { _, verifier := getJWKSignerVerifier(tt) _, err = VerifyPresentationSubmission(context.Background(), *verifier, resolver, JWTVPTarget, def, []byte{0, 1, 2, 3}) assert.Error(tt, err) - assert.Contains(tt, err.Error(), "validation of the presentation submission failed") + assert.Contains(tt, err.Error(), "verification of the presentation submission failed") }) t.Run("Supported embed target, valid submission, invalid credential format", func(tt *testing.T) { diff --git a/credential/integrity/signature_test.go b/credential/integrity/signature_test.go index 948c7d7d..484f4ddb 100644 --- a/credential/integrity/signature_test.go +++ b/credential/integrity/signature_test.go @@ -182,7 +182,7 @@ func TestVerifyJWTCredential(t *testing.T) { jwtCred := getTestJWTCredential(tt, *signer) _, err = VerifyJWTCredential(jwtCred, resolver) assert.Error(tt, err) - assert.Contains(tt, err.Error(), "has no validation methods with kid: missing") + assert.Contains(tt, err.Error(), "has no verification methods with kid: missing") }) t.Run("valid credential, bad signature", func(tt *testing.T) { diff --git a/credential/status/statuslist2021.go b/credential/status/statuslist2021.go index 3c4fde99..89e4eb54 100644 --- a/credential/status/statuslist2021.go +++ b/credential/status/statuslist2021.go @@ -250,7 +250,7 @@ func bitstringExpansion(compressedBitstring string) ([]string, error) { // ValidateCredentialInStatusList determines whether a credential is contained in a status list 2021 credential // https://w3c-ccg.github.io/vc-status-list-2021/#validate-algorithm -// NOTE: this method does not perform credential signature/proof block validation +// NOTE: this method does not perform credential signature/proof block verification func ValidateCredentialInStatusList(credentialToValidate credential.VerifiableCredential, statusCredential credential.VerifiableCredential) (bool, error) { // 1. Let credentialToValidate be a verifiable credentials containing a credentialStatus entry that is a StatusList2021Entry. statusListEntryValue, ok := toStatusList2021Entry(credentialToValidate.CredentialStatus) diff --git a/cryptosuite/bbs/bbsplussignatureproofsuite.go b/cryptosuite/bbs/bbsplussignatureproofsuite.go index 9b00f73c..aab2adc2 100644 --- a/cryptosuite/bbs/bbsplussignatureproofsuite.go +++ b/cryptosuite/bbs/bbsplussignatureproofsuite.go @@ -273,7 +273,7 @@ func (b BBSPlusSignatureProofSuite) Verify(v cryptosuite.Verifier, p cryptosuite // make sure we set it back after we're done verifying defer p.SetProof(proof) - // remove the proof value in the proof before validation + // remove the proof value in the proof before verification signatureValue, err := decodeProofValue(gotProof.ProofValue) if err != nil { return errors.Wrap(err, "decoding proof value") @@ -430,7 +430,7 @@ func (b BBSPlusSignatureProofSuite) prepareProof(proof crypto.Proof, opts *crypt genericProof["created"] = GetRFC3339Timestamp() } - // for validation, we must replace the BBS ProofType with the Signature Type + // for verification, we must replace the BBS ProofType with the Signature Type genericProof["type"] = BBSPlusSignature2020 var contexts []any diff --git a/cryptosuite/bbs/bbsplussignaturesuite.go b/cryptosuite/bbs/bbsplussignaturesuite.go index f111390f..69127b91 100644 --- a/cryptosuite/bbs/bbsplussignaturesuite.go +++ b/cryptosuite/bbs/bbsplussignaturesuite.go @@ -142,7 +142,7 @@ func (b BBSPlusSignatureSuite) Verify(v cryptosuite.Verifier, p cryptosuite.With // make sure we set it back after we're done verifying defer p.SetProof(proof) - // remove the proof value in the proof before validation + // remove the proof value in the proof before verification signatureValue, err := decodeProofValue(gotProof.ProofValue) if err != nil { return errors.Wrap(err, "decoding proof value") diff --git a/cryptosuite/jws2020/jsonwebkey2020.go b/cryptosuite/jws2020/jsonwebkey2020.go index 4ef60a9e..71cbd5ae 100644 --- a/cryptosuite/jws2020/jsonwebkey2020.go +++ b/cryptosuite/jws2020/jsonwebkey2020.go @@ -231,7 +231,7 @@ type JSONWebKeyVerifier struct { jwx.Verifier } -// Verify attempts to verify a `signature` against a given `message`, returning nil if the validation is successful +// Verify attempts to verify a `signature` against a given `message`, returning nil if the verification is successful // and an error should it fail. func (v JSONWebKeyVerifier) Verify(message, signature []byte) error { pubKey, err := v.PublicKeyJWK.ToPublicKey() diff --git a/cryptosuite/jws2020/jwssignaturesuite.go b/cryptosuite/jws2020/jwssignaturesuite.go index 220fb367..091f6e21 100644 --- a/cryptosuite/jws2020/jwssignaturesuite.go +++ b/cryptosuite/jws2020/jwssignaturesuite.go @@ -108,7 +108,7 @@ func (j JWSSignatureSuite) Verify(v cryptosuite.Verifier, p cryptosuite.WithEmbe proof := p.GetProof() gotProof, err := JSONWebSignatureProofFromGenericProof(*proof) if err != nil { - return errors.Wrap(err, "could not prepare proof for validation; error coercing proof into JsonWebSignature2020 proof") + return errors.Wrap(err, "could not prepare proof for verification; error coercing proof into JsonWebSignature2020 proof") } // remove proof before verifying @@ -117,7 +117,7 @@ func (j JWSSignatureSuite) Verify(v cryptosuite.Verifier, p cryptosuite.WithEmbe // make sure we set it back after we're done verifying defer p.SetProof(proof) - // remove the JWS value in the proof before validation + // remove the JWS value in the proof before verification jwsCopy := []byte(gotProof.JWS) gotProof.SetDetachedJWS("") diff --git a/cryptosuite/jws2020/jwssignaturesuite_test.go b/cryptosuite/jws2020/jwssignaturesuite_test.go index c90da4b4..2473187b 100644 --- a/cryptosuite/jws2020/jwssignaturesuite_test.go +++ b/cryptosuite/jws2020/jwssignaturesuite_test.go @@ -153,7 +153,7 @@ func TestCredentialLDProof(t *testing.T) { }, } - // create a copy for value validation later + // create a copy for value verification later var preSigned TestCredential err := util.Copy(&knownCred, &preSigned) assert.NoError(t, err) diff --git a/did/ion/crypto.go b/did/ion/crypto.go index 4435fe70..b6b55c2a 100644 --- a/did/ion/crypto.go +++ b/did/ion/crypto.go @@ -158,7 +158,7 @@ func (sv *BTCSignerVerifier) Sign(dataHash []byte) ([]byte, error) { return hex.DecodeString(r + s) } -// Verify verifies the given data according to Bitcoin's validation process +// Verify verifies the given data according to Bitcoin's verification process func (sv *BTCSignerVerifier) Verify(data, signature []byte) (bool, error) { r := new(secp256k1.ModNScalar) r.SetBytes((*[32]byte)(signature[:32])) @@ -196,7 +196,7 @@ func (sv *BTCSignerVerifier) SignJWT(data any) (string, error) { return compactJWS, nil } -// VerifyJWS verifies the given data according to the protocol's JWS validation process +// VerifyJWS verifies the given data according to the protocol's JWS verification process func (sv *BTCSignerVerifier) VerifyJWS(jws string) (bool, error) { jwsParts := strings.Split(jws, ".") if len(jwsParts) != 3 { diff --git a/did/key/key.go b/did/key/key.go index b1bc51e6..5e25b93f 100644 --- a/did/key/key.go +++ b/did/key/key.go @@ -212,7 +212,7 @@ func (d DIDKey) Expand(opts ...Option) (*did.Document, error) { case cryptosuite.JSONWebKey2020Type: verificationMethod, err = did.ConstructJWKVerificationMethod(keyID, id, pubKey, cryptoKeyType) if err != nil { - return nil, errors.Wrapf(err, "could not construct %s validation method", publicKeyFormat) + return nil, errors.Wrapf(err, "could not construct %s verification method", publicKeyFormat) } case cryptosuite.MultikeyType: multiKeyType, err := did.KeyTypeToMultikeyLDType(cryptoKeyType) @@ -221,13 +221,13 @@ func (d DIDKey) Expand(opts ...Option) (*did.Document, error) { } verificationMethod, err = did.ConstructMultibaseVerificationMethod(keyID, id, pubKey, multiKeyType) if err != nil { - return nil, errors.Wrapf(err, "could not construct %s validation method", publicKeyFormat) + return nil, errors.Wrapf(err, "could not construct %s verification method", publicKeyFormat) } default: return nil, fmt.Errorf("unsupported public key format: %s", publicKeyFormat) } - // always include the first key as a validation method + // always include the first key as a verification method verificationMethodSet := []did.VerificationMethodSet{keyID} doc := did.Document{ @@ -280,7 +280,7 @@ func (d DIDKey) Expand(opts ...Option) (*did.Document, error) { if enableEncryptionDerivation && !isVerificationMethodX25519Key { keyAgreementVerificationMethod, keyAgreementVerificationMethodSet, err := generateKeyAgreementVerificationMethod(*verificationMethod) if err != nil { - return nil, errors.Wrap(err, "could not generate key agreement validation method") + return nil, errors.Wrap(err, "could not generate key agreement verification method") } if keyAgreementVerificationMethod != nil { doc.VerificationMethod = append(doc.VerificationMethod, *keyAgreementVerificationMethod) diff --git a/did/key/resolver_test.go b/did/key/resolver_test.go index ea788beb..83222efa 100644 --- a/did/key/resolver_test.go +++ b/did/key/resolver_test.go @@ -52,7 +52,7 @@ func TestResolveKeyForDID(t *testing.T) { assert.NoError(tt, err) _, err = resolution.ResolveKeyForDID(context.Background(), r, didKey.String(), "test-kid") assert.Error(tt, err) - assert.Contains(tt, err.Error(), "has no validation methods with kid: test-kid") + assert.Contains(tt, err.Error(), "has no verification methods with kid: test-kid") }) t.Run("valid did; valid kid", func(tt *testing.T) { diff --git a/did/model.go b/did/model.go index 04864c6d..b70b5e05 100644 --- a/did/model.go +++ b/did/model.go @@ -52,7 +52,7 @@ type VerificationMethod struct { // VerificationMethodSet is a union type supporting the `authentication`, `assertionMethod`, `keyAgreement`, // `capabilityInvocation`, and `capabilityDelegation` types. -// A set of one or more validation methods. Each validation method MAY be embedded or referenced. +// A set of one or more verification methods. Each verification method MAY be embedded or referenced. // TODO(gabe) consider changing this to a custom unmarshaler https://stackoverflow.com/a/28016508 type VerificationMethodSet any diff --git a/did/peer/peer2.go b/did/peer/peer2.go index 1a406058..2d081b81 100644 --- a/did/peer/peer2.go +++ b/did/peer/peer2.go @@ -74,7 +74,7 @@ func (Method2) resolve(didDoc did.DID, _ resolution.Option) (*resolution.Result, case PurposeVerificationCode: vm, err := d.buildVerificationMethod(entry[1:], string(d)) if err != nil { - return nil, errors.Wrap(err, "failed to build validation code") + return nil, errors.Wrap(err, "failed to build verification code") } doc.Authentication = append(doc.Authentication, *vm) case PurposeCapabilityInvocationCode: diff --git a/did/pkh/pkh.go b/did/pkh/pkh.go index 35a095bd..9a0072c9 100644 --- a/did/pkh/pkh.go +++ b/did/pkh/pkh.go @@ -44,7 +44,7 @@ const ( ) // GetDIDPKHContext returns a context which should be manually inserted into each did:pkh document. This will likely -// change over time as new validation methods are supported, and general-purpose methods are specified. +// change over time as new verification methods are supported, and general-purpose methods are specified. func GetDIDPKHContext() (string, error) { b, err := knownContexts.ReadFile("context/" + pkhContextFilename) return string(b), err @@ -130,7 +130,7 @@ func GetDIDPKHNetworkForDID(id string) (Network, error) { return "", fmt.Errorf("could not find network for did:pkh DID: %s", id) } -// GetVerificationTypeForNetwork returns the validation key type for a given network +// GetVerificationTypeForNetwork returns the verification key type for a given network func GetVerificationTypeForNetwork(n Network) (string, error) { switch n { case Bitcoin, Ethereum, Polygon: @@ -152,7 +152,7 @@ func (d PKH) Expand() (*did.Document, error) { verificationMethod, err := constructPKHVerificationMethod(d) if err != nil { - return nil, errors.Wrap(err, "could not construct validation method") + return nil, errors.Wrap(err, "could not construct verification method") } knownDIDPKHContextJSON, err := GetDIDPKHContext() @@ -194,7 +194,7 @@ func constructPKHVerificationMethod(didPKH PKH) (*did.VerificationMethod, error) } verificationType, err := GetVerificationTypeForNetwork(network) if err != nil { - return nil, errors.Wrap(err, "could not find validation type") + return nil, errors.Wrap(err, "could not find verification type") } suffix, err := didPKH.Suffix() diff --git a/did/resolution/resolver.go b/did/resolution/resolver.go index f5c82de5..d1999ab5 100644 --- a/did/resolution/resolver.go +++ b/did/resolution/resolver.go @@ -112,10 +112,10 @@ func ResolveKeyForDID(ctx context.Context, resolver Resolver, id, kid string) (g return nil, errors.Wrapf(err, "resolving DID: %s", id) } - // next, get the validation information (key) from the did document + // next, get the verification information (key) from the did document pubKey, err := did.GetKeyFromVerificationMethod(resolved.Document, kid) if err != nil { - return nil, errors.Wrapf(err, "getting validation information from DID Document: %s", id) + return nil, errors.Wrapf(err, "getting verification information from DID Document: %s", id) } return pubKey, err } diff --git a/did/util.go b/did/util.go index 0abef9be..83869a18 100644 --- a/did/util.go +++ b/did/util.go @@ -31,8 +31,8 @@ const ( SHA256MultiCodec = multicodec.Sha2_256 ) -// GetKeyFromVerificationMethod resolves a DID and provides a kid and public key needed for data validation -// it is possible that a DID has multiple validation methods, in which case a kid must be provided, otherwise +// GetKeyFromVerificationMethod resolves a DID and provides a kid and public key needed for data verification +// it is possible that a DID has multiple verification methods, in which case a kid must be provided, otherwise // resolution will fail. // A KID can be fully qualified (e.g. did:example:123#key-1) or just the fragment (e.g. key-1, #key-1) // Some DIDs, like did:key, use the entire DID as the KID, so we need to handle all three cases. @@ -46,17 +46,17 @@ func GetKeyFromVerificationMethod(did Document, kid string) (gocrypto.PublicKey, verificationMethods := did.VerificationMethod if len(verificationMethods) == 0 { - return nil, errors.Errorf("did<%s> has no validation methods", did.ID) + return nil, errors.Errorf("did<%s> has no verification methods", did.ID) } for _, method := range verificationMethods { - // make sure the kid matches the validation method + // make sure the kid matches the verification method if matchesKIDConstruction(did.ID, kid, method.ID) { return extractKeyFromVerificationMethod(method) } } - return nil, errors.Errorf("did<%s> has no validation methods with kid: %s", did.ID, kid) + return nil, errors.Errorf("did<%s> has no verification methods with kid: %s", did.ID, kid) } // matchesKIDConstruction checks if the targetID matches possible combinations of the did and kid @@ -97,7 +97,7 @@ func extractKeyFromVerificationMethod(method VerificationMethod) (gocrypto.Publi } return pubKey, nil } - return nil, errors.New("no public key found in validation method") + return nil, errors.New("no public key found in verification method") } // MultiBaseToPubKeyBytes converts a multibase encoded public key to public key bytes for known multibase encodings @@ -255,7 +255,7 @@ func DecodeMultibasePublicKeyWithType(data []byte) ([]byte, cryptosuite.LDKeyTyp } } -// ConstructJWKVerificationMethod builds a DID validation method with a known LD key type as a JWK +// ConstructJWKVerificationMethod builds a DID verification method with a known LD key type as a JWK func ConstructJWKVerificationMethod(id, controller string, pubKeyBytes []byte, cryptoKeyType crypto.KeyType) (*VerificationMethod, error) { pubKey, err := crypto.BytesToPubKey(pubKeyBytes, cryptoKeyType) if err != nil { @@ -275,7 +275,7 @@ func ConstructJWKVerificationMethod(id, controller string, pubKeyBytes []byte, c }, nil } -// ConstructMultibaseVerificationMethod builds a DID validation method with a known LD key type as a multibase encoded key +// ConstructMultibaseVerificationMethod builds a DID verification method with a known LD key type as a multibase encoded key func ConstructMultibaseVerificationMethod(id, controller string, pubKey []byte, keyType cryptosuite.LDKeyType) (*VerificationMethod, error) { return &VerificationMethod{ ID: id, diff --git a/did/util_test.go b/did/util_test.go index b62eba95..01dd0e9d 100644 --- a/did/util_test.go +++ b/did/util_test.go @@ -27,7 +27,7 @@ func TestGetKeyFromVerificationInformation(t *testing.T) { doc := Document{ID: "test-did"} _, err := GetKeyFromVerificationMethod(doc, "test-kid") assert.Error(t, err) - assert.Contains(t, err.Error(), "has no validation methods") + assert.Contains(t, err.Error(), "has no verification methods") }) t.Run("doc without specified kid", func(t *testing.T) { @@ -43,7 +43,7 @@ func TestGetKeyFromVerificationInformation(t *testing.T) { } _, err := GetKeyFromVerificationMethod(doc, "test-kid") assert.Error(t, err) - assert.Contains(t, err.Error(), "no validation methods with kid: test-kid") + assert.Contains(t, err.Error(), "no verification methods with kid: test-kid") }) t.Run("doc with specified kid, bad multibase key", func(t *testing.T) { @@ -108,7 +108,7 @@ func TestGetKeyFromVerificationInformation(t *testing.T) { } _, err := GetKeyFromVerificationMethod(doc, "test-kid") assert.Error(t, err) - assert.Contains(t, err.Error(), "no public key found in validation method") + assert.Contains(t, err.Error(), "no public key found in verification method") }) t.Run("doc with unqualified kid", func(t *testing.T) { diff --git a/did/web/web.go b/did/web/web.go index 5541ed3b..25718ce4 100644 --- a/did/web/web.go +++ b/did/web/web.go @@ -60,7 +60,7 @@ func (d DIDWeb) CreateDoc(kt crypto.KeyType, publicKey []byte) (*did.Document, e verificationMethod, err := did.ConstructJWKVerificationMethod(didWebStr, keyReference, publicKey, kt) if err != nil { - return nil, fmt.Errorf("could not construct validation method for DIDWeb %+v", d) + return nil, fmt.Errorf("could not construct verification method for DIDWeb %+v", d) } verificationMethodSet := []did.VerificationMethodSet{ diff --git a/did/web/web_test.go b/did/web/web_test.go index d7c46106..476409ac 100644 --- a/did/web/web_test.go +++ b/did/web/web_test.go @@ -117,7 +117,7 @@ func TestDIDWebCreateDoc(t *testing.T) { t.Run("Bad Public Key for JWK", func(tt *testing.T) { _, err := didWebBasic.CreateDoc(crypto.P256, nil) assert.Error(tt, err) - assert.Contains(tt, err.Error(), "could not construct validation method for DIDWeb") + assert.Contains(tt, err.Error(), "could not construct verification method for DIDWeb") }) } diff --git a/example/presentation/presentation.go b/example/presentation/presentation.go index a831ec65..bc77436a 100644 --- a/example/presentation/presentation.go +++ b/example/presentation/presentation.go @@ -76,7 +76,7 @@ func makePresentationRequest(requesterID string, presentationData exchange.Prese return nil, err } - // TODO: Add better documentation on the validation process + // TODO: Add better documentation on the verification process // Seems like needed to know more of: https://github.com/lestrrat-go/jwx/tree/develop/v2/jwt verifier, err := jws2020.NewJSONWebKeyVerifier(audience, jwk.PublicKeyJWK) if err != nil { diff --git a/example/usecase/steel_thread/steel_thread.go b/example/usecase/steel_thread/steel_thread.go index a60ca2fa..c2fb9771 100644 --- a/example/usecase/steel_thread/steel_thread.go +++ b/example/usecase/steel_thread/steel_thread.go @@ -1,5 +1,5 @@ -// Annotated steel thread flow for calling out all signing, validation, and key management. -// This example is focused on the signing, exchange, and validation of objects. +// Annotated steel thread flow for calling out all signing, verification, and key management. +// This example is focused on the signing, exchange, and verification of objects. // We assume there are two parties: // 1 . Alice, using a wallet, applying for a credential From e4398f4c985013dd8bc88bf19e8f4a8c381d5465 Mon Sep 17 00:00:00 2001 From: gabe Date: Wed, 31 May 2023 14:57:56 -0700 Subject: [PATCH 7/9] renames --- credential/exchange/verification_test.go | 2 +- did/peer/peer0.go | 2 +- did/util_test.go | 2 +- .../apartment_application.go | 2 +- sd-jwt/example/main.go | 4 +-- sd-jwt/sd_jwt.go | 30 +++++++++---------- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/credential/exchange/verification_test.go b/credential/exchange/verification_test.go index 0bbe645c..a4709512 100644 --- a/credential/exchange/verification_test.go +++ b/credential/exchange/verification_test.go @@ -152,7 +152,7 @@ func TestVerifyPresentationSubmission(t *testing.T) { } func TestVerifyPresentationSubmissionVP(t *testing.T) { - t.Run("Simple validation", func(tt *testing.T) { + t.Run("Simple verification", func(tt *testing.T) { def := PresentationDefinition{ ID: "test-id", InputDescriptors: []InputDescriptor{ diff --git a/did/peer/peer0.go b/did/peer/peer0.go index 61f9ca74..c2d13bc3 100644 --- a/did/peer/peer0.go +++ b/did/peer/peer0.go @@ -35,7 +35,7 @@ func (Method0) Generate(kt crypto.KeyType, publicKey gocrypto.PublicKey) (*DIDPe } // Resolve resolves a did:peer into a DID Document -// To do so, it decodes the key, constructs a validation method, and returns a DID Document .This allows Method0 +// To do so, it decodes the key, constructs a verification method, and returns a DID Document .This allows Method0 // to implement the DID Resolver interface and be used to expand the did into the DID Document. func (Method0) resolve(didDoc did.DID, _ resolution.Option) (*resolution.Result, error) { d, ok := didDoc.(DIDPeer) diff --git a/did/util_test.go b/did/util_test.go index 01dd0e9d..34406f5d 100644 --- a/did/util_test.go +++ b/did/util_test.go @@ -23,7 +23,7 @@ func TestGetKeyFromVerificationInformation(t *testing.T) { assert.Contains(tt, err.Error(), "kid is required") }) - t.Run("doc with no validation methods", func(t *testing.T) { + t.Run("doc with no verification methods", func(t *testing.T) { doc := Document{ID: "test-did"} _, err := GetKeyFromVerificationMethod(doc, "test-kid") assert.Error(t, err) diff --git a/example/usecase/apartment_application/apartment_application.go b/example/usecase/apartment_application/apartment_application.go index 6292f1ec..34d88a19 100644 --- a/example/usecase/apartment_application/apartment_application.go +++ b/example/usecase/apartment_application/apartment_application.go @@ -108,7 +108,7 @@ func main() { err = presentationDefinitionBuilder.SetInputDescriptors([]exchange.InputDescriptor{ { ID: "birthdate", - Purpose: "Age validation", + Purpose: "Age verification", Format: &exchange.ClaimFormat{ JWTVC: &exchange.JWTType{Alg: []crypto.SignatureAlgorithm{crypto.EdDSA}}, }, diff --git a/sd-jwt/example/main.go b/sd-jwt/example/main.go index dc36c2dc..4f38edad 100644 --- a/sd-jwt/example/main.go +++ b/sd-jwt/example/main.go @@ -112,7 +112,7 @@ func main() { fmt.Println(string(sdPresentation)) // Amazing! We've been able to only share pieces of information with the bar... but how does the bar know that - // this information is legitimate? Easy, let's do some validation! + // this information is legitimate? Easy, let's do some verification! // First the bar gets the *public* key from the issuer, which is part of the DID document they created. issuerKey, _ := expandedIssuerDID.VerificationMethod[0].PublicKeyJWK.ToPublicKey() @@ -125,7 +125,7 @@ func main() { IssuerKey: issuerKey, }) - // A lack of error means that validation worked! Note that this says nothing related to the truthfulness of the + // A lack of error means that verification worked! Note that this says nothing related to the truthfulness of the // claim. The bar trusts the issuer (the DMV) for this. if err != nil { fmt.Println("This should never happen") diff --git a/sd-jwt/sd_jwt.go b/sd-jwt/sd_jwt.go index 51b23cda..9aeae050 100644 --- a/sd-jwt/sd_jwt.go +++ b/sd-jwt/sd_jwt.go @@ -384,7 +384,7 @@ func parseDisclosures(disclosuresData []string, hashAlg HashFunc) (map[string]*D ds = append(ds, d) } disclosureDigests := make(map[string]*Disclosure, len(ds)) - //For each Disclosure provided: + // For each Disclosure provided: for _, disclosure := range ds { // Calculate the digest over the base64url-encoded string as described in Section 5.1.1.2. disclosureDigests[disclosure.Digest(hashAlg)] = disclosure @@ -424,7 +424,7 @@ type VerificationOptions struct { Alg string IssuerKey any - // The nonce and audience to check for when doing holder binding validation. + // The nonce and audience to check for when doing holder binding verification. // Needed only when HolderBindingOption == VerifyHolderBinding. DesiredNonce, DesiredAudience string @@ -444,16 +444,16 @@ func VerifySDPresentation(presentation []byte, verificationOptions VerificationO // Validate the SD-JWT: // - //Ensure that a signing algorithm was used that was deemed secure for the application. Refer to [RFC8725], Sections 3.1 and 3.2 for details. The none algorithm MUST NOT be accepted. - //Validate the signature over the SD-JWT. - //Validate the Issuer of the SD-JWT and that the signing key belongs to this Issuer. - //Check that the SD-JWT is valid using nbf, iat, and exp claims, if provided in the SD-JWT, and not selectively disclosed. + // Ensure that a signing algorithm was used that was deemed secure for the application. Refer to [RFC8725], Sections 3.1 and 3.2 for details. The none algorithm MUST NOT be accepted. + // Validate the signature over the SD-JWT. + // Validate the Issuer of the SD-JWT and that the signing key belongs to this Issuer. + // Check that the SD-JWT is valid using nbf, iat, and exp claims, if provided in the SD-JWT, and not selectively disclosed. sdToken, err := jwt.Parse([]byte(sdParts[0]), jwt.WithKey(jwa.KeyAlgorithmFrom(verificationOptions.Alg), verificationOptions.IssuerKey), jwt.WithValidate(true)) if err != nil { return nil, errors.Wrap(err, "parsing jwt") } - //Check that the _sd_alg claim value is understood and the hash algorithm is deemed secure. + // Check that the _sd_alg claim value is understood and the hash algorithm is deemed secure. hashAlg, err := GetHashAlg(sdToken) if err != nil { return nil, err @@ -468,7 +468,7 @@ func VerifySDPresentation(presentation []byte, verificationOptions VerificationO // Process the Disclosures and _sd keys in the SD-JWT as follows: // - //Create a copy of the SD-JWT payload, if required for further processing. + // Create a copy of the SD-JWT payload, if required for further processing. tokenClaims, err := sdToken.AsMap(context.Background()) if err != nil { return nil, errors.Wrap(err, "gathering token map") @@ -488,13 +488,13 @@ func VerifySDPresentation(presentation []byte, verificationOptions VerificationO // Determine the public key for the Holder from the SD-JWT. holderKey := verificationOptions.ResolveHolderKey(sdToken) - //Ensure that a signing algorithm was used that was deemed secure for the application. Refer to [RFC8725], Sections 3.1 and 3.2 for details. The none algorithm MUST NOT be accepted. - //TODO(https://github.com/TBD54566975/ssi-sdk/issues/377): support holder binding properly as specified in RFC7800. Alg should be coming from CNF. + // Ensure that a signing algorithm was used that was deemed secure for the application. Refer to [RFC8725], Sections 3.1 and 3.2 for details. The none algorithm MUST NOT be accepted. + // TODO(https://github.com/TBD54566975/ssi-sdk/issues/377): support holder binding properly as specified in RFC7800. Alg should be coming from CNF. holderBindingAlg := jwa.ES256K - //Validate the signature over the Holder Binding JWT. - //Check that the Holder Binding JWT is valid using nbf, iat, and exp claims, if provided in the Holder Binding JWT. - //Determine that the Holder Binding JWT is bound to the current transaction and was created for this Verifier (replay protection). This is usually achieved by a nonce and aud field within the Holder Binding JWT. + // Validate the signature over the Holder Binding JWT. + // Check that the Holder Binding JWT is valid using nbf, iat, and exp claims, if provided in the Holder Binding JWT. + // Determine that the Holder Binding JWT is bound to the current transaction and was created for this Verifier (replay protection). This is usually achieved by a nonce and aud field within the Holder Binding JWT. holderBindingToken, err := jwt.Parse([]byte(holderBindingJWT), jwt.WithKey(holderBindingAlg, holderKey), jwt.WithValidate(true)) if err != nil { return nil, errors.Wrap(err, "parsing and validating holder binding jwt") @@ -526,7 +526,7 @@ func VerifySDPresentation(presentation []byte, verificationOptions VerificationO // found inside disclosuresByDigest. func processPayload(claims map[string]any, disclosuresByDigest map[string]*Disclosure, digestsFound map[string]struct{}) error { - //Find all _sd keys in the SD-JWT payload. For each such key perform the following steps (*): + // Find all _sd keys in the SD-JWT payload. For each such key perform the following steps (*): for _, claimValue := range claims { switch claimMap := claimValue.(type) { case map[string]any: @@ -611,7 +611,7 @@ func VerifyIssuance(issuance []byte, verificationOptions IssuanceVerificationOpt return errors.Wrap(err, "getting token claim map") } - //Check that the _sd_alg claim value is understood and the hash algorithm is deemed secure. + // Check that the _sd_alg claim value is understood and the hash algorithm is deemed secure. hashAlg, err := GetHashAlg(sdToken) if err != nil { return err From e72d69e816aae7985fdf4e3b51ff5038b38bb96f Mon Sep 17 00:00:00 2001 From: gabe Date: Wed, 31 May 2023 18:23:03 -0700 Subject: [PATCH 8/9] make id optional --- credential/builder.go | 4 ---- credential/builder_test.go | 9 ++++----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/credential/builder.go b/credential/builder.go index 5e7202b2..b173af27 100644 --- a/credential/builder.go +++ b/credential/builder.go @@ -187,10 +187,6 @@ func (vcb *VerifiableCredentialBuilder) SetCredentialSubject(subject CredentialS return errors.New(BuilderEmptyError) } - if subject.GetID() == "" { - return errors.New("credential subject must have an ID property") - } - vcb.CredentialSubject = subject return nil } diff --git a/credential/builder_test.go b/credential/builder_test.go index 2f0830eb..717bfd56 100644 --- a/credential/builder_test.go +++ b/credential/builder_test.go @@ -168,13 +168,12 @@ func TestCredentialBuilder(t *testing.T) { err = builder.SetCredentialStatus(status) assert.NoError(t, err) - // bad cred subject - no id - badSubject := CredentialSubject{ + // cred subject - no id + subjectWithMissingID := CredentialSubject{ "name": "Satoshi", } - err = builder.SetCredentialSubject(badSubject) - assert.Error(t, err) - assert.Contains(t, err.Error(), "credential subject must have an ID property") + err = builder.SetCredentialSubject(subjectWithMissingID) + assert.NoError(t, err) // good subject subject := CredentialSubject{ From 42d892cf3b079f62816debf754d0b49a1c0d686f Mon Sep 17 00:00:00 2001 From: Andres Uribe Gonzalez Date: Thu, 1 Jun 2023 16:07:43 -0400 Subject: [PATCH 9/9] Missing updates --- credential/validation/validation_test.go | 2 +- crypto/jwx/jwt.go | 2 +- did/key/key.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/credential/validation/validation_test.go b/credential/validation/validation_test.go index aaaac3ac..bdbb26e3 100644 --- a/credential/validation/validation_test.go +++ b/credential/validation/validation_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestVerifier(t *testing.T) { +func TestValidator(t *testing.T) { t.Run("Test Basic Validator", func(tt *testing.T) { // empty validator _, err := NewCredentialValidator(nil) diff --git a/crypto/jwx/jwt.go b/crypto/jwx/jwt.go index d36913c6..8c51752c 100644 --- a/crypto/jwx/jwt.go +++ b/crypto/jwx/jwt.go @@ -129,7 +129,7 @@ func jwxVerifier(id string, jwk PublicKeyJWK, key gocrypto.PublicKey) (*Verifier jwk.ALG = alg } if !IsSupportedJWXSigningVerificationAlgorithm(jwk.ALG) && !IsExperimentalJWXSigningVerificationAlgorithm(jwk.ALG) { - return nil, fmt.Errorf("unsupported signing/validation algorithm: %s", jwk.ALG) + return nil, fmt.Errorf("unsupported signing/verification algorithm: %s", jwk.ALG) } if convertedPubKey, ok := pubKeyForJWX(key); ok { key = convertedPubKey diff --git a/did/key/key.go b/did/key/key.go index 5e25b93f..1517034d 100644 --- a/did/key/key.go +++ b/did/key/key.go @@ -276,7 +276,7 @@ func (d DIDKey) Expand(opts ...Option) (*did.Document, error) { } // https://w3c-ccg.github.io/did-method-key/#derive-encryption-key-algorithm - // the only case we have to consider is if the validation method is X25519 + // the only case we have to consider is if the verification method is X25519 if enableEncryptionDerivation && !isVerificationMethodX25519Key { keyAgreementVerificationMethod, keyAgreementVerificationMethodSet, err := generateKeyAgreementVerificationMethod(*verificationMethod) if err != nil {