Skip to content

Commit

Permalink
vp: embryo2 of verify vc's in a vp_token of type jws (backup commit)
Browse files Browse the repository at this point in the history
  • Loading branch information
matskramer committed Jan 30, 2025
1 parent 9e4a60d commit 53fb325
Show file tree
Hide file tree
Showing 15 changed files with 5,707 additions and 44 deletions.
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ require (
github.com/swaggo/files v1.0.1
github.com/swaggo/gin-swagger v1.6.0
github.com/swaggo/swag v1.16.4
github.com/tidwall/gjson v1.18.0
github.com/wealdtech/go-merkletree v1.0.0
github.com/xuri/excelize/v2 v2.9.0
go.mongodb.org/mongo-driver v1.17.1
Expand Down Expand Up @@ -93,6 +94,8 @@ require (
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.4 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,12 @@ github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE=
github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
Expand Down
79 changes: 44 additions & 35 deletions internal/verifier/apiv1/verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"errors"
"fmt"
"github.com/golang-jwt/jwt/v5"
"github.com/tidwall/gjson"

"strings"
"time"
)
Expand All @@ -28,11 +30,15 @@ func NewVPToken(vp_token string) (*VPToken, error) {
type VPToken struct {
RawToken string // The raw input token

HeaderDecoded map[string]interface{}
PayloadDecoded map[string]interface{}
SignatureDecoded string
HeaderDecoded string
HeaderDecodedMap map[string]interface{}
PayloadDecoded string
PayloadDecodedMap map[string]interface{}
SignatureDecoded string

VerifiableCredentialList *[]VC

VerifiableCredentials *[]VC
//TODO ta fram och lägg in presentation submission som en struct

//DisclosedClaims []string // Claims disclosed by the Holder

Expand All @@ -44,13 +50,14 @@ type VPToken struct {
type VC struct {
//if jwt_vc or ldp_vc
Format string
Typ string

// jwt_vc
RawToken string
HeaderDecoded map[string]interface{}
PayloadDecoded map[string]interface{}
SignatureDecoded string
Disclosures []string
RawToken string
HeaderDecodedMap map[string]interface{}
PayloadDecodedMap map[string]interface{}
SignatureDecoded string
Disclosures []string
//TODO add HolderBinding

//TODO ldp_vc
Expand Down Expand Up @@ -103,22 +110,29 @@ func (vp *VPToken) Validate(holderPublicKey interface{}) error {
return vp.validatePresentationRequirements()
}

// TODO döp om till något i stil med parseDecryptAndDecodeVPToken
// extractAndDecodeTopLevel (decrypt - not supported yet), extract and decode the vp_token into its components: header, payload, and signature.
func (vp *VPToken) extractAndDecodeVPToken() error {
parsedToken, err := parseVPToken(vp.RawToken)
if err != nil {
return err
}

headerDecoded, err := decodeBase64URL(parsedToken.header)
headerDecoded, err := decodeBase64URL(parsedToken.headerEncoded)
if err != nil {
return err
}
if !gjson.Valid(headerDecoded) {
return fmt.Errorf("Header is not valid json")
}

payloadDecoded, err := decodeBase64URL(parsedToken.payload)
payloadDecoded, err := decodeBase64URL(parsedToken.payloadEncoded)
if err != nil {
return err
}
if !gjson.Valid(payloadDecoded) {
return fmt.Errorf("Payload is not valid json")
}

headerMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(headerDecoded), &headerMap); err != nil {
Expand All @@ -130,7 +144,7 @@ func (vp *VPToken) extractAndDecodeVPToken() error {
return err
}

paddedSignature := parsedToken.signature
paddedSignature := parsedToken.signatureEncoded
switch len(paddedSignature) % 4 {
case 2:
paddedSignature += "=="
Expand All @@ -144,8 +158,10 @@ func (vp *VPToken) extractAndDecodeVPToken() error {
// convert byte-array till en string (if signature actually is a text)
signatureString := string(signatureBytes)

vp.HeaderDecoded = headerMap
vp.PayloadDecoded = payloadMap
vp.HeaderDecoded = headerDecoded
vp.HeaderDecodedMap = headerMap
vp.PayloadDecoded = payloadDecoded
vp.PayloadDecodedMap = payloadMap
vp.SignatureDecoded = signatureString

//TODO: hantera vad som ev. finns i parsedVPToken.disclosures - kan vara så att vissa disclosures i själva verket är en egen jwt (den sista i så fall?)
Expand All @@ -155,19 +171,14 @@ func (vp *VPToken) extractAndDecodeVPToken() error {

func (vp *VPToken) extractAndDecodeVerifiableCredentials() error {

//TODO: ta in och använd https://github.com/tidwall/gjson för att suga ut nedan samt presentation_submission och dess delar för att veta vad för vc som finns

vpField, ok := vp.PayloadDecoded["vp"].(map[string]interface{})
if !ok {
return fmt.Errorf("vp key in vp_token.payload is missing or har wrong format/name")
vcList := gjson.Get(vp.PayloadDecoded, "vp.verifiableCredential")
if !vcList.Exists() || !vcList.IsArray() {
return errors.New("verifiable credentials not found in vp_token payload")
}

vcList, ok := vpField["verifiableCredential"].([]interface{})
if !ok {
return fmt.Errorf("verifiableCredential key in vp_token.payload is missing or has wrong format/name")
}
//TODO ta ut presentation_submission för användning nedan samt för att avgöra om koden kan hantera denna typ av vc (och är samma som begärd från holdern i tidigare request)

for _, vc := range vcList {
for _, vc := range vcList.Array() {
fmt.Println(vc)

//TODO avgör för varje vc via payload.presentation_submission.descriptor_map.format om det är jwt_vc (jwt)eller ldp_vc (json-ld)
Expand All @@ -187,7 +198,7 @@ func (vp *VPToken) validateHolderSignature(holderPublicKey interface{}) error {

parsedToken, err := jwt.Parse(vp.RawToken, func(token *jwt.Token) (interface{}, error) {
alg := token.Method.Alg()
fmt.Printf("\n🔍 Found signing alg:: %s\n", alg)
fmt.Printf("\n🔍 Found vp_token signing alg: %s\n", alg)
return holderPublicKey, nil
})
if err != nil {
Expand Down Expand Up @@ -224,7 +235,7 @@ func (vp *VPToken) validateHolderSignature(holderPublicKey interface{}) error {
}
}

//TODO(mk): check revocation of the JWT
//TODO(mk): check revocation
//if jti, ok := claims["jti"].(string); ok {
// if revokedTokens[jti] {
// return fmt.Errorf("JWT is revoked")
Expand Down Expand Up @@ -283,14 +294,12 @@ func (vp *VPToken) decodeBase64URL(input string) ([]byte, error) {
type parsedVPToken struct {
raw string

header string
payload string
signature string
headerEncoded string
payloadEncoded string
signatureEncoded string
}

func parseVPToken(vpToken string) (*parsedVPToken, error) {
//TODO: om vp_token är en JWE så dekryptera den först: JWS (header.payload.signature(~)) eller en JWE (x.x.x.x.x)

result := &parsedVPToken{
// just to simplify debug
raw: vpToken,
Expand All @@ -309,13 +318,13 @@ func parseVPToken(vpToken string) (*parsedVPToken, error) {
return nil, fmt.Errorf("invalid JWS/JWE-structure")
}
if len(parts) == 5 {
//TODO(mk): handle that the vp_token is a JWE
//TODO(mk): handle that the vp_token is a JWE (decrypt)
return nil, fmt.Errorf("JWE (encrypted) not supported yet!")
}

result.header = tokenParts[0]
result.payload = tokenParts[1]
result.signature = tokenParts[2]
result.headerEncoded = tokenParts[0]
result.payloadEncoded = tokenParts[1]
result.signatureEncoded = tokenParts[2]

//TODO(mk): handle disclosures, holder bindings and other stuff??? if exist
//if len(parts) > 1 {
Expand Down
77 changes: 68 additions & 9 deletions internal/verifier/apiv1/verifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,23 @@ import (
"fmt"
"github.com/ethereum/go-ethereum/crypto" // For secp256k1 (ES256K)
"github.com/golang-jwt/jwt/v5"
"strings"
"testing"
"time"
)

func TestVPToken_Validate(t *testing.T) {
const pid_sd_vc_jwt_with_selective_disclosures_and_holder_binding = "eyJ0eXAiOiJKV1QiLCJ2Y3RtIjpbImV5SjJZM1FpT2lKMWNtNDZZM0psWkdWdWRHbGhiRHAyYVdRaUxDSnVZVzFsSWpvaVVFbEVJaXdpWkdWelkzSnBjSFJwYjI0aU9pSlVhR2x6SUdseklHRWdVRWxFSUdSdlkzVnRaVzUwSUdsemMzVmxaQ0JpZVNCMGFHVWdkMlZzYkNCcmJtOTNiaUJXU1VRZ1NYTnpkV1Z5SWl3aVpHbHpjR3hoZVNJNlczc2libUZ0WlNJNklsQkpSQ0lzSW5KbGJtUmxjbWx1WnlJNmV5SnphVzF3YkdVaU9uc2liRzluYnlJNmV5SjFjbWtpT2lKb2RIUndjem92TDNsdmRYSmxkV1JwTG1Sak5HVjFMbVYxTDJsdFlXZGxjeTkyYVdSRFlYSmtMbkJ1WnlJc0luVnlhU05wYm5SbFozSnBkSGtpT2lKemFHRXlOVFl0WVdOa1lUTTBNRFJqTW1ObU5EWmtZVEU1TW1ObU1qUTFZMk5qTm1JNU1XVmtZMlU0T0RZNU1USXlabUUxWVRZMk16WXlPRFJtTVdFMk1HWm1ZMlE0TmlJc0ltRnNkRjkwWlhoMElqb2lWa2xFSUVOaGNtUWlmU3dpWW1GamEyZHliM1Z1WkY5amIyeHZjaUk2SWlNeE1qRXdOMk1pTENKMFpYaDBYMk52Ykc5eUlqb2lJMFpHUmtaR1JpSjlMQ0p6ZG1kZmRHVnRjR3hoZEdWeklqcGJleUoxY21raU9pSm9kSFJ3Y3pvdkwzbHZkWEpsZFdScExtUmpOR1YxTG1WMUwybHRZV2RsY3k5cFpGUmxiWEJzWVhSbExuTjJaeUo5WFgxOVhTd2lZMnhoYVcxeklqcGJleUp3WVhSb0lqcGJJbWRwZG1WdVgyNWhiV1VpWFN3aVpHbHpjR3hoZVNJNmV5SmxiaTFWVXlJNmV5SnNZV0psYkNJNklrZHBkbVZ1SUU1aGJXVWlMQ0prWlhOamNtbHdkR2x2YmlJNklsUm9aU0JuYVhabGJpQnVZVzFsSUc5bUlIUm9aU0JXU1VRZ2FHOXNaR1Z5SW4xOUxDSjJaWEpwWm1sallYUnBiMjRpT2lKMlpYSnBabWxsWkNJc0luTmtJam9pWVd4c2IzZGxaQ0lzSW5OMloxOXBaQ0k2SW1kcGRtVnVYMjVoYldVaWZTeDdJbkJoZEdnaU9sc2labUZ0YVd4NVgyNWhiV1VpWFN3aVpHbHpjR3hoZVNJNmV5SmxiaTFWVXlJNmV5SnNZV0psYkNJNklrWmhiV2xzZVNCT1lXMWxJaXdpWkdWelkzSnBjSFJwYjI0aU9pSlVhR1VnWm1GdGFXeDVJRzVoYldVZ2IyWWdkR2hsSUZaSlJDQm9iMnhrWlhJaWZYMHNJblpsY21sbWFXTmhkR2x2YmlJNkluWmxjbWxtYVdWa0lpd2ljMlFpT2lKaGJHeHZkMlZrSWl3aWMzWm5YMmxrSWpvaVptRnRhV3g1WDI1aGJXVWlmU3g3SW5CaGRHZ2lPbHNpWW1seWRHaGZaR0YwWlNKZExDSmthWE53YkdGNUlqcDdJbVZ1TFZWVElqcDdJbXhoWW1Wc0lqb2lRbWx5ZEdnZ1JHRjBaU0lzSW1SbGMyTnlhWEIwYVc5dUlqb2lWR2hsSUdKcGNuUm9JR1JoZEdVZ2IyWWdkR2hsSUZaSlJDQm9iMnhrWlhJaWZYMHNJblpsY21sbWFXTmhkR2x2YmlJNkluWmxjbWxtYVdWa0lpd2ljMlFpT2lKaGJHeHZkMlZrSWl3aWMzWm5YMmxrSWpvaVltbHlkR2hmWkdGMFpTSjlMSHNpY0dGMGFDSTZXeUpwYzNOMWFXNW5YMkYxZEdodmNtbDBlU0pkTENKa2FYTndiR0Y1SWpwN0ltVnVMVlZUSWpwN0lteGhZbVZzSWpvaVNYTnpkV2x1WnlCQmRYUm9iM0pwZEhraUxDSmtaWE5qY21sd2RHbHZiaUk2SWxSb1pTQmpiM1Z1ZEhKNUlHTnZaR1VnYjJZZ2RHaGxJR0YxZEdodmNtbDBlU0IwYUdGMElHbHpjM1ZsWkNCMGFHbHpJR055WldSbGJuUnBZV3dpZlgwc0luWmxjbWxtYVdOaGRHbHZiaUk2SW1GMWRHaHZjbWwwWVhScGRtVWlMQ0p6WkNJNkltRnNiRzkzWldRaUxDSnpkbWRmYVdRaU9pSnBjM04xYVc1blgyRjFkR2h2Y21sMGVTSjlMSHNpY0dGMGFDSTZXeUpwYzNOMVlXNWpaVjlrWVhSbElsMHNJbVJwYzNCc1lYa2lPbnNpWlc0dFZWTWlPbnNpYkdGaVpXd2lPaUpKYzNOMVlXNWpaU0JFWVhSbElpd2laR1Z6WTNKcGNIUnBiMjRpT2lKVWFHVWdaR0YwWlNCaGJtUWdkR2x0WlNCcGMzTjFaV1FnZEdocGN5QmpjbVZrWlc1MGFXRnNJbjE5TENKMlpYSnBabWxqWVhScGIyNGlPaUpoZFhSb2IzSnBkR0YwYVhabElpd2ljMlFpT2lKaGJHeHZkMlZrSWl3aWMzWm5YMmxrSWpvaWFYTnpkV0Z1WTJWZlpHRjBaU0o5TEhzaWNHRjBhQ0k2V3lKbGVIQnBjbmxmWkdGMFpTSmRMQ0prYVhOd2JHRjVJanA3SW1WdUxWVlRJanA3SW14aFltVnNJam9pUlhod2FYSjVJRVJoZEdVaUxDSmtaWE5qY21sd2RHbHZiaUk2SWxSb1pTQmtZWFJsSUdGdVpDQjBhVzFsSUdWNGNHbHlaV1FnZEdocGN5QmpjbVZrWlc1MGFXRnNJbjE5TENKMlpYSnBabWxqWVhScGIyNGlPaUpoZFhSb2IzSnBkR0YwYVhabElpd2ljMlFpT2lKaGJHeHZkMlZrSWl3aWMzWm5YMmxrSWpvaVpYaHdhWEo1WDJSaGRHVWlmVjBzSW5OamFHVnRZU0k2ZXlJa2MyTm9aVzFoSWpvaWFIUjBjRG92TDJwemIyNHRjMk5vWlcxaExtOXlaeTlrY21GbWRDMHdOeTl6WTJobGJXRWpJaXdpZEhsd1pTSTZJbTlpYW1WamRDSXNJbkJ5YjNCbGNuUnBaWE1pT25zaVoybDJaVzVmYm1GdFpTSTZleUowZVhCbElqb2ljM1J5YVc1bkluMHNJbVpoYldsc2VWOXVZVzFsSWpwN0luUjVjR1VpT2lKemRISnBibWNpZlN3aVltbHlkR2hmWkdGMFpTSTZleUowZVhCbElqb2ljM1J5YVc1bkluMHNJbWx6YzNWcGJtZGZZWFYwYUc5eWFYUjVJanA3SW5SNWNHVWlPaUp6ZEhKcGJtY2lmU3dpYVhOemRXRnVZMlZmWkdGMFpTSTZleUowZVhCbElqb2ljM1J5YVc1bkluMHNJbVY0Y0dseWVWOWtZWFJsSWpwN0luUjVjR1VpT2lKemRISnBibWNpZlgwc0luSmxjWFZwY21Wa0lqcGJYU3dpWVdSa2FYUnBiMjVoYkZCeWIzQmxjblJwWlhNaU9uUnlkV1Y5ZlEiXSwieDVjIjpbIk1JSUIzRENDQVlFQ0ZIQkRXcGtMaTY0ZjVackYweHV5dGo1UElyYnFNQW9HQ0NxR1NNNDlCQU1DTUhBeEN6QUpCZ05WQkFZVEFrZFNNUTh3RFFZRFZRUUlEQVpCZEdobGJuTXhFREFPQmdOVkJBY01CMGxzYkdsemFXRXhFVEFQQmdOVkJBb01DSGQzVjJGc2JHVjBNUkV3RHdZRFZRUUxEQWhKWkdWdWRHbDBlVEVZTUJZR0ExVUVBd3dQZDNkM1lXeHNaWFF0YVhOemRXVnlNQjRYRFRJME1Ea3lOakE0TVRReE1sb1hEVE0wTURreU5EQTRNVFF4TWxvd2NERUxNQWtHQTFVRUJoTUNSMUl4RHpBTkJnTlZCQWdNQmtGMGFHVnVjekVRTUE0R0ExVUVCd3dIU1d4c2FYTnBZVEVSTUE4R0ExVUVDZ3dJZDNkWFlXeHNaWFF4RVRBUEJnTlZCQXNNQ0Vsa1pXNTBhWFI1TVJnd0ZnWURWUVFEREE5M2QzZGhiR3hsZEMxcGMzTjFaWEl3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVF0WTlrVVFGZkRmNmlvY0ZFNHJSdnkzR015WXlwcW1YM1pqbXdVZVhKeTBra2dSVDczQzgrV1BrV05nL3lkSkhDRURETzVYdVJhSWFPSGM5RHBMcE5TTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDSVFEencyN25CcjdFOE42R3FjODN2LzYrOWl6aS9ORVhCS2xvandMSkFlU2xzQUloQU8ySmRqUEV6M2JEMHN0b1dFZzdSRHRyQW04ZHNncnlDeTFXNUJER0NWZE4iXSwiYWxnIjoiRVMyNTYifQ.eyJjbmYiOnsiandrIjp7ImNydiI6IlAtMjU2IiwiZXh0Ijp0cnVlLCJrZXlfb3BzIjpbInZlcmlmeSJdLCJrdHkiOiJFQyIsIngiOiJvdy0tc1EwTERHYWxEMEJtZ2VmeWtnOTBJT2FKX1lHZ0RyZTNLMUtwNkY4IiwieSI6Ikp1SjBOX3ZNQ3NrNkdsTVd1SEpVMXlsNVRDQkp0dnpNWjlEMjU3UkJmUFUifX0sInZjdCI6InVybjpjcmVkZW50aWFsOnZpZCIsImp0aSI6InVybjp2aWQ6YjBmNzE3MzgtYzI0Zi00OWVjLThkZTMtOWJhN2YyN2FlYWMyIiwiaXNzdWFuY2VfZGF0ZSI6IjIwMjUtMDEtMjRUMTI6NDc6NDMuMjI4WiIsImV4cGlyeV9kYXRlIjoiMjAyNi0wNC0yMVQwMDowMDowMC4wMDBaIiwiaWF0IjoxNzM3NzIyODYzLCJleHAiOjE3NzY3Mjk2MDAsImlzcyI6Imh0dHBzOi8veW91cmV1ZGkuZGM0ZXUuZXUiLCJzdWIiOiJWckdRbUlYa1pZNVktOUxCWG43TUduU01DT1NOSnVIaTRjSUJHZ01QNkdrIiwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiQjJPRWsxalNweS02Z0Fmc21pb2Z2ZFZqeFgzSlBoZ0pmQXJLdXdpaXNCQSIsIlNVUnhpMjc3VzlzeWVlY2FHMWZIVDFyUTVCYnhQZkJBYkdpbjRRNDBHT28iLCJmZm9wSTlRczRFZDVFR3o5bm5RbGFfazZ6MnJWODNMXzYxRTNjWXA2OWtjIiwidk5kUWRCTlEyODFpb3N4S204SzB4NzV5WlMybGI1MEtRTndlOVVMNlRHOCIsIncwMzU3YV9uV2ZHaFlpR3ZvVGVTaXhSZzNzRzd0X3hQNmhEQjBaeGRNYkEiXX0.qVUfsWRZxMQsbzMR5kYNvNikJNEBjuEPMQ6npjRRAZrYz_-egFBVq0TivIOHfJ0hcYxIJh3kxIUzHBWjLV9yFQ~WyJyOWtyS1J6S3JVTU5TSXViTlJQOWp3IiwiZ2l2ZW5fbmFtZSIsIlNjYXJsZXR0Il0~WyJOQ2lYekI5ZjJYRWlwU2xtc0dPRWFRIiwiZmFtaWx5X25hbWUiLCJKb2hhbnNzb24iXQ~eyJ0eXAiOiJrYitqd3QiLCJhbGciOiJFUzI1NiJ9.eyJub25jZSI6IjA2NWY0NTQ4LTM3NzQtNDJhNS04MjYyLWU5NDhiMjIyNDhkMCIsImF1ZCI6InlvdXJmcmllbmRseXZlcmlmaWVyLmRjNGV1LmV1Iiwic2RfaGFzaCI6ImlfdjJQbUg5NnZ4eGJfbXQ3RmtIdkQ1aEdXeENOamhIdlpzYXlUSlA1alUiLCJpYXQiOjE3Mzc5Njk3Mzl9.4cJbdod2KnKoNAsaIyGlw4ehNl4JAEk9fw6lJqW8Kdq2a65iL9qsVgRSVGO11OuSKX663lUdjnAWA9_glnDUIQ"

func TestVPToken_Validate(t *testing.T) {
ecdsaP256Private, ecdsaP256Public, err := generateECDSAKeyPair(elliptic.P256())
if err != nil {
t.Fatal(err)
}
vp_token, err := build_vp_jws_token_with_ldp_vc_credentials(jwt.SigningMethodES256, ecdsaP256Private, "did:example:issuer#key-1")
vp_token_with_1_jwt_vc, err := build_vp_jws_token_with_jwt_vc_credentials(pid_sd_vc_jwt_with_selective_disclosures_and_holder_binding, jwt.SigningMethodES256, ecdsaP256Private, "did:example:issuer#key-1")
if err != nil {
t.Fatal(err)
}
vp_token_with_2_ldp_vc, err := build_vp_jws_token_with_ldp_vc_credentials(jwt.SigningMethodES256, ecdsaP256Private, "did:example:issuer#key-1")
if err != nil {
t.Fatal(err)
}
Expand All @@ -36,13 +42,22 @@ func TestVPToken_Validate(t *testing.T) {
}{
//TODO bryt ut till till en testcase builder för att enkelt testa massa olika varianter
{
name: "Generated vp token",
name: "Generated vp token with 1 hardcoded jwt_vc",
fields: fields{
RawToken: vp_token_with_1_jwt_vc,
},
holderPublicKey: ecdsaP256Public,
wantErr: false,
},
{
name: "Generated vp token with 2 ldp_vc",
fields: fields{
RawToken: vp_token,
RawToken: vp_token_with_2_ldp_vc,
},
holderPublicKey: ecdsaP256Public,
wantErr: false,
},

//{
// name: "Hardcoded vp_token_1",
// fields: fields{
Expand All @@ -66,6 +81,49 @@ func TestVPToken_Validate(t *testing.T) {
}
}

func build_vp_jws_token_with_jwt_vc_credentials(vcJWT string, signingMethod jwt.SigningMethod, holderPublicKey interface{}, keyID string) (string, error) {
now := time.Now()

var vcList []string
if strings.TrimSpace(vcJWT) == "" {
vcList = []string{}
} else {
vcList = []string{vcJWT}
}

claims := jwt.MapClaims{
"iss": "did:example:issuer",
"aud": "did:example:verifier",
"iat": now.Unix(),
"exp": now.Add(time.Minute * 5).Unix(),
"vp": map[string]interface{}{
"@context": []string{
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/security/v2",
},
"type": []string{"VerifiablePresentation"},
"verifiableCredential": vcList,
},
"presentation_submission": map[string]interface{}{
"id": "ae1773e-3e19-4032-a1c2-a6b69087e5b2",
"definition_id": "vp_definition_1",
"descriptor_map": []map[string]interface{}{
{
"id": "pid_input",
"path": "$.vp.verifiableCredential[0]",
"format": "jwt_vc",
},
},
},
}

token := jwt.NewWithClaims(signingMethod, claims)
token.Header["kid"] = keyID
token.Header["typ"] = "JWS"

return signJWT(signingMethod, token, holderPublicKey)
}

func build_vp_jws_token_with_ldp_vc_credentials(signingMethod jwt.SigningMethod, holderPublicKey interface{}, keyID string) (string, error) {
now := time.Now()

Expand All @@ -80,9 +138,6 @@ func build_vp_jws_token_with_ldp_vc_credentials(signingMethod jwt.SigningMethod,
"https://w3id.org/security/v2",
},
"type": []string{"VerifiablePresentation"},
// "verifiableCredential": []string{
// "eyJhbGciOiJFUzI1NiIsImtpZCI6IjE2In0...", //TODO(mk): use this for jwt and replace with generated credential (vc+sd-jwt with and without disclosures (and holder sign?)). Also change format in presentation_submission to "jwt_vc"
// },
"verifiableCredential": []interface{}{
map[string]interface{}{
"@context": []string{
Expand Down Expand Up @@ -132,8 +187,8 @@ func build_vp_jws_token_with_ldp_vc_credentials(signingMethod jwt.SigningMethod,
},
},
"presentation_submission": map[string]interface{}{
"id": "ae73773e-3e39-4032-a1c2-a6b69087e5b6",
"definition_id": "vp_definition_1",
"id": "ae23773e-3e39-4032-a1c2-a6b69087e5b6",
"definition_id": "vp_definition_2",
"descriptor_map": []map[string]interface{}{
{
"id": "degree_input",
Expand All @@ -153,6 +208,10 @@ func build_vp_jws_token_with_ldp_vc_credentials(signingMethod jwt.SigningMethod,
token.Header["kid"] = keyID
token.Header["typ"] = "JWS"

return signJWT(signingMethod, token, holderPublicKey)
}

func signJWT(signingMethod jwt.SigningMethod, token *jwt.Token, holderPublicKey interface{}) (string, error) {
switch signingMethod.(type) {
case *jwt.SigningMethodECDSA:
return token.SignedString(holderPublicKey.(*ecdsa.PrivateKey))
Expand Down
20 changes: 20 additions & 0 deletions vendor/github.com/tidwall/gjson/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 53fb325

Please sign in to comment.