Documentation ¶
Overview ¶
Package holder enables the Holder: an entity that receives SD-JWTs from the Issuer and has control over them.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CreateHolderBinding ¶
func CreateHolderBinding(info *BindingInfo) (string, error)
CreateHolderBinding will create holder binding from binding info.
func CreatePresentation ¶
func CreatePresentation(combinedFormatForIssuance string, claimsToDisclose []string, opts ...Option) (string, error)
CreatePresentation is a convenience method to assemble combined format for presentation using selected disclosures (claimsToDisclose) and optional holder binding. This call assumes that combinedFormatForIssuance has already been parsed and verified using Parse() function.
For presentation to a Verifier, the Holder MUST perform the following (or equivalent) steps:
- Decide which Disclosures to release to the Verifier, obtaining proper End-User consent if necessary.
- If Holder Binding is required, create a Holder Binding JWT.
- Create the Combined Format for Presentation from selected Disclosures and Holder Binding JWT(if applicable).
- Send the Presentation to the Verifier.
Example ¶
signer, signatureVerifier, err := setUp() if err != nil { fmt.Println("failed to set-up test: %w", err.Error()) } holderSigner, holderJWK, err := setUpHolderBinding() if err != nil { fmt.Println("failed to set-up test: %w", err.Error()) } claims := map[string]interface{}{ "given_name": "Albert", "last_name": "Smith", } // Issuer will issue SD-JWT for specified claims and holder public key. token, err := issuer.New(testIssuer, claims, nil, signer, issuer.WithHolderPublicKey(holderJWK)) if err != nil { fmt.Println("failed to issue SD-JWT: %w", err.Error()) } combinedFormatForIssuance, err := token.Serialize(false) if err != nil { fmt.Println("failed to issue SD-JWT: %w", err.Error()) } // Holder will parse combined format for issuance and hold on to that // combined format for issuance and the claims that can be selected. holderClaims, err := Parse(combinedFormatForIssuance, WithSignatureVerifier(signatureVerifier)) if err != nil { fmt.Println("holder failed to parse SD-JWT: %w", err.Error()) } // The Holder will only select given_name selectedDisclosures := getDisclosuresFromClaimNames([]string{"given_name"}, holderClaims) // Holder will disclose only sub-set of claims to verifier and create holder binding for the verifier. combinedFormatForPresentation, err := CreatePresentation(combinedFormatForIssuance, selectedDisclosures, WithHolderBinding(&BindingInfo{ Payload: BindingPayload{ Nonce: "nonce", Audience: "https://test.com/verifier", IssuedAt: jwt.NewNumericDate(time.Now()), }, Signer: holderSigner, })) if err != nil { fmt.Println("holder failed to create presentation: %w", err.Error()) } cfp := common.ParseCombinedFormatForPresentation(combinedFormatForPresentation) fmt.Println(cfp.HolderBinding != "")
Output: true
Types ¶
type BindingInfo ¶
type BindingInfo struct { Payload BindingPayload Signer jose.Signer }
BindingInfo defines holder binding payload and signer.
type BindingPayload ¶
type BindingPayload struct { Nonce string `json:"nonce,omitempty"` Audience string `json:"aud,omitempty"` IssuedAt *jwt.NumericDate `json:"iat,omitempty"` }
BindingPayload represents holder binding payload.
type Claim ¶
Claim defines claim.
func Parse ¶
Parse parses issuer SD-JWT and returns claims that can be selected. The Holder MUST perform the following (or equivalent) steps when receiving a Combined Format for Issuance:
Separate the SD-JWT and the Disclosures in the Combined Format for Issuance.
Hash all the Disclosures separately.
Find the places in the SD-JWT where the digests of the Disclosures are included.
If any of the digests cannot be found in the SD-JWT, the Holder MUST reject the SD-JWT.
Decode Disclosures and obtain plaintext of the claim values.
It is up to the Holder how to maintain the mapping between the Disclosures and the plaintext claim values to be able to display them to the End-User when needed.
Example ¶
signer, signatureVerifier, err := setUp() if err != nil { fmt.Println("failed to set-up test: %w", err.Error()) } claims := map[string]interface{}{ "given_name": "Albert", "last_name": "Smith", } // Issuer will issue SD-JWT for specified claims. Salt function is only provided to keep example outcome the same. token, err := issuer.New(testIssuer, claims, nil, signer, issuer.WithSaltFnc(func() (string, error) { return "3jqcb67z9wks08zwiK7EyQ", nil })) if err != nil { fmt.Println("failed to issue SD-JWT: %w", err.Error()) } combinedFormatForIssuance, err := token.Serialize(false) if err != nil { fmt.Println("failed to issue SD-JWT: %w", err.Error()) } // Holder will parse combined format for issuance and hold on to that // combined format for issuance and the claims that can be selected. holderClaims, err := Parse(combinedFormatForIssuance, WithSignatureVerifier(signatureVerifier)) if err != nil { fmt.Println("holder failed to parse SD-JWT: %w", err.Error()) } // Sort by claim name, keeping original order or equal elements. sort.SliceStable(holderClaims, func(i, j int) bool { return holderClaims[i].Name < holderClaims[j].Name }) holderClaimsJSON, err := marshalObj(holderClaims) if err != nil { fmt.Println("verifier failed to marshal holder claims: %w", err.Error()) } fmt.Println(holderClaimsJSON)
Output: [ { "Disclosure": "WyIzanFjYjY3ejl3a3MwOHp3aUs3RXlRIiwiZ2l2ZW5fbmFtZSIsIkFsYmVydCJd", "Name": "given_name", "Value": "Albert" }, { "Disclosure": "WyIzanFjYjY3ejl3a3MwOHp3aUs3RXlRIiwibGFzdF9uYW1lIiwiU21pdGgiXQ", "Name": "last_name", "Value": "Smith" } ]
type NoopSignatureVerifier ¶
type NoopSignatureVerifier struct { }
NoopSignatureVerifier is no-op signature verifier (signature will not get checked).
type Option ¶
type Option func(opts *options)
Option is a holder option.
func WithHolderBinding ¶
func WithHolderBinding(info *BindingInfo) Option
WithHolderBinding option to set optional holder binding.
type ParseOpt ¶
type ParseOpt func(opts *parseOpts)
ParseOpt is the SD-JWT Parser option.
func WithJWTDetachedPayload ¶
WithJWTDetachedPayload option is for definition of JWT detached payload.
func WithSignatureVerifier ¶
func WithSignatureVerifier(signatureVerifier jose.SignatureVerifier) ParseOpt
WithSignatureVerifier option is for definition of JWT detached payload.