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

fix: Presentation Without Holder Binding should end with ~ #3468

Merged
merged 1 commit into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 61 additions & 9 deletions pkg/doc/sdjwt/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,43 @@ type Payload struct {
SDAlg string `json:"_sd_alg,omitempty"`
}

// SDJWT holds SD-JWT info.
type SDJWT struct {
JWTSerialized string
// CombinedFormatForIssuance holds SD-JWT and disclosures.
type CombinedFormatForIssuance struct {
SDJWT string
Disclosures []string
}

// Serialize will assemble combined format for issuance.
func (cf *CombinedFormatForIssuance) Serialize() string {
presentation := cf.SDJWT
for _, disclosure := range cf.Disclosures {
presentation += DisclosureSeparator + disclosure
}

return presentation
}

// CombinedFormatForPresentation holds SD-JWT, disclosures and optional holder binding info.
type CombinedFormatForPresentation struct {
SDJWT string
Disclosures []string
HolderBinding string
}

// Serialize will assemble combined format for presentation.
func (cf *CombinedFormatForPresentation) Serialize() string {
presentation := cf.SDJWT
for _, disclosure := range cf.Disclosures {
presentation += DisclosureSeparator + disclosure
}

if len(cf.Disclosures) > 0 || cf.HolderBinding != "" {
presentation += DisclosureSeparator
}

presentation += cf.HolderBinding

return presentation
}

// DisclosureClaim defines claim.
Expand Down Expand Up @@ -107,18 +140,37 @@ func getDisclosureClaim(disclosure string) (*DisclosureClaim, error) {
return claim, nil
}

// ParseSDJWT parses SD-JWT serialized token into SDJWT parts.
func ParseSDJWT(sdJWTSerialized string) *SDJWT {
parts := strings.Split(sdJWTSerialized, DisclosureSeparator)
// ParseCombinedFormatForIssuance parses combined format for issuance into CombinedFormatForIssuance parts.
func ParseCombinedFormatForIssuance(combinedFormatForIssuance string) *CombinedFormatForIssuance {
parts := strings.Split(combinedFormatForIssuance, DisclosureSeparator)

var disclosures []string
if len(parts) > 1 {
disclosures = parts[1:]
}

jwtSerialized := parts[0]
sdJWT := parts[0]

return &CombinedFormatForIssuance{SDJWT: sdJWT, Disclosures: disclosures}
}

// ParseCombinedFormatForPresentation parses combined format for presentation into CombinedFormatForPresentation parts.
func ParseCombinedFormatForPresentation(combinedFormatForPresentation string) *CombinedFormatForPresentation {
parts := strings.Split(combinedFormatForPresentation, DisclosureSeparator)

var disclosures []string
if len(parts) > 2 {
disclosures = parts[1 : len(parts)-1]
}

var holderBinding string
if len(parts) > 1 {
holderBinding = parts[len(parts)-1]
}

sdJWT := parts[0]

return &SDJWT{JWTSerialized: jwtSerialized, Disclosures: disclosures}
return &CombinedFormatForPresentation{SDJWT: sdJWT, Disclosures: disclosures, HolderBinding: holderBinding}
}

// GetHash calculates hash of data using hash function identified by hash.
Expand Down Expand Up @@ -207,7 +259,7 @@ func getSDAlg(claims map[string]interface{}) (string, error) {
return str, nil
}

// GetDisclosureDigests returns digests from from claims map.
// GetDisclosureDigests returns digests from claims map.
func GetDisclosureDigests(claims map[string]interface{}) (map[string]bool, error) {
disclosuresObj, ok := claims[SDKey]
if !ok {
Expand Down
102 changes: 85 additions & 17 deletions pkg/doc/sdjwt/common/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,79 @@ func TestGetHash(t *testing.T) {
})
}

func TestParseSDJWT(t *testing.T) {
t.Run("success", func(t *testing.T) {
sdJWT := ParseSDJWT(sdJWT)
require.Equal(t, 1, len(sdJWT.Disclosures))
func TestParseCombinedFormatForIssuance(t *testing.T) {
t.Run("success - SD-JWT only", func(t *testing.T) {
cfi := ParseCombinedFormatForIssuance(testCombinedFormatForIssuance)
require.Equal(t, testSDJWT, cfi.SDJWT)
require.Equal(t, 1, len(cfi.Disclosures))

require.Equal(t, testCombinedFormatForIssuance, cfi.Serialize())
})
t.Run("success", func(t *testing.T) {
sdJWT := ParseSDJWT(specSDJWT)
require.Equal(t, 7, len(sdJWT.Disclosures))
t.Run("success - spec example", func(t *testing.T) {
cfi := ParseCombinedFormatForIssuance(specCombinedFormatForIssuance)
require.Equal(t, 7, len(cfi.Disclosures))

require.Equal(t, specCombinedFormatForIssuance, cfi.Serialize())
})
t.Run("success - AFG generated", func(t *testing.T) {
cfi := ParseCombinedFormatForIssuance(testSDJWT)
require.Equal(t, testSDJWT, cfi.SDJWT)
require.Equal(t, 0, len(cfi.Disclosures))

require.Equal(t, testSDJWT, cfi.Serialize())
})
}

func TestParseCombinedFormatForPresentation(t *testing.T) {
const testHolderBinding = "holder.binding.jwt"

testCombinedFormatForPresentation := testCombinedFormatForIssuance + DisclosureSeparator

t.Run("success - AFG example", func(t *testing.T) {
cfp := ParseCombinedFormatForPresentation(testCombinedFormatForPresentation)
require.Equal(t, testSDJWT, cfp.SDJWT)
require.Equal(t, 1, len(cfp.Disclosures))
require.Empty(t, cfp.HolderBinding)

require.Equal(t, testCombinedFormatForPresentation, cfp.Serialize())
})

t.Run("success - spec example", func(t *testing.T) {
cfp := ParseCombinedFormatForPresentation(specCombinedFormatForIssuance + DisclosureSeparator)
require.Equal(t, 7, len(cfp.Disclosures))
require.Empty(t, cfp.HolderBinding)

require.Equal(t, specCombinedFormatForIssuance+DisclosureSeparator, cfp.Serialize())
})

t.Run("success - AFG test with holder binding", func(t *testing.T) {
testCFI := testCombinedFormatForPresentation + testHolderBinding
cfp := ParseCombinedFormatForPresentation(testCFI)
require.Equal(t, testSDJWT, cfp.SDJWT)
require.Equal(t, 1, len(cfp.Disclosures))
require.Equal(t, testHolderBinding, cfp.HolderBinding)

require.Equal(t, testCFI, cfp.Serialize())
})

t.Run("success - SD-JWT only", func(t *testing.T) {
cfp := ParseCombinedFormatForPresentation(testSDJWT)
require.Equal(t, testSDJWT, cfp.SDJWT)
require.Equal(t, 0, len(cfp.Disclosures))
require.Empty(t, cfp.HolderBinding)

require.Equal(t, testSDJWT, cfp.Serialize())
})

t.Run("success - SD-JWT + holder binding", func(t *testing.T) {
testCFI := testSDJWT + DisclosureSeparator + testHolderBinding

cfp := ParseCombinedFormatForPresentation(testCFI)
require.Equal(t, testSDJWT, cfp.SDJWT)
require.Equal(t, 0, len(cfp.Disclosures))
require.Equal(t, testHolderBinding, cfp.HolderBinding)

require.Equal(t, testCFI, cfp.Serialize())
})
}

Expand All @@ -62,10 +127,10 @@ func TestVerifyDisclosuresInSDJWT(t *testing.T) {
signer := afjwt.NewEd25519Signer(privKey)

t.Run("success", func(t *testing.T) {
sdJWT := ParseSDJWT(sdJWT)
sdJWT := ParseCombinedFormatForIssuance(testCombinedFormatForIssuance)
require.Equal(t, 1, len(sdJWT.Disclosures))

signedJWT, err := afjwt.Parse(sdJWT.JWTSerialized, afjwt.WithSignatureVerifier(&NoopSignatureVerifier{}))
signedJWT, err := afjwt.Parse(sdJWT.SDJWT, afjwt.WithSignatureVerifier(&NoopSignatureVerifier{}))
require.NoError(t, err)

err = VerifyDisclosuresInSDJWT(sdJWT.Disclosures, signedJWT)
Expand Down Expand Up @@ -98,10 +163,10 @@ func TestVerifyDisclosuresInSDJWT(t *testing.T) {
})

t.Run("error - disclosure not present in SD-JWT", func(t *testing.T) {
sdJWT := ParseSDJWT(sdJWT)
sdJWT := ParseCombinedFormatForIssuance(testCombinedFormatForIssuance)
require.Equal(t, 1, len(sdJWT.Disclosures))

signedJWT, err := afjwt.Parse(sdJWT.JWTSerialized, afjwt.WithSignatureVerifier(&NoopSignatureVerifier{}))
signedJWT, err := afjwt.Parse(sdJWT.SDJWT, afjwt.WithSignatureVerifier(&NoopSignatureVerifier{}))
require.NoError(t, err)

err = VerifyDisclosuresInSDJWT(append(sdJWT.Disclosures, additionalDisclosure), signedJWT)
Expand Down Expand Up @@ -195,7 +260,7 @@ func TestGetDisclosureClaims(t *testing.T) {
r := require.New(t)

t.Run("success", func(t *testing.T) {
sdJWT := ParseSDJWT(sdJWT)
sdJWT := ParseCombinedFormatForIssuance(testCombinedFormatForIssuance)
require.Equal(t, 1, len(sdJWT.Disclosures))

disclosureClaims, err := GetDisclosureClaims(sdJWT.Disclosures)
Expand All @@ -207,7 +272,7 @@ func TestGetDisclosureClaims(t *testing.T) {
})

t.Run("error - invalid disclosure format (not encoded)", func(t *testing.T) {
sdJWT := ParseSDJWT("jws~xyz")
sdJWT := ParseCombinedFormatForIssuance("jws~xyz")
require.Equal(t, 1, len(sdJWT.Disclosures))

disclosureClaims, err := GetDisclosureClaims(sdJWT.Disclosures)
Expand All @@ -221,7 +286,7 @@ func TestGetDisclosureClaims(t *testing.T) {
disclosureJSON, err := json.Marshal(disclosureArr)
require.NoError(t, err)

sdJWT := ParseSDJWT(fmt.Sprintf("jws~%s", base64.RawURLEncoding.EncodeToString(disclosureJSON)))
sdJWT := ParseCombinedFormatForIssuance(fmt.Sprintf("jws~%s", base64.RawURLEncoding.EncodeToString(disclosureJSON)))
require.Equal(t, 1, len(sdJWT.Disclosures))

disclosureClaims, err := GetDisclosureClaims(sdJWT.Disclosures)
Expand All @@ -235,7 +300,7 @@ func TestGetDisclosureClaims(t *testing.T) {
disclosureJSON, err := json.Marshal(disclosureArr)
require.NoError(t, err)

sdJWT := ParseSDJWT(fmt.Sprintf("jws~%s", base64.RawURLEncoding.EncodeToString(disclosureJSON)))
sdJWT := ParseCombinedFormatForIssuance(fmt.Sprintf("jws~%s", base64.RawURLEncoding.EncodeToString(disclosureJSON)))
require.Equal(t, 1, len(sdJWT.Disclosures))

disclosureClaims, err := GetDisclosureClaims(sdJWT.Disclosures)
Expand All @@ -255,7 +320,10 @@ func (sv *NoopSignatureVerifier) Verify(joseHeaders jose.Headers, payload, signi
const additionalDisclosure = `WyJfMjZiYzRMVC1hYzZxMktJNmNCVzVlcyIsICJmYW1pbHlfbmFtZSIsICJNw7ZiaXVzIl0`

// nolint: lll
const sdJWT = `eyJhbGciOiJFZERTQSJ9.eyJfc2QiOlsicXF2Y3FuY3pBTWdZeDdFeWtJNnd3dHNweXZ5dks3OTBnZTdNQmJRLU51cyJdLCJfc2RfYWxnIjoic2hhLTI1NiIsImV4cCI6MTcwMzAyMzg1NSwiaWF0IjoxNjcxNDg3ODU1LCJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tL2lzc3VlciIsIm5iZiI6MTY3MTQ4Nzg1NX0.vscuzfwcHGi04pWtJCadc4iDELug6NH6YK-qxhY1qacsciIHuoLELAfon1tGamHtuu8TSs6OjtLk3lHE16jqAQ~WyIzanFjYjY3ejl3a3MwOHp3aUs3RXlRIiwgImdpdmVuX25hbWUiLCAiSm9obiJd`
const testCombinedFormatForIssuance = `eyJhbGciOiJFZERTQSJ9.eyJfc2QiOlsicXF2Y3FuY3pBTWdZeDdFeWtJNnd3dHNweXZ5dks3OTBnZTdNQmJRLU51cyJdLCJfc2RfYWxnIjoic2hhLTI1NiIsImV4cCI6MTcwMzAyMzg1NSwiaWF0IjoxNjcxNDg3ODU1LCJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tL2lzc3VlciIsIm5iZiI6MTY3MTQ4Nzg1NX0.vscuzfwcHGi04pWtJCadc4iDELug6NH6YK-qxhY1qacsciIHuoLELAfon1tGamHtuu8TSs6OjtLk3lHE16jqAQ~WyIzanFjYjY3ejl3a3MwOHp3aUs3RXlRIiwgImdpdmVuX25hbWUiLCAiSm9obiJd`

// nolint: lll
const testSDJWT = `eyJhbGciOiJFZERTQSJ9.eyJfc2QiOlsicXF2Y3FuY3pBTWdZeDdFeWtJNnd3dHNweXZ5dks3OTBnZTdNQmJRLU51cyJdLCJfc2RfYWxnIjoic2hhLTI1NiIsImV4cCI6MTcwMzAyMzg1NSwiaWF0IjoxNjcxNDg3ODU1LCJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tL2lzc3VlciIsIm5iZiI6MTY3MTQ4Nzg1NX0.vscuzfwcHGi04pWtJCadc4iDELug6NH6YK-qxhY1qacsciIHuoLELAfon1tGamHtuu8TSs6OjtLk3lHE16jqAQ`

// nolint: lll
const specSDJWT = `eyJhbGciOiAiUlMyNTYiLCAia2lkIjogImNBRUlVcUowY21MekQxa3pHemhlaUJhZzBZUkF6VmRsZnhOMjgwTmdIYUEifQ.eyJfc2QiOiBbIk5ZQ29TUktFWXdYZHBlNXlkdUpYQ3h4aHluRVU4ei1iNFR5TmlhcDc3VVkiLCAiU1k4bjJCYmtYOWxyWTNleEhsU3dQUkZYb0QwOUdGOGE5Q1BPLUc4ajIwOCIsICJUUHNHTlBZQTQ2d21CeGZ2MnpuT0poZmRvTjVZMUdrZXpicGFHWkNUMWFjIiwgIlprU0p4eGVHbHVJZFlCYjdDcWtaYkpWbTB3MlY1VXJSZU5UekFRQ1lCanciLCAibDlxSUo5SlRRd0xHN09MRUlDVEZCVnhtQXJ3OFBqeTY1ZEQ2bXRRVkc1YyIsICJvMVNBc0ozM1lNaW9POXBYNVZlQU0xbHh1SEY2aFpXMmtHZGtLS0JuVmxvIiwgInFxdmNxbmN6QU1nWXg3RXlrSTZ3d3RzcHl2eXZLNzkwZ2U3TUJiUS1OdXMiXSwgImlzcyI6ICJodHRwczovL2V4YW1wbGUuY29tL2lzc3VlciIsICJpYXQiOiAxNTE2MjM5MDIyLCAiZXhwIjogMTUxNjI0NzAyMiwgIl9zZF9hbGciOiAic2hhLTI1NiIsICJjbmYiOiB7Imp3ayI6IHsia3R5IjogIlJTQSIsICJuIjogInBtNGJPSEJnLW9ZaEF5UFd6UjU2QVdYM3JVSVhwMTFfSUNEa0dnUzZXM1pXTHRzLWh6d0kzeDY1NjU5a2c0aFZvOWRiR29DSkUzWkdGX2VhZXRFMzBVaEJVRWdwR3dyRHJRaUo5enFwcm1jRmZyM3F2dmtHanR0aDhaZ2wxZU0yYkpjT3dFN1BDQkhXVEtXWXMxNTJSN2c2SmcyT1ZwaC1hOHJxLXE3OU1oS0c1UW9XX21UejEwUVRfNkg0YzdQaldHMWZqaDhocFdObmJQX3B2NmQxelN3WmZjNWZsNnlWUkwwRFYwVjNsR0hLZTJXcWZfZU5HakJyQkxWa2xEVGs4LXN0WF9NV0xjUi1FR21YQU92MFVCV2l0U19kWEpLSnUtdlhKeXcxNG5IU0d1eFRJSzJoeDFwdHRNZnQ5Q3N2cWltWEtlRFRVMTRxUUwxZUU3aWhjdyIsICJlIjogIkFRQUIifX19.xqgKrDO6dK_oBL3fiqdcq_elaIGxM6Z-RyuysglGyddR1O1IiE3mIk8kCpoqcRLR88opkVWN2392K_XYfAuAmeT9kJVisD8ZcgNcv-MQlWW9s8WaViXxBRe7EZWkWRQcQVR6jf95XZ5H2-_KA54POq3L42xjk0y5vDr8yc08Reak6vvJVvjXpp-Wk6uxsdEEAKFspt_EYIvISFJhfTuQqyhCjnaW13X312MSQBPwjbHn74ylUqVLljDvqcemxeqjh42KWJq4C3RqNJ7anA2i3FU1kB4-KNZWsijY7-op49iL7BrnIBxdlAMrbHEkoGTbFWdl7Ki17GHtDxxa1jaxQg~WyJkcVR2WE14UzBHYTNEb2FHbmU5eDBRIiwgInN1YiIsICJqb2huX2RvZV80MiJd~WyIzanFjYjY3ejl3a3MwOHp3aUs3RXlRIiwgImdpdmVuX25hbWUiLCAiSm9obiJd~WyJxUVdtakpsMXMxUjRscWhFTkxScnJ3IiwgImZhbWlseV9uYW1lIiwgIkRvZSJd~WyJLVXhTNWhFX1hiVmFjckdBYzdFRnd3IiwgImVtYWlsIiwgImpvaG5kb2VAZXhhbXBsZS5jb20iXQ~WyIzcXZWSjFCQURwSERTUzkzOVEtUml3IiwgInBob25lX251bWJlciIsICIrMS0yMDItNTU1LTAxMDEiXQ~WyIweEd6bjNNaXFzY3RaSV9PcERsQWJRIiwgImFkZHJlc3MiLCB7InN0cmVldF9hZGRyZXNzIjogIjEyMyBNYWluIFN0IiwgImxvY2FsaXR5IjogIkFueXRvd24iLCAicmVnaW9uIjogIkFueXN0YXRlIiwgImNvdW50cnkiOiAiVVMifV0~WyJFUktNMENOZUZKa2FENW1UWFZfWDh3IiwgImJpcnRoZGF0ZSIsICIxOTQwLTAxLTAxIl0`
const specCombinedFormatForIssuance = `eyJhbGciOiAiUlMyNTYiLCAia2lkIjogImNBRUlVcUowY21MekQxa3pHemhlaUJhZzBZUkF6VmRsZnhOMjgwTmdIYUEifQ.eyJfc2QiOiBbIk5ZQ29TUktFWXdYZHBlNXlkdUpYQ3h4aHluRVU4ei1iNFR5TmlhcDc3VVkiLCAiU1k4bjJCYmtYOWxyWTNleEhsU3dQUkZYb0QwOUdGOGE5Q1BPLUc4ajIwOCIsICJUUHNHTlBZQTQ2d21CeGZ2MnpuT0poZmRvTjVZMUdrZXpicGFHWkNUMWFjIiwgIlprU0p4eGVHbHVJZFlCYjdDcWtaYkpWbTB3MlY1VXJSZU5UekFRQ1lCanciLCAibDlxSUo5SlRRd0xHN09MRUlDVEZCVnhtQXJ3OFBqeTY1ZEQ2bXRRVkc1YyIsICJvMVNBc0ozM1lNaW9POXBYNVZlQU0xbHh1SEY2aFpXMmtHZGtLS0JuVmxvIiwgInFxdmNxbmN6QU1nWXg3RXlrSTZ3d3RzcHl2eXZLNzkwZ2U3TUJiUS1OdXMiXSwgImlzcyI6ICJodHRwczovL2V4YW1wbGUuY29tL2lzc3VlciIsICJpYXQiOiAxNTE2MjM5MDIyLCAiZXhwIjogMTUxNjI0NzAyMiwgIl9zZF9hbGciOiAic2hhLTI1NiIsICJjbmYiOiB7Imp3ayI6IHsia3R5IjogIlJTQSIsICJuIjogInBtNGJPSEJnLW9ZaEF5UFd6UjU2QVdYM3JVSVhwMTFfSUNEa0dnUzZXM1pXTHRzLWh6d0kzeDY1NjU5a2c0aFZvOWRiR29DSkUzWkdGX2VhZXRFMzBVaEJVRWdwR3dyRHJRaUo5enFwcm1jRmZyM3F2dmtHanR0aDhaZ2wxZU0yYkpjT3dFN1BDQkhXVEtXWXMxNTJSN2c2SmcyT1ZwaC1hOHJxLXE3OU1oS0c1UW9XX21UejEwUVRfNkg0YzdQaldHMWZqaDhocFdObmJQX3B2NmQxelN3WmZjNWZsNnlWUkwwRFYwVjNsR0hLZTJXcWZfZU5HakJyQkxWa2xEVGs4LXN0WF9NV0xjUi1FR21YQU92MFVCV2l0U19kWEpLSnUtdlhKeXcxNG5IU0d1eFRJSzJoeDFwdHRNZnQ5Q3N2cWltWEtlRFRVMTRxUUwxZUU3aWhjdyIsICJlIjogIkFRQUIifX19.xqgKrDO6dK_oBL3fiqdcq_elaIGxM6Z-RyuysglGyddR1O1IiE3mIk8kCpoqcRLR88opkVWN2392K_XYfAuAmeT9kJVisD8ZcgNcv-MQlWW9s8WaViXxBRe7EZWkWRQcQVR6jf95XZ5H2-_KA54POq3L42xjk0y5vDr8yc08Reak6vvJVvjXpp-Wk6uxsdEEAKFspt_EYIvISFJhfTuQqyhCjnaW13X312MSQBPwjbHn74ylUqVLljDvqcemxeqjh42KWJq4C3RqNJ7anA2i3FU1kB4-KNZWsijY7-op49iL7BrnIBxdlAMrbHEkoGTbFWdl7Ki17GHtDxxa1jaxQg~WyJkcVR2WE14UzBHYTNEb2FHbmU5eDBRIiwgInN1YiIsICJqb2huX2RvZV80MiJd~WyIzanFjYjY3ejl3a3MwOHp3aUs3RXlRIiwgImdpdmVuX25hbWUiLCAiSm9obiJd~WyJxUVdtakpsMXMxUjRscWhFTkxScnJ3IiwgImZhbWlseV9uYW1lIiwgIkRvZSJd~WyJLVXhTNWhFX1hiVmFjckdBYzdFRnd3IiwgImVtYWlsIiwgImpvaG5kb2VAZXhhbXBsZS5jb20iXQ~WyIzcXZWSjFCQURwSERTUzkzOVEtUml3IiwgInBob25lX251bWJlciIsICIrMS0yMDItNTU1LTAxMDEiXQ~WyIweEd6bjNNaXFzY3RaSV9PcERsQWJRIiwgImFkZHJlc3MiLCB7InN0cmVldF9hZGRyZXNzIjogIjEyMyBNYWluIFN0IiwgImxvY2FsaXR5IjogIkFueXRvd24iLCAicmVnaW9uIjogIkFueXN0YXRlIiwgImNvdW50cnkiOiAiVVMifV0~WyJFUktNMENOZUZKa2FENW1UWFZfWDh3IiwgImJpcnRoZGF0ZSIsICIxOTQwLTAxLTAxIl0`
28 changes: 14 additions & 14 deletions pkg/doc/sdjwt/holder/holder.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func WithSignatureVerifier(signatureVerifier jose.SignatureVerifier) ParseOpt {
}

// Parse parses issuer SD-JWT and returns claims that can be selected.
func Parse(sdJWTSerialized string, opts ...ParseOpt) ([]*Claim, error) {
func Parse(combinedFormatForIssuance string, opts ...ParseOpt) ([]*Claim, error) {
pOpts := &parseOpts{
sigVerifier: &NoopSignatureVerifier{},
}
Expand All @@ -60,19 +60,19 @@ func Parse(sdJWTSerialized string, opts ...ParseOpt) ([]*Claim, error) {
afgjwt.WithSignatureVerifier(pOpts.sigVerifier),
afgjwt.WithJWTDetachedPayload(pOpts.detachedPayload))

sdJWT := common.ParseSDJWT(sdJWTSerialized)
cfi := common.ParseCombinedFormatForIssuance(combinedFormatForIssuance)

signedJWT, err := afgjwt.Parse(sdJWT.JWTSerialized, jwtOpts...)
signedJWT, err := afgjwt.Parse(cfi.SDJWT, jwtOpts...)
if err != nil {
return nil, err
}

err = common.VerifyDisclosuresInSDJWT(sdJWT.Disclosures, signedJWT)
err = common.VerifyDisclosuresInSDJWT(cfi.Disclosures, signedJWT)
if err != nil {
return nil, err
}

return getClaims(sdJWT.Disclosures)
return getClaims(cfi.Disclosures)
}

func getClaims(disclosures []string) ([]*Claim, error) {
Expand All @@ -94,14 +94,14 @@ func getClaims(disclosures []string) ([]*Claim, error) {
}

// DiscloseClaims discloses claims with specified claim names.
func DiscloseClaims(sdJWTSerialized string, claimNames []string) (string, error) {
sdJWT := common.ParseSDJWT(sdJWTSerialized)
func DiscloseClaims(combinedFormatForIssuance string, claimNames []string) (string, error) {
cfi := common.ParseCombinedFormatForIssuance(combinedFormatForIssuance)

if len(sdJWT.Disclosures) == 0 {
if len(cfi.Disclosures) == 0 {
return "", fmt.Errorf("no disclosures found in SD-JWT")
}

disclosures, err := common.GetDisclosureClaims(sdJWT.Disclosures)
disclosures, err := common.GetDisclosureClaims(cfi.Disclosures)
if err != nil {
return "", err
}
Expand All @@ -110,16 +110,16 @@ func DiscloseClaims(sdJWTSerialized string, claimNames []string) (string, error)

for _, claimName := range claimNames {
if index := getDisclosureByClaimName(claimName, disclosures); index != notFound {
selectedDisclosures = append(selectedDisclosures, sdJWT.Disclosures[index])
selectedDisclosures = append(selectedDisclosures, cfi.Disclosures[index])
}
}

combinedFormatForPresentation := sdJWT.JWTSerialized
for _, disclosure := range selectedDisclosures {
combinedFormatForPresentation += common.DisclosureSeparator + disclosure
cf := common.CombinedFormatForPresentation{
SDJWT: cfi.SDJWT,
Disclosures: selectedDisclosures,
}

return combinedFormatForPresentation, nil
return cf.Serialize(), nil
}

func getDisclosureByClaimName(name string, disclosures []*common.DisclosureClaim) int {
Expand Down
Loading