Documentation
¶
Overview ¶
Package issuer enables the Issuer: An entity that creates SD-JWTs.
An SD-JWT is a digitally signed document containing digests over the claims (per claim: a random salt, the claim name and the claim value). It MAY further contain clear-text claims that are always disclosed to the Verifier. It MUST be digitally signed using the Issuer's private key.
SD-JWT-DOC = (METADATA, SD-CLAIMS, NON-SD-CLAIMS) SD-JWT = SD-JWT-DOC | SIG(SD-JWT-DOC, ISSUER-PRIV-KEY)
SD-CLAIMS is an array of digest values that ensure the integrity of and map to the respective Disclosures. Digest values are calculated over the Disclosures, each of which contains the claim name (CLAIM-NAME), the claim value (CLAIM-VALUE), and a random salt (SALT). Digests are calculated using a hash function:
SD-CLAIMS = ( HASH(SALT, CLAIM-NAME, CLAIM-VALUE) )*
SD-CLAIMS can also be nested deeper to capture more complex objects.
The Issuer further creates a set of Disclosures for all claims in the SD-JWT. The Disclosures are sent to the Holder together with the SD-JWT:
DISCLOSURES = ( (SALT, CLAIM-NAME, CLAIM-VALUE) )*
The SD-JWT and the Disclosures are sent to the Holder by the Issuer:
COMBINED-ISSUANCE = SD-JWT | DISCLOSURES
Index ¶
- type Claims
- type NewOpt
- func WithAudience(audience string) NewOpt
- func WithDecoyDigests(flag bool) NewOpt
- func WithExpiry(expiry *jwt.NumericDate) NewOpt
- func WithHashAlgorithm(alg crypto.Hash) NewOpt
- func WithHolderPublicKey(jwk *jwk.JWK) NewOpt
- func WithID(id string) NewOpt
- func WithIssuedAt(issuedAt *jwt.NumericDate) NewOpt
- func WithJSONMarshaller(jsonMarshal func(v interface{}) ([]byte, error)) NewOpt
- func WithJTI(jti string) NewOpt
- func WithNonSelectivelyDisclosableClaims(nonSDClaims []string) NewOpt
- func WithNotBefore(notBefore *jwt.NumericDate) NewOpt
- func WithSaltFnc(fnc func() (string, error)) NewOpt
- func WithStructuredClaims(flag bool) NewOpt
- func WithSubject(subject string) NewOpt
- type SelectiveDisclosureJWT
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Claims ¶
Claims defines JSON Web Token Claims (https://tools.ietf.org/html/rfc7519#section-4)
type NewOpt ¶
type NewOpt func(opts *newOpts)
NewOpt is the SD-JWT New option.
func WithAudience ¶
WithAudience is an option for SD-JWT payload. This is a clear-text claim that is always disclosed.
func WithDecoyDigests ¶
WithDecoyDigests is an option for adding decoy digests(default is false).
func WithExpiry ¶
func WithExpiry(expiry *jwt.NumericDate) NewOpt
WithExpiry is an option for SD-JWT payload. This is a clear-text claim that is always disclosed.
func WithHashAlgorithm ¶
WithHashAlgorithm is an option for hashing disclosures.
func WithHolderPublicKey ¶
WithHolderPublicKey is an option for SD-JWT payload. The Holder can prove legitimate possession of an SD-JWT by proving control over the same private key during the issuance and presentation. An SD-JWT with Holder Binding contains a public key or a reference to a public key that matches to the private key controlled by the Holder. The "cnf" claim value MUST represent only a single proof-of-possession key. This implementation is using CNF "jwk".
func WithID ¶
WithID is an option for SD-JWT payload. This is a clear-text claim that is always disclosed.
func WithIssuedAt ¶
func WithIssuedAt(issuedAt *jwt.NumericDate) NewOpt
WithIssuedAt is an option for SD-JWT payload. This is a clear-text claim that is always disclosed.
func WithJSONMarshaller ¶
WithJSONMarshaller is option is for marshalling disclosure.
func WithJTI ¶
WithJTI is an option for SD-JWT payload. This is a clear-text claim that is always disclosed.
func WithNonSelectivelyDisclosableClaims ¶
WithNonSelectivelyDisclosableClaims is an option for provide claim names that should be ignored when creating selectively disclosable claims. For example if you would like to not selectively disclose id and degree type from the following claims: {
"degree": { "degree": "MIT", "type": "BachelorDegree", }, "name": "Jayden Doe", "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", }
you should specify the following array: []string{"id", "degree.type"}.
func WithNotBefore ¶
func WithNotBefore(notBefore *jwt.NumericDate) NewOpt
WithNotBefore is an option for SD-JWT payload. This is a clear-text claim that is always disclosed.
func WithSaltFnc ¶
WithSaltFnc is an option for generating salt. Mostly used for testing. A new salt MUST be chosen for each claim independently of other salts. The RECOMMENDED minimum length of the randomly-generated portion of the salt is 128 bits. It is RECOMMENDED to base64url-encode the salt value, producing a string.
func WithStructuredClaims ¶
WithStructuredClaims is an option for handling structured claims(default is false).
func WithSubject ¶
WithSubject is an option for SD-JWT payload. This is a clear-text claim that is always disclosed.
type SelectiveDisclosureJWT ¶
type SelectiveDisclosureJWT struct { SignedJWT *afgjwt.JSONWebToken Disclosures []string }
SelectiveDisclosureJWT defines Selective Disclosure JSON Web Token (https://tools.ietf.org/html/rfc7519)
func New ¶
func New(issuer string, claims interface{}, headers jose.Headers, signer jose.Signer, opts ...NewOpt) (*SelectiveDisclosureJWT, error)
New creates new signed Selective Disclosure JWT based on input claims. The Issuer MUST create a Disclosure for each selectively disclosable claim as follows: Create an array of three elements in this order:
A salt value. Generated by the system, the salt value MUST be unique for each claim that is to be selectively disclosed. The claim name, or key, as it would be used in a regular JWT body. This MUST be a string. The claim's value, as it would be used in a regular JWT body. The value MAY be of any type that is allowed in JSON, including numbers, strings, booleans, arrays, and objects.
Then JSON-encode the array such that an UTF-8 string is produced. Then base64url-encode the byte representation of the UTF-8 string to create the Disclosure.
Example ¶
package main import ( "crypto/ed25519" "crypto/rand" "encoding/json" "fmt" afjwt "github.com/hyperledger/aries-framework-go/pkg/doc/jwt" ) func main() { signer, _, err := setUp() if err != nil { fmt.Println("failed to set-up test: %w", err.Error()) } claims := map[string]interface{}{ "last_name": "Smith", "address": map[string]interface{}{ "street_address": "123 Main St", "country": "US", }, } // Issuer will issue SD-JWT for specified claims. Salt function is only provided to keep example outcome the same. token, err := New("https://example.com/issuer", claims, nil, signer, WithStructuredClaims(true), WithNonSelectivelyDisclosableClaims([]string{"address.country"}), WithSaltFnc(func() (string, error) { return sampleSalt, nil })) if err != nil { fmt.Println("failed to issue SD-JWT: %w", err.Error()) } var decoded map[string]interface{} err = token.DecodeClaims(&decoded) if err != nil { fmt.Println("failed to decode SD-JWT claims: %w", err.Error()) } issuerClaimsJSON, err := marshalObj(decoded) if err != nil { fmt.Println("verifier failed to marshal verified claims: %w", err.Error()) } fmt.Println(issuerClaimsJSON) } func setUp() (*afjwt.JoseED25519Signer, *afjwt.JoseEd25519Verifier, error) { issuerPublicKey, issuerPrivateKey, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, nil, err } signer := afjwt.NewEd25519Signer(issuerPrivateKey) signatureVerifier, err := afjwt.NewEd25519Verifier(issuerPublicKey) if err != nil { return nil, nil, err } return signer, signatureVerifier, nil } func marshalObj(obj interface{}) (string, error) { objBytes, err := json.Marshal(obj) if err != nil { fmt.Println("failed to marshal object: %w", err.Error()) } return prettyPrint(objBytes) }
Output: { "_sd": [ "V9-Eiizd3iJpdlxojQuwps44Zba7z6R08S7rPCDg_wU" ], "_sd_alg": "sha-256", "address": { "_sd": [ "tD1XVFffEo0KTGuvHn9UlXCBgt3vot5xAanqXMdvVMg" ], "country": "US" }, "iss": "https://example.com/issuer" }
func NewFromVC ¶
func NewFromVC(vc map[string]interface{}, headers jose.Headers, signer jose.Signer, opts ...NewOpt) (*SelectiveDisclosureJWT, error)
NewFromVC creates new signed Selective Disclosure JWT based on Verifiable Credential.
Algorithm:
- extract credential subject map from verifiable credential
- create un-signed SD-JWT plus Disclosures with credential subject map
- decode claims from SD-JWT to get credential subject map with selective disclosures
- replace VC credential subject with newly created credential subject with selective disclosures
- create signed SD-JWT based on VC
- return signed SD-JWT plus Disclosures
func (*SelectiveDisclosureJWT) DecodeClaims ¶
func (j *SelectiveDisclosureJWT) DecodeClaims(c interface{}) error
DecodeClaims fills input c with claims of a token.
func (*SelectiveDisclosureJWT) LookupStringHeader ¶
func (j *SelectiveDisclosureJWT) LookupStringHeader(name string) string
LookupStringHeader makes look up of particular header with string value.