Documentation ¶
Index ¶
- Constants
- Variables
- func ExtractArrayValuesForSDJWTV5(obj map[string]interface{}) []string
- type Constraints
- type CwtType
- type Field
- type Filter
- type Format
- type Holder
- type InputDescriptor
- type InputDescriptorMapping
- type JwtType
- type LdpType
- type MatchOption
- type MatchOptions
- type MatchRequirementsOpt
- func WithDefaultPresentationFormat(format string) MatchRequirementsOpt
- func WithSDBBSProofCreator(sdBBSProofCreator *verifiable.BBSProofCreator) MatchRequirementsOpt
- func WithSDCredentialOptions(options ...verifiable.CredentialOpt) MatchRequirementsOpt
- func WithSelectiveDisclosureApply() MatchRequirementsOpt
- type MatchValue
- type MatchedInputDescriptor
- type MatchedSubmissionRequirement
- type Preference
- type PresentationDefinition
- func (pd *PresentationDefinition) CreateVP(credentials []*verifiable.Credential, documentLoader ld.DocumentLoader, ...) (*verifiable.Presentation, error)
- func (pd *PresentationDefinition) CreateVPArray(credentials []*verifiable.Credential, documentLoader ld.DocumentLoader, ...) ([]*verifiable.Presentation, *PresentationSubmission, error)
- func (pd *PresentationDefinition) Match(vpList []*verifiable.Presentation, contextLoader ld.DocumentLoader, ...) ([]*MatchValue, error)
- func (pd *PresentationDefinition) MatchSubmissionRequirement(credentials []*verifiable.Credential, documentLoader ld.DocumentLoader, ...) ([]*MatchedSubmissionRequirement, error)
- func (pd *PresentationDefinition) ValidateSchema() error
- type PresentationSubmission
- type Schema
- type Selection
- type StrOrInt
- type SubmissionRequirement
Examples ¶
- PresentationDefinition.CreateVP (LimitedDisclosureSkipsNonSDVCs)
- PresentationDefinition.CreateVP (MultipleMatches)
- PresentationDefinition.CreateVP (MultipleMatchesDisclosure)
- PresentationDefinition.CreateVP (SubmissionRequirements)
- PresentationDefinition.CreateVP (SubmissionRequirements2)
- PresentationDefinition.CreateVP (SubmissionRequirementsLimitDisclosure)
- PresentationDefinition.CreateVP (V1)
- PresentationDefinition.CreateVP (V1_With_LDPVC_FormatAndProof)
- PresentationDefinition.CreateVP (V1_With_LDP_FormatAndProof)
- PresentationDefinition.CreateVP (V2)
- PresentationDefinition.CreateVP (WithFormatInInputDescriptor)
- PresentationDefinition.CreateVP (WithFrame)
- PresentationDefinition.CreateVP (With_LdpVC_Format)
- PresentationDefinition.CreateVP (With_Ldp_Format)
- PresentationDefinition.Match
- PresentationDefinition.Match (Jwt_vp_path_workaround)
Constants ¶
const ( // PresentationSubmissionJSONLDContextIRI is the JSONLD context of presentation submissions. PresentationSubmissionJSONLDContextIRI = "https://identity.foundation/presentation-exchange/submission/v1" // CredentialApplicationJSONLDContextIRI is the JSONLD context of credential application // which also contains presentation submission details. CredentialApplicationJSONLDContextIRI = "https://identity.foundation/credential-manifest/application/v1" // PresentationSubmissionJSONLDType is the JSONLD type of presentation submissions. PresentationSubmissionJSONLDType = "PresentationSubmission" // CredentialApplicationJSONLDType is the JSONLD type of credential application. CredentialApplicationJSONLDType = "CredentialApplication" )
const ( // All rule`s value. All Selection = "all" // Pick rule`s value. Pick Selection = "pick" // Required predicate`s value. Required Preference = "required" // Preferred predicate`s value. Preferred Preference = "preferred" // FormatJWT presentation exchange format. FormatJWT = "jwt" // FormatJWTVC presentation exchange format. FormatJWTVC = "jwt_vc" // FormatJWTVP presentation exchange format. FormatJWTVP = "jwt_vp" // FormatLDP presentation exchange format. FormatLDP = "ldp" // FormatLDPVC presentation exchange format. FormatLDPVC = "ldp_vc" // FormatLDPVP presentation exchange format. FormatLDPVP = "ldp_vp" )
const DefinitionJSONSchemaV1 = `` /* 13163-byte string literal not displayed */
DefinitionJSONSchemaV1 is the JSONSchema definition for PresentationDefinition. nolint:lll https://github.com/decentralized-identity/presentation-exchange/blob/9a6abc6d2b0f08b6339c9116132fa94c4c834418/test/presentation-definition/schema.json
const DefinitionJSONSchemaV2 = `` /* 7559-byte string literal not displayed */
DefinitionJSONSchemaV2 is the JSONSchema definition for PresentationDefinition. nolint:lll
Variables ¶
var ErrNoCredentials = errors.New("credentials do not satisfy requirements")
ErrNoCredentials when any credentials do not satisfy requirements.
Functions ¶
func ExtractArrayValuesForSDJWTV5 ¶ added in v1.2.0
ExtractArrayValuesForSDJWTV5 extracts array values for SD JWT V5.
Types ¶
type Constraints ¶
type Constraints struct { LimitDisclosure *Preference `json:"limit_disclosure,omitempty"` SubjectIsIssuer *Preference `json:"subject_is_issuer,omitempty"` IsHolder []*Holder `json:"is_holder,omitempty"` Fields []*Field `json:"fields,omitempty"` }
Constraints describes InputDescriptor`s Constraints field.
type CwtType ¶ added in v1.2.0
type CwtType struct {
Alg []string `json:"alg,omitempty"`
}
CwtType contains alg.
type Field ¶
type Field struct { Path []string `json:"path,omitempty"` ID string `json:"id,omitempty"` Purpose string `json:"purpose,omitempty"` Filter *Filter `json:"filter,omitempty"` Predicate *Preference `json:"predicate,omitempty"` IntentToRetain bool `json:"intent_to_retain,omitempty"` Optional bool `json:"optional,omitempty"` }
Field describes Constraints`s Fields field.
type Filter ¶
type Filter struct { Type *string `json:"type,omitempty"` Format string `json:"format,omitempty"` Pattern string `json:"pattern,omitempty"` Minimum StrOrInt `json:"minimum,omitempty"` Maximum StrOrInt `json:"maximum,omitempty"` MinLength int `json:"minLength,omitempty"` MaxLength int `json:"maxLength,omitempty"` ExclusiveMinimum StrOrInt `json:"exclusiveMinimum,omitempty"` ExclusiveMaximum StrOrInt `json:"exclusiveMaximum,omitempty"` Const StrOrInt `json:"const,omitempty"` Enum []StrOrInt `json:"enum,omitempty"` Not map[string]interface{} `json:"not,omitempty"` Contains map[string]interface{} `json:"contains,omitempty"` }
Filter describes filter.
type Format ¶
type Format struct { Jwt *JwtType `json:"jwt,omitempty"` JwtVC *JwtType `json:"jwt_vc,omitempty"` JwtVP *JwtType `json:"jwt_vp,omitempty"` Ldp *LdpType `json:"ldp,omitempty"` LdpVC *LdpType `json:"ldp_vc,omitempty"` LdpVP *LdpType `json:"ldp_vp,omitempty"` CwtVC *CwtType `json:"cwt_vc,omitempty"` CwtVP *CwtType `json:"cwt_vp,omitempty"` }
Format describes PresentationDefinition`s Format field.
type Holder ¶
type Holder struct { FieldID []string `json:"field_id,omitempty"` Directive *Preference `json:"directive,omitempty"` }
Holder describes Constraints`s holder object.
type InputDescriptor ¶
type InputDescriptor struct { ID string `json:"id,omitempty"` Group []string `json:"group,omitempty"` Name string `json:"name,omitempty"` Purpose string `json:"purpose,omitempty"` Metadata map[string]interface{} `json:"metadata,omitempty"` Schema []*Schema `json:"schema,omitempty"` Constraints *Constraints `json:"constraints,omitempty"` Format *Format `json:"format,omitempty"` }
InputDescriptor input descriptors.
type InputDescriptorMapping ¶
type InputDescriptorMapping struct { ID string `json:"id,omitempty"` Format string `json:"format,omitempty"` Path string `json:"path,omitempty"` PathNested *InputDescriptorMapping `json:"path_nested,omitempty"` }
InputDescriptorMapping maps an InputDescriptor to a verifiable credential pointed to by the JSONPath in `Path`.
type LdpType ¶
type LdpType struct {
ProofType []string `json:"proof_type,omitempty"`
}
LdpType contains proof_type.
type MatchOption ¶
type MatchOption func(*MatchOptions)
MatchOption is an option that sets an option for when matching.
func WithCredentialOptions ¶
func WithCredentialOptions(options ...verifiable.CredentialOpt) MatchOption
WithCredentialOptions used when parsing the embedded credentials.
func WithDisableSchemaValidation ¶
func WithDisableSchemaValidation() MatchOption
WithDisableSchemaValidation used to disable schema validation.
func WithMergedSubmission ¶
func WithMergedSubmission(submission *PresentationSubmission) MatchOption
WithMergedSubmission provides a presentation submission that's external to the Presentations being matched, which contains the descriptor mapping for each Presentation.
If there are multiple Presentations, this merged submission should use the Presentation array as the JSON Path root when referencing the contained Presentations and the Credentials within.
func WithMergedSubmissionMap ¶
func WithMergedSubmissionMap(submissionMap map[string]interface{}) MatchOption
WithMergedSubmissionMap provides a presentation submission that's external to the Presentations being matched, which contains the descriptor mapping for each Presentation. This submission is expected to be in the map[string]interface{} format used by json.Unmarshal.
If there are multiple Presentations, this merged submission should use the Presentation array as the JSON Path root when referencing the contained Presentations and the Credentials within.
type MatchOptions ¶
type MatchOptions struct { CredentialOptions []verifiable.CredentialOpt DisableSchemaValidation bool MergedSubmission *PresentationSubmission MergedSubmissionMap map[string]interface{} }
MatchOptions is a holder of options that can set when matching a submission against definitions.
type MatchRequirementsOpt ¶
type MatchRequirementsOpt func(opts *matchRequirementsOpts)
MatchRequirementsOpt is the MatchSubmissionRequirement option.
func WithDefaultPresentationFormat ¶ added in v1.1.2
func WithDefaultPresentationFormat(format string) MatchRequirementsOpt
WithDefaultPresentationFormat sets the default presentation format.
func WithSDBBSProofCreator ¶ added in v1.1.0
func WithSDBBSProofCreator(sdBBSProofCreator *verifiable.BBSProofCreator) MatchRequirementsOpt
WithSDBBSProofCreator used when applying selective disclosure.
func WithSDCredentialOptions ¶
func WithSDCredentialOptions(options ...verifiable.CredentialOpt) MatchRequirementsOpt
WithSDCredentialOptions used when applying selective disclosure.
func WithSelectiveDisclosureApply ¶
func WithSelectiveDisclosureApply() MatchRequirementsOpt
WithSelectiveDisclosureApply enables selective disclosure apply on resulting VC.
type MatchValue ¶
type MatchValue struct { PresentationID string Credential *verifiable.Credential DescriptorID string }
MatchValue holds a matched credential from PresentationDefinition.Match, along with the ID of the presentation that held the matched credential.
type MatchedInputDescriptor ¶
type MatchedInputDescriptor struct { ID string Name string Purpose string Constraints *Constraints Schemas []*Schema MatchedVCs []*verifiable.Credential }
MatchedInputDescriptor contains information about VCs that matched an input descriptor of presentation definition.
type MatchedSubmissionRequirement ¶
type MatchedSubmissionRequirement struct { Name string Purpose string Rule Selection Count int Min int Max int Descriptors []*MatchedInputDescriptor Nested []*MatchedSubmissionRequirement }
MatchedSubmissionRequirement contains information about VCs that matched a presentation definition.
type PresentationDefinition ¶
type PresentationDefinition struct { // ID unique resource identifier. ID string `json:"id,omitempty"` // Name human-friendly name that describes what the Presentation Definition pertains to. Name string `json:"name,omitempty"` // Purpose describes the purpose for which the Presentation Definition’s inputs are being requested. Purpose string `json:"purpose,omitempty"` Locale string `json:"locale,omitempty"` // Format is an object with one or more properties matching the registered Claim Format Designations // (jwt, jwt_vc, jwt_vp, etc.) to inform the Holder of the claim format configurations the Verifier can process. Format *Format `json:"format,omitempty"` // Frame is used for JSON-LD document framing. Frame map[string]interface{} `json:"frame,omitempty"` // SubmissionRequirements must conform to the Submission Requirement Format. // If not present, all inputs listed in the InputDescriptors array are required for submission. SubmissionRequirements []*SubmissionRequirement `json:"submission_requirements,omitempty"` InputDescriptors []*InputDescriptor `json:"input_descriptors,omitempty"` }
PresentationDefinition presentation definitions (https://identity.foundation/presentation-exchange/).
func (*PresentationDefinition) CreateVP ¶
func (pd *PresentationDefinition) CreateVP(credentials []*verifiable.Credential, documentLoader ld.DocumentLoader, opts ...MatchRequirementsOpt) (*verifiable.Presentation, error)
CreateVP creates verifiable presentation.
Example (LimitedDisclosureSkipsNonSDVCs) ¶
nolint:gocyclo
required := Required pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Purpose: "To provide mauve alerts, we need to verify your authorization to receive mauve alert warnings.", InputDescriptors: []*InputDescriptor{{ ID: "mauve_alert", Purpose: "You are authorized to receive warnings for mauve alerts.", Constraints: &Constraints{ LimitDisclosure: &required, Fields: []*Field{ { Path: []string{"$.credentialSubject.warn_alert", "$.vc.credentialSubject.warn_alert", "$.warn_alert"}, // Predicate: &required, Filter: &Filter{ Type: &strFilterType, Const: "mauve", }, }, }, }, }}, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } makeVC := func(id string) *verifiable.Credential { vc, makeErr := verifiable.CreateCredential(verifiable.CredentialContents{ ID: id, Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Schemas: []verifiable.TypedID{{ ID: "hub://did:foo:123/Collections/schema.us.gov/passport.json", Type: "JsonSchemaValidator2018", }}, Subject: parseSubject(map[string]interface{}{ "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", "first_name": "Jesse", "last_name": "Pinkman", "warn_alert": "mauve", }), }, nil) if makeErr != nil { panic(fmt.Errorf("make vc :%w", makeErr)) } return vc } proofCreators, _, err := testsupport.NewKMSSignersAndVerifierErr([]*testsupport.SigningKey{ {Type: kms.ECDSAP256TypeIEEEP1363, PublicKeyID: "#key-1"}, }) if err != nil { panic(err) } jwtSrc := makeVC("http://example.edu/credentials/888") claims, err := jwtSrc.JWTClaims(false) if err != nil { panic(err) } credJWT, err := claims.MarshalJWSString(verifiable.ECDSASecp256r1, proofCreators[0], "#key-1") if err != nil { panic(err) } jwtVC, err := verifiable.ParseCredential([]byte(credJWT), verifiable.WithDisabledProofCheck()) if err != nil { panic(err) } sdJWTSrc := makeVC("http://example.edu/credentials/999") joseSig, err := jwt.NewJOSESigner(jwt.SignParameters{ KeyID: "#key-1", JWTAlg: "ES256", }, proofCreators[0]) if err != nil { panic(err) } marshaledSDJWTVC, err := sdJWTSrc.MarshalWithDisclosure(verifiable.DiscloseAll(), verifiable.DisclosureSigner(joseSig, "#key-1")) if err != nil { panic(err) } sdJWTVC, err := verifiable.ParseCredential([]byte(marshaledSDJWTVC), verifiable.WithDisabledProofCheck()) if err != nil { panic(err) } vp, err := pd.CreateVP([]*verifiable.Credential{ jwtVC, sdJWTVC, makeVC("http://example.edu/credentials/777"), }, loader, WithSDCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy presentedVC := vp.Credentials()[0] vcBytes, err := json.MarshalIndent(presentedVC.ToRawJSON(), "", "\t") if err != nil { panic(err) } vcStr := string(vcBytes) for _, sd := range presentedVC.Contents().Subject[0].CustomFields["_sd"].([]interface{}) { vcStr = strings.ReplaceAll(vcStr, sd.(string), "DUMMY") } vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } presentedJWT, err := presentedVC.ToJWTString() if err != nil { panic(err) } vpStr := strings.ReplaceAll(string(vpBytes), presentedJWT, "DUMMY") fmt.Println(vpStr) fmt.Println(vcStr) fmt.Println(prettifyDisclosures(presentedVC.SDJWTDisclosures()))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "mauve_alert", "format": "ldp_vp", "path": "$", "path_nested": { "id": "mauve_alert", "format": "jwt_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ "DUMMY" ] } { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "_sd_alg": "sha-256", "credentialSchema": { "id": "hub://did:foo:123/Collections/schema.us.gov/passport.json", "type": "JsonSchemaValidator2018" }, "credentialSubject": { "_sd": [ "DUMMY", "DUMMY", "DUMMY" ], "id": "did:example:ebfeb1f712ebc6f1c276e12ec21" }, "id": "http://example.edu/credentials/999", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ('warn_alert': mauve)
Example (MultipleMatches) ¶
pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Purpose: "To sell you a drink we need to know that you are an adult.", InputDescriptors: []*InputDescriptor{{ ID: "age_descriptor", Purpose: "Your age should be greater or equal to 18.", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ Fields: []*Field{{ Path: []string{"$.age"}, Filter: &Filter{ Type: &intFilterType, Minimum: 18, }, }}, }, }, { ID: "first_name_descriptor", Purpose: "First name must be either Andrew or Jesse", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ Fields: []*Field{{ Path: []string{"$.first_name"}, Filter: &Filter{ Type: &strFilterType, Pattern: "Andrew|Jesse", }, }}, }, }}, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } vp, err := pd.CreateVP(createExampleCredentials([]credentialProto{ { ID: "http://example.edu/credentials/777", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:777", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ID: "did:example:777"}}, CustomFields: map[string]interface{}{ "first_name": "Andrew", "last_name": "Hanks", "age": 25, }, }, { ID: "http://example.edu/credentials/888", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:888", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ID: "did:example:888"}}, CustomFields: map[string]interface{}{ "first_name": "Jesse", "last_name": "Pinkman", "age": 21, }, }, }), loader, WithSDCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } }, { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[1]" } }, { "id": "first_name_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "first_name_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } }, { "id": "first_name_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "first_name_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[1]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 25, "credentialSubject": { "id": "did:example:777" }, "first_name": "Andrew", "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:777", "last_name": "Hanks", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 21, "credentialSubject": { "id": "did:example:888" }, "first_name": "Jesse", "id": "http://example.edu/credentials/888", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:888", "last_name": "Pinkman", "type": "VerifiableCredential" } ] }
Example (MultipleMatchesDisclosure) ¶
required := Required pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Purpose: "To sell you a drink we need to know that you are an adult.", InputDescriptors: []*InputDescriptor{{ ID: "age_descriptor", Purpose: "Your age should be greater or equal to 18.", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ Fields: []*Field{{ Path: []string{"$.age"}, Filter: &Filter{ Type: &intFilterType, Minimum: 18, }, }}, }, }, { ID: "first_name_descriptor", Purpose: "First name must be either Andrew or Jesse", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ LimitDisclosure: &required, Fields: []*Field{{ Path: []string{"$.first_name"}, Filter: &Filter{ Type: &strFilterType, Pattern: "Andrew|Jesse", }, }}, }, }}, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } vp, err := pd.CreateVP(createExampleCredentials([]credentialProto{ { ID: "http://example.edu/credentials/777", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:777", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ID: "did:example:777"}}, CustomFields: map[string]interface{}{ "first_name": "Andrew", "last_name": "Hanks", "age": 25, }, }, { ID: "http://example.edu/credentials/888", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:888", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ID: "did:example:888"}}, CustomFields: map[string]interface{}{ "first_name": "Jesse", "last_name": "Pinkman", "age": 21, }, }, }), loader, WithSDCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } }, { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[1]" } }, { "id": "first_name_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "first_name_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[2]" } }, { "id": "first_name_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "first_name_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[3]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 25, "credentialSubject": { "id": "did:example:777" }, "first_name": "Andrew", "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:777", "last_name": "Hanks", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 21, "credentialSubject": { "id": "did:example:888" }, "first_name": "Jesse", "id": "http://example.edu/credentials/888", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:888", "last_name": "Pinkman", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": "did:example:777", "first_name": "Andrew", "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:777", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": "did:example:888", "first_name": "Jesse", "id": "http://example.edu/credentials/888", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:888", "type": "VerifiableCredential" } ] }
Example (SubmissionRequirements) ¶
pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Purpose: "To sell you a drink we need to know that you are an adult.", SubmissionRequirements: []*SubmissionRequirement{ // { // Rule: "all", // FromNested: []*SubmissionRequirement{ { Rule: "all", From: "A", }, { Rule: "pick", Purpose: "We need your photo to identify you.", Count: 1, FromNested: []*SubmissionRequirement{ { Rule: "all", From: "drivers_license_image", }, { Rule: "all", From: "passport_image", }, }, }, // }, // }, }, InputDescriptors: []*InputDescriptor{{ ID: "age_descriptor", Group: []string{"A"}, Purpose: "Your age should be greater or equal to 18.", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ Fields: []*Field{{ Path: []string{"$.age"}, Filter: &Filter{ Type: &intFilterType, Minimum: 18, }, }}, }, }, { ID: "drivers_license_image_descriptor", Group: []string{"drivers_license_image"}, Purpose: "We need your photo to identify you", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ Fields: []*Field{{ Path: []string{"$.photo"}, Filter: &Filter{ Type: &strFilterType, Format: "uri", }, }}, }, }, { ID: "passport_image_descriptor", Group: []string{"passport_image"}, Purpose: "We need your image to identify you", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ Fields: []*Field{{ Path: []string{"$.image"}, Filter: &Filter{ Type: &strFilterType, Format: "uri", }, }}, }, }}, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } vp, err := pd.CreateVP(createExampleCredentials([]credentialProto{ { ID: "http://example.edu/credentials/777", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:777", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ID: "did:example:777"}}, CustomFields: map[string]interface{}{ "first_name": "Andrew", "last_name": "Hanks", "image": "http://image.com/user777", "age": 25, }, }, { ID: "http://example.edu/credentials/888", Context: []string{"https://www.w3.org/2018/credentials/v1"}, Types: []string{"VerifiableCredential"}, Issuer: &verifiable.Issuer{ ID: "did:example:888", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ID: "did:example:888"}}, CustomFields: map[string]interface{}{ "first_name": "Jesse", "last_name": "Pinkman", "photo": "http://image.com/user777", "age": 21, }, }, }), loader, WithSDCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } }, { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[1]" } }, { "id": "drivers_license_image_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "drivers_license_image_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[1]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 25, "credentialSubject": { "id": "did:example:777" }, "first_name": "Andrew", "id": "http://example.edu/credentials/777", "image": "http://image.com/user777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:777", "last_name": "Hanks", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 21, "credentialSubject": { "id": "did:example:888" }, "first_name": "Jesse", "id": "http://example.edu/credentials/888", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:888", "last_name": "Pinkman", "photo": "http://image.com/user777", "type": "VerifiableCredential" } ] }
Example (SubmissionRequirements2) ¶
// TODO: this example demonstrates a bug, need to investigate // - create a unit test that simplifies this for investigation // - describe the issue for Rolson pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Purpose: "The following accreditations and clearances are required to proceed with your application.", SubmissionRequirements: []*SubmissionRequirement{ { Rule: "pick", Purpose: "We need a photo from government ID for your badge.", Count: 1, FromNested: []*SubmissionRequirement{ { Rule: "all", From: "drivers_license_image", }, { Rule: "all", From: "passport_image", }, }, }, { Rule: "all", Purpose: "We need to validate your flight experience.", FromNested: []*SubmissionRequirement{ { Rule: "pick", Count: 1, From: "flight_training", }, { Rule: "pick", Min: 1, From: "pilot_employment", }, }, }, }, InputDescriptors: []*InputDescriptor{ { ID: "drivers_license_image_descriptor", Group: []string{"drivers_license_image"}, Purpose: "We need your photo to identify you", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ Fields: []*Field{{ Path: []string{"$.photo"}, Filter: &Filter{ Type: &strFilterType, Format: "uri", }, }}, }, }, { ID: "passport_image_descriptor", Group: []string{"passport_image"}, Purpose: "We need your photo to identify you", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ Fields: []*Field{{ Path: []string{"$.image"}, Filter: &Filter{ Type: &strFilterType, Format: "uri", }, }}, }, }, { ID: "flight_training_1", Group: []string{"flight_training"}, Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ Fields: []*Field{{ Path: []string{"$.credentialSubject.pilot_id"}, Filter: &Filter{ Type: &strFilterType, }, }, { Path: []string{"$.credentialSubject.expiry"}, Filter: &Filter{ Type: &strFilterType, }, }}, }, }, { ID: "employment_private_1", Group: []string{"pilot_employment"}, Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ Fields: []*Field{{ Path: []string{"$.credentialSubject.pilot_id"}, Filter: &Filter{ Type: &strFilterType, }, }, { Path: []string{"$.credentialSubject.employed_since"}, Filter: &Filter{ Type: &strFilterType, }, }}, }, }, { ID: "employment_gov", Group: []string{"pilot_employment"}, Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ Fields: []*Field{{ Path: []string{"$.credentialSubject.clearance_level"}, Filter: &Filter{ Type: &arrFilterType, }, }, { Path: []string{"$.credentialSubject.travel_authorization.subnational"}, Filter: &Filter{ Type: &strFilterType, Const: "Allow", }, }}, }, }, }, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } vp, err := pd.CreateVP(createExampleCredentials([]credentialProto{ { ID: "http://example.dmv/credentials/777", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:777", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ID: "did:example:777"}}, CustomFields: map[string]interface{}{ "first_name": "Andrew", "last_name": "Hanks", "photo": "https://image.com/user777", "DOB": "5/18/86", }, }, { ID: "https://example.gov/credentials/888", Context: []string{"https://www.w3.org/2018/credentials/v1"}, Types: []string{"VerifiableCredential", "GovSecureEmployeeCredential"}, Issuer: &verifiable.Issuer{ ID: "did:example:888", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ ID: "did:example:888", CustomFields: map[string]interface{}{ "clearance_level": []string{"Public", "Low-Security", "Facility-Supervised"}, "employee_id": "2956348576547", "travel_authorization": map[string]interface{}{ "subnational": "Allow", "international_default": "S2-Signoff", }, }, }}, }, { ID: "https://example.faa/credentials/123", Context: []string{"https://www.w3.org/2018/credentials/v1"}, Types: []string{"VerifiableCredential", "FlightCertificationCredential"}, Issuer: &verifiable.Issuer{ ID: "did:example:123", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ ID: "did:example:123", CustomFields: map[string]interface{}{ "pilot_id": "4358793", "accrediting_institution": "Nowheresville Community College", "licensed_vehicles": []string{"hang_glider", "kite", "Cessna 152"}, "expiry": "2027-12-30", }, }}, }, { ID: "https://example.business/credentials/employee/12345", Context: []string{"https://www.w3.org/2018/credentials/v1"}, Types: []string{"VerifiableCredential", "EmployeeCredential"}, Issuer: &verifiable.Issuer{ ID: "did:example:12345", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ ID: "did:example:12345", CustomFields: map[string]interface{}{ "employed_since": "2021-07-06", "employed_until": "2021-07-07", "role": "Management Consultant", "reference": "did:example:10101", "pilot_id": "4358793", }}, }, }, { ID: "https://example.co.website/credentials/employee/7", Context: []string{"https://www.w3.org/2018/credentials/v1"}, Types: []string{"VerifiableCredential", "EmployeeCredential"}, Issuer: &verifiable.Issuer{ ID: "did:example:7", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ ID: "did:example:7", CustomFields: map[string]interface{}{ "employed_since": "2017-01-01", "employed_until": "2021-08-09", "role": "Customer Relationships Manager", "employer": "Chucky Pilot's Bar & Grill", "pilot_points": 172, "pilot_id": "Bravo-7", }}, }, }, }), loader, WithSDCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "drivers_license_image_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "drivers_license_image_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } }, { "id": "employment_private_1", "format": "ldp_vp", "path": "$", "path_nested": { "id": "employment_private_1", "format": "ldp_vc", "path": "$.verifiableCredential[1]" } }, { "id": "employment_private_1", "format": "ldp_vp", "path": "$", "path_nested": { "id": "employment_private_1", "format": "ldp_vc", "path": "$.verifiableCredential[2]" } }, { "id": "flight_training_1", "format": "ldp_vp", "path": "$", "path_nested": { "id": "flight_training_1", "format": "ldp_vc", "path": "$.verifiableCredential[3]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "DOB": "5/18/86", "credentialSubject": { "id": "did:example:777" }, "first_name": "Andrew", "id": "http://example.dmv/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:777", "last_name": "Hanks", "photo": "https://image.com/user777", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": { "employed_since": "2021-07-06", "employed_until": "2021-07-07", "id": "did:example:12345", "pilot_id": "4358793", "reference": "did:example:10101", "role": "Management Consultant" }, "id": "https://example.business/credentials/employee/12345", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:12345", "type": [ "VerifiableCredential", "EmployeeCredential" ] }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": { "employed_since": "2017-01-01", "employed_until": "2021-08-09", "employer": "Chucky Pilot's Bar \u0026 Grill", "id": "did:example:7", "pilot_id": "Bravo-7", "pilot_points": 172, "role": "Customer Relationships Manager" }, "id": "https://example.co.website/credentials/employee/7", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:7", "type": [ "VerifiableCredential", "EmployeeCredential" ] }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": { "accrediting_institution": "Nowheresville Community College", "expiry": "2027-12-30", "id": "did:example:123", "licensed_vehicles": [ "hang_glider", "kite", "Cessna 152" ], "pilot_id": "4358793" }, "id": "https://example.faa/credentials/123", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:123", "type": [ "VerifiableCredential", "FlightCertificationCredential" ] } ] }
Example (SubmissionRequirementsLimitDisclosure) ¶
required := Required pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Purpose: "To sell you a drink we need to know that you are an adult.", SubmissionRequirements: []*SubmissionRequirement{ { Rule: "all", From: "A", }, { Rule: "pick", Purpose: "We need your photo to identify you", Count: 1, FromNested: []*SubmissionRequirement{ { Rule: "all", From: "drivers_license_image", }, { Rule: "all", From: "passport_image", }, }, }, }, InputDescriptors: []*InputDescriptor{{ ID: "age_descriptor", Group: []string{"A"}, Purpose: "Your age should be greater or equal to 18.", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ Fields: []*Field{{ Path: []string{"$.age"}, Filter: &Filter{ Type: &intFilterType, Minimum: 18, }, }}, }, }, { ID: "drivers_license_image_descriptor", Group: []string{"drivers_license_image"}, Purpose: "We need your photo to identify you", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ LimitDisclosure: &required, Fields: []*Field{{ Path: []string{"$.photo"}, Filter: &Filter{ Type: &strFilterType, Format: "uri", }, }}, }, }, { ID: "passport_image_descriptor", Group: []string{"passport_image"}, Purpose: "We need your image to identify you", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ LimitDisclosure: &required, Fields: []*Field{{ Path: []string{"$.image"}, Filter: &Filter{ Type: &strFilterType, Format: "uri", }, }}, }, }}, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } vp, err := pd.CreateVP(createExampleCredentials([]credentialProto{ { ID: "http://example.edu/credentials/777", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:777", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ID: "did:example:777"}}, CustomFields: map[string]interface{}{ "first_name": "Andrew", "last_name": "Hanks", "image": "http://image.com/user777", "age": 25, }, }, { ID: "http://example.edu/credentials/888", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:888", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ID: "did:example:888"}}, CustomFields: map[string]interface{}{ "first_name": "Jesse", "last_name": "Pinkman", "photo": "http://image.com/user777", "age": 21, }, }, }), loader, WithSDCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } //TODO: check why presentation some times serialize subjects as string, according to spec they should be objects fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } }, { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[1]" } }, { "id": "drivers_license_image_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "drivers_license_image_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[2]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 25, "credentialSubject": { "id": "did:example:777" }, "first_name": "Andrew", "id": "http://example.edu/credentials/777", "image": "http://image.com/user777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:777", "last_name": "Hanks", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 21, "credentialSubject": { "id": "did:example:888" }, "first_name": "Jesse", "id": "http://example.edu/credentials/888", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:888", "last_name": "Pinkman", "photo": "http://image.com/user777", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": "did:example:888", "id": "http://example.edu/credentials/888", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:888", "photo": "http://image.com/user777", "type": "VerifiableCredential" } ] }
Example (V1) ¶
required := Required pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Purpose: "To sell you a drink we need to know that you are an adult.", InputDescriptors: []*InputDescriptor{{ ID: "age_descriptor", Purpose: "Your age should be greater or equal to 18.", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ LimitDisclosure: &required, Fields: []*Field{{ Path: []string{"$.age"}, Predicate: &required, Filter: &Filter{ Type: &intFilterType, Minimum: 18, }, }}, }, }}, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } vp, err := pd.CreateVP(createExampleCredentials([]credentialProto{ { ID: "http://example.edu/credentials/777", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ID: "did:example:76e12ec712ebc6f1c221ebfeb1f"}}, CustomFields: map[string]interface{}{ "first_name": "Jesse", "last_name": "Pinkman", "age": 21, }, }, }), loader, WithSDCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": true, "credentialSubject": "did:example:76e12ec712ebc6f1c221ebfeb1f", "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
Example (V1_With_LDPVC_FormatAndProof) ¶
required := Required pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Purpose: "To sell you a drink we need to know that you are an adult.", InputDescriptors: []*InputDescriptor{{ ID: "age_descriptor", Purpose: "Your age should be greater or equal to 18.", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ LimitDisclosure: &required, Fields: []*Field{{ Path: []string{"$.age"}, Predicate: &required, Filter: &Filter{ Type: &intFilterType, Minimum: 18, }, }}, }, }}, Format: &Format{ LdpVC: &LdpType{ProofType: []string{"JsonWebSignature2020"}}, }, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } vp, err := pd.CreateVP(createExampleCredentials([]credentialProto{ { ID: "http://example.edu/credentials/777", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ID: "did:example:76e12ec712ebc6f1c221ebfeb1f"}}, CustomFields: map[string]interface{}{ "first_name": "Jesse", "last_name": "Pinkman", "age": 21, }, Proofs: []verifiable.Proof{{"type": "JsonWebSignature2020"}}, }, }), loader, WithSDCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vc", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": true, "credentialSubject": "did:example:76e12ec712ebc6f1c221ebfeb1f", "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
Example (V1_With_LDP_FormatAndProof) ¶
required := Required pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Purpose: "To sell you a drink we need to know that you are an adult.", InputDescriptors: []*InputDescriptor{{ ID: "age_descriptor", Purpose: "Your age should be greater or equal to 18.", Schema: []*Schema{{ URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType), }}, Constraints: &Constraints{ LimitDisclosure: &required, Fields: []*Field{{ Path: []string{"$.age"}, Predicate: &required, Filter: &Filter{ Type: &intFilterType, Minimum: 18, }, }}, }, }}, Format: &Format{ Ldp: &LdpType{ProofType: []string{"JsonWebSignature2020"}}, }, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } vp, err := pd.CreateVP(createExampleCredentials([]credentialProto{ { ID: "http://example.edu/credentials/777", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Subject: []verifiable.Subject{{ID: "did:example:76e12ec712ebc6f1c221ebfeb1f"}}, CustomFields: map[string]interface{}{ "first_name": "Jesse", "last_name": "Pinkman", "age": 21, }, Proofs: []verifiable.Proof{{"type": "JsonWebSignature2020"}}, }, }), loader, WithSDCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": true, "credentialSubject": "did:example:76e12ec712ebc6f1c221ebfeb1f", "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
Example (V2) ¶
required := Required pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Purpose: "To sell you a drink we need to know that you are an adult.", InputDescriptors: []*InputDescriptor{{ ID: "age_descriptor", Purpose: "Your age should be greater or equal to 18.", Constraints: &Constraints{ LimitDisclosure: &required, Fields: []*Field{ { Path: []string{"$.credentialSubject.age", "$.vc.credentialSubject.age", "$.age"}, Predicate: &required, Filter: &Filter{ Type: &intFilterType, Minimum: 18, }, }, { Path: []string{"$.credentialSchema[0].id", "$.credentialSchema.id", "$.vc.credentialSchema.id"}, Filter: &Filter{ Type: &strFilterType, Const: "hub://did:foo:123/Collections/schema.us.gov/passport.json", }, }, }, }, }}, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } vp, err := pd.CreateVP(createExampleCredentials([]credentialProto{ { ID: "http://example.edu/credentials/777", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Schemas: []verifiable.TypedID{{ ID: "hub://did:foo:123/Collections/schema.us.gov/passport.json", Type: "JsonSchemaValidator2018", }}, Subject: parseSubject(map[string]interface{}{ "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", "first_name": "Jesse", "last_name": "Pinkman", "age": 21, }), }, }), loader, WithSDCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": { "age": true, "id": "did:example:ebfeb1f712ebc6f1c276e12ec21" }, "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
Example (WithFormatInInputDescriptor) ¶
required := Required pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Purpose: "To sell you a drink we need to know that you are an adult.", InputDescriptors: []*InputDescriptor{{ ID: "age_descriptor", Purpose: "Your age should be greater or equal to 18.", Format: &Format{ LdpVP: &LdpType{ ProofType: []string{"Ed25519Signature2018"}, }, }, Constraints: &Constraints{ LimitDisclosure: &required, Fields: []*Field{ { Path: []string{"$.credentialSubject.age", "$.vc.credentialSubject.age", "$.age"}, Predicate: &required, Filter: &Filter{ Type: &intFilterType, Minimum: 18, }, }, { Path: []string{"$.credentialSchema[0].id", "$.credentialSchema.id", "$.vc.credentialSchema.id"}, Filter: &Filter{ Type: &strFilterType, Const: "hub://did:foo:123/Collections/schema.us.gov/passport.json", }, }, }, }, }}, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } vp, err := pd.CreateVP(createExampleCredentials([]credentialProto{ { ID: "http://example.edu/credentials/777", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Schemas: []verifiable.TypedID{{ ID: "hub://did:foo:123/Collections/schema.us.gov/passport.json", Type: "JsonSchemaValidator2018", }}, Subject: parseSubject(map[string]interface{}{ "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", "first_name": "Jesse", "last_name": "Pinkman", "age": 21, }), Proofs: []verifiable.Proof{ {"type": "Ed25519Signature2018"}, }, }, }), loader, WithSDCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": { "age": true, "id": "did:example:ebfeb1f712ebc6f1c276e12ec21" }, "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
Example (WithFrame) ¶
vcJSON := ` { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://w3id.org/citizenship/v1", "https://w3id.org/security/bbs/v1" ], "id": "https://issuer.oidp.uscis.gov/credentials/83627465", "type": [ "VerifiableCredential", "PermanentResidentCard" ], "issuer": "did:example:489398593", "identifier": "83627465", "name": "Permanent Resident Card", "description": "Government of Example Permanent Resident Card.", "issuanceDate": "2019-12-03T12:19:52Z", "expirationDate": "2029-12-03T12:19:52Z", "credentialSubject": { "id": "did:example:b34ca6cd37bbf23", "type": [ "PermanentResident", "Person" ], "givenName": "JOHN", "familyName": "SMITH", "gender": "Male", "image": "data:image/png;base64,iVBORw0KGgokJggg==", "residentSince": "2015-01-01", "lprCategory": "C09", "lprNumber": "999-999-999", "commuterClassification": "C1", "birthCountry": "Bahamas", "birthDate": "1958-07-17" } } ` frameJSONWithMissingIssuer := ` { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://w3id.org/citizenship/v1", "https://w3id.org/security/bbs/v1" ], "type": ["VerifiableCredential", "PermanentResidentCard"], "@explicit": true, "identifier": {}, "issuer": {}, "issuanceDate": {}, "credentialSubject": { "@explicit": true, "type": ["PermanentResident", "Person"], "givenName": {}, "familyName": {}, "gender": {}, "birthCountry": {} } } ` frameDoc, err := jsonutil.ToMap(frameJSONWithMissingIssuer) if err != nil { panic(err) } required := Required pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Frame: frameDoc, InputDescriptors: []*InputDescriptor{{ ID: "country_descriptor", Constraints: &Constraints{ Fields: []*Field{ { Path: []string{"$.credentialSubject.birthCountry", "$.vc.credentialSubject.birthCountry"}, Predicate: &required, Filter: &Filter{ Type: &strFilterType, Const: "Bahamas", }, }, }, }, }}, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } vc, err := verifiable.ParseCredential([]byte(vcJSON), verifiable.WithDisabledProofCheck(), verifiable.WithJSONLDDocumentLoader(loader)) if err != nil { panic(err) } pubKey, privKey, err := bbs12381g2pub.GenerateKeyPair(sha256.New, nil) if err != nil { panic(err) } pubKeyBytes, err := pubKey.Marshal() if err != nil { panic(err) } signVCWithBBS(privKey, vc, loader) bbsProofCreator := &verifiable.BBSProofCreator{ ProofDerivation: bbs12381g2pub.New(), VerificationMethodResolver: testsupport.NewSingleKeyResolver("did:example:123456#key1", pubKeyBytes, "Bls12381G2Key2020", ""), } vp, err := pd.CreateVP([]*verifiable.Credential{vc}, loader, WithSDBBSProofCreator(bbsProofCreator), WithSDCredentialOptions( verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy vp.Credentials()[0].Proofs()[0]["created"] = dummy vp.Credentials()[0].Proofs()[0]["proofValue"] = dummy vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "country_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "country_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://w3id.org/citizenship/v1", "https://w3id.org/security/bbs/v1" ], "credentialSubject": { "birthCountry": true, "familyName": "SMITH", "gender": "Male", "givenName": "JOHN", "id": "did:example:b34ca6cd37bbf23", "type": [ "Person", "PermanentResident" ] }, "id": "https://issuer.oidp.uscis.gov/credentials/83627465", "identifier": "83627465", "issuanceDate": "2019-12-03T12:19:52Z", "issuer": "did:example:489398593", "proof": { "created": "DUMMY", "nonce": "", "proofPurpose": "assertionMethod", "proofValue": "DUMMY", "type": "BbsBlsSignatureProof2020", "verificationMethod": "did:example:123456#key1" }, "type": [ "PermanentResidentCard", "VerifiableCredential" ] } ] }
Example (With_LdpVC_Format) ¶
required := Required pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Purpose: "To sell you a drink we need to know that you are an adult.", Format: &Format{ LdpVC: &LdpType{ ProofType: []string{"Ed25519Signature2018"}, }, }, InputDescriptors: []*InputDescriptor{{ ID: "age_descriptor", Purpose: "Your age should be greater or equal to 18.", Constraints: &Constraints{ LimitDisclosure: &required, Fields: []*Field{ { Path: []string{"$.credentialSubject.age", "$.vc.credentialSubject.age", "$.age"}, Predicate: &required, Filter: &Filter{ Type: &intFilterType, Minimum: 18, }, }, { Path: []string{"$.credentialSchema[0].id", "$.credentialSchema.id", "$.vc.credentialSchema.id"}, Filter: &Filter{ Type: &strFilterType, Const: "hub://did:foo:123/Collections/schema.us.gov/passport.json", }, }, }, }, }}, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } vp, err := pd.CreateVP(createExampleCredentials([]credentialProto{ { ID: "http://example.edu/credentials/777", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Schemas: []verifiable.TypedID{{ ID: "hub://did:foo:123/Collections/schema.us.gov/passport.json", Type: "JsonSchemaValidator2018", }}, Subject: parseSubject(map[string]interface{}{ "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", "first_name": "Jesse", "last_name": "Pinkman", "age": 21, }), Proofs: []verifiable.Proof{ {"type": "Ed25519Signature2018"}, }, }, }), loader, WithSDCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vc", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": { "age": true, "id": "did:example:ebfeb1f712ebc6f1c276e12ec21" }, "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
Example (With_Ldp_Format) ¶
required := Required pd := &PresentationDefinition{ ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd", Purpose: "To sell you a drink we need to know that you are an adult.", Format: &Format{ Ldp: &LdpType{ ProofType: []string{"Ed25519Signature2018"}, }, }, InputDescriptors: []*InputDescriptor{{ ID: "age_descriptor", Purpose: "Your age should be greater or equal to 18.", Constraints: &Constraints{ LimitDisclosure: &required, Fields: []*Field{ { Path: []string{"$.credentialSubject.age", "$.vc.credentialSubject.age", "$.age"}, Predicate: &required, Filter: &Filter{ Type: &intFilterType, Minimum: 18, }, }, { Path: []string{"$.credentialSchema[0].id", "$.credentialSchema.id", "$.vc.credentialSchema.id"}, Filter: &Filter{ Type: &strFilterType, Const: "hub://did:foo:123/Collections/schema.us.gov/passport.json", }, }, }, }, }}, } loader, err := ldtestutil.DocumentLoader() if err != nil { panic(err) } vp, err := pd.CreateVP(createExampleCredentials([]credentialProto{ { ID: "http://example.edu/credentials/777", Context: []string{verifiable.ContextURI}, Types: []string{verifiable.VCType}, Issuer: &verifiable.Issuer{ ID: "did:example:76e12ec712ebc6f1c221ebfeb1f", }, Issued: &utiltime.TimeWrapper{ Time: time.Time{}, }, Schemas: []verifiable.TypedID{{ ID: "hub://did:foo:123/Collections/schema.us.gov/passport.json", Type: "JsonSchemaValidator2018", }}, Subject: parseSubject(map[string]interface{}{ "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", "first_name": "Jesse", "last_name": "Pinkman", "age": 21, }), Proofs: []verifiable.Proof{ {"type": "Ed25519Signature2018"}, }, }, }), loader, WithSDCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader))) if err != nil { panic(err) } vp.ID = dummy vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy vpBytes, err := json.MarshalIndent(vp, "", "\t") if err != nil { panic(err) } fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "id": "DUMMY", "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": { "age": true, "id": "did:example:ebfeb1f712ebc6f1c276e12ec21" }, "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
func (*PresentationDefinition) CreateVPArray ¶
func (pd *PresentationDefinition) CreateVPArray( credentials []*verifiable.Credential, documentLoader ld.DocumentLoader, opts ...MatchRequirementsOpt, ) ([]*verifiable.Presentation, *PresentationSubmission, error)
CreateVPArray creates a list of verifiable presentations, with one presentation for each provided credential. A PresentationSubmission is returned alongside, which uses the presentation list as the root for json paths.
func (*PresentationDefinition) Match ¶
func (pd *PresentationDefinition) Match(vpList []*verifiable.Presentation, contextLoader ld.DocumentLoader, options ...MatchOption) ([]*MatchValue, error)
Match returns the credentials matched against the InputDescriptors ids.
Example ¶
Example of a Verifier verifying the presentation submission of a Holder.
// verifier sends their presentation definitions to the holder verifierDefinitions := &PresentationDefinition{ InputDescriptors: []*InputDescriptor{ { ID: "banking", Schema: []*Schema{{ URI: "https://example.org/examples#Customer", }}, }, { ID: "residence", Schema: []*Schema{{ URI: "https://example.org/examples#Street", }}, }, }, } // holder fetches their credentials accountCredential := fetchVC([]string{"https://example.context.jsonld/account"}, []string{"Customer"}) addressCredential := fetchVC([]string{"https://example.context.jsonld/address"}, []string{"Street"}) // holder builds their presentation submission against the verifier's definitions vp, err := newPresentationSubmission( &PresentationSubmission{DescriptorMap: []*InputDescriptorMapping{ { ID: "banking", Path: "$.verifiableCredential[0]", }, { ID: "residence", Path: "$.verifiableCredential[1]", }, }}, accountCredential, addressCredential, ) if err != nil { panic(err) } // holder sends VP over the wire to the verifier vpBytes, err := json.Marshal(vp) if err != nil { panic(err) } // load json-ld context loader, err := ldtestutil.DocumentLoader( ldcontext.Document{ URL: "https://example.context.jsonld/account", Content: []byte(exampleJSONLDContext), }, ldcontext.Document{ URL: "https://example.context.jsonld/address", Content: []byte(exampleJSONLDContext), }, ) if err != nil { panic(err) } // verifier parses the vp // note: parsing this VP without verifying the proof just for example purposes. // Always verify proofs in production! receivedVP, err := verifiable.ParsePresentation(vpBytes, verifiable.WithPresDisabledProofCheck(), verifiable.WithPresJSONLDDocumentLoader(loader)) if err != nil { panic(err) } // verifier matches the received VP against their definitions matched, err := verifierDefinitions.Match( []*verifiable.Presentation{receivedVP}, loader, WithCredentialOptions( verifiable.WithDisabledProofCheck(), verifiable.WithJSONLDDocumentLoader(loader)), ) if err != nil { panic(fmt.Errorf("presentation submission did not match definitions: %w", err)) } for _, descriptor := range verifierDefinitions.InputDescriptors { for _, match := range matched { if match.DescriptorID == descriptor.ID { fmt.Printf( "verifier received the '%s' credential for the input descriptor id '%s'\n", match.Credential.Contents().Context[1], descriptor.ID) } } }
Output: verifier received the 'https://example.context.jsonld/account' credential for the input descriptor id 'banking' verifier received the 'https://example.context.jsonld/address' credential for the input descriptor id 'residence'
Example (Jwt_vp_path_workaround) ¶
// verifier sends their presentation definitions to the holder verifierDefinitions := &PresentationDefinition{ InputDescriptors: []*InputDescriptor{ { ID: "banking", Schema: []*Schema{{ URI: "https://example.org/examples#Customer", }}, }, }, } vc := fetchVC([]string{"https://example.context.jsonld/account"}, []string{"Customer"}) // holder builds their presentation submission against the verifier's definitions vp, err := newPresentationSubmission( &PresentationSubmission{DescriptorMap: []*InputDescriptorMapping{ { ID: "banking", Path: "$.verifiableCredential[0]", // use invalid path (missing .vp) to demonstrate the workaround }, }}, vc, ) if err != nil { panic(err) } claims, err := vp.JWTClaims([]string{""}, false) if err != nil { panic(err) } unsecuredJWT, err := claims.MarshalUnsecuredJWT() if err != nil { panic(err) } vp.JWT = unsecuredJWT // holder sends VP over the wire to the verifier vpBytes, err := json.Marshal(vp) if err != nil { panic(err) } // load json-ld context loader, err := ldtestutil.DocumentLoader( ldcontext.Document{ URL: "https://example.context.jsonld/account", Content: []byte(exampleJSONLDContext), }, ) if err != nil { panic(err) } receivedVP, err := verifiable.ParsePresentation(vpBytes, verifiable.WithPresDisabledProofCheck(), verifiable.WithPresJSONLDDocumentLoader(loader), ) if err != nil { panic(err) } // verifier matches the received VP against their definitions matched, err := verifierDefinitions.Match( []*verifiable.Presentation{receivedVP}, loader, WithCredentialOptions( verifiable.WithDisabledProofCheck(), verifiable.WithJSONLDDocumentLoader(loader)), ) if err != nil { panic(fmt.Errorf("presentation submission did not match definitions: %w", err)) } for _, descriptor := range verifierDefinitions.InputDescriptors { for _, match := range matched { if match.DescriptorID == descriptor.ID { fmt.Printf( "verifier received the '%s' credential for the input descriptor id '%s'\n", match.Credential.Contents().Context[1], descriptor.ID) } } }
Output: verifier received the 'https://example.context.jsonld/account' credential for the input descriptor id 'banking'
func (*PresentationDefinition) MatchSubmissionRequirement ¶
func (pd *PresentationDefinition) MatchSubmissionRequirement(credentials []*verifiable.Credential, documentLoader ld.DocumentLoader, opts ...MatchRequirementsOpt) ([]*MatchedSubmissionRequirement, error)
MatchSubmissionRequirement return information about matching VCs.
func (*PresentationDefinition) ValidateSchema ¶
func (pd *PresentationDefinition) ValidateSchema() error
ValidateSchema validates presentation definition.
type PresentationSubmission ¶
type PresentationSubmission struct { // ID unique resource identifier. ID string `json:"id,omitempty"` Locale string `json:"locale,omitempty"` // DefinitionID links the submission to its definition and must be the id value of a valid Presentation Definition. DefinitionID string `json:"definition_id,omitempty"` DescriptorMap []*InputDescriptorMapping `json:"descriptor_map"` }
PresentationSubmission is the container for the descriptor_map: https://identity.foundation/presentation-exchange/#presentation-submission.
type SubmissionRequirement ¶
type SubmissionRequirement struct { Name string `json:"name,omitempty"` Purpose string `json:"purpose,omitempty"` Rule Selection `json:"rule,omitempty"` Count int `json:"count,omitempty"` Min int `json:"min,omitempty"` Max int `json:"max,omitempty"` From string `json:"from,omitempty"` FromNested []*SubmissionRequirement `json:"from_nested,omitempty"` }
SubmissionRequirement describes input that must be submitted via a Presentation Submission to satisfy Verifier demands.