From 288059c9cbb96db3a998ecf7c5c6e1a710e8180f Mon Sep 17 00:00:00 2001 From: ilya-korotya Date: Tue, 17 Sep 2024 12:21:57 +0200 Subject: [PATCH 1/3] use package manager to verify jwz token --- auth.go | 22 ++-------------------- go.mod | 6 +++--- go.sum | 11 ++++++----- 3 files changed, 11 insertions(+), 28 deletions(-) diff --git a/auth.go b/auth.go index 46a0cba..da97909 100644 --- a/auth.go +++ b/auth.go @@ -524,29 +524,11 @@ func (v *Verifier) VerifyJWZ( opts ...pubsignals.VerifyOpt, ) (t *jwz.Token, err error) { - t, err = jwz.Parse(token) - if err != nil { - return nil, err - } - - verificationKey, err := v.verificationKeyLoader.Load(circuits.CircuitID(t.CircuitID)) - if err != nil { - return nil, errors.Errorf("verification key for circuit with id %s not found", t.CircuitID) - } - isValid, err := t.Verify(verificationKey) + _, _, err = v.packageManager.Unpack([]byte(token)) if err != nil { return nil, err } - if !isValid { - return nil, errors.New("zero knowledge proof of jwz is not valid") - } - - circuitVerifier, err := getPublicSignalsVerifier(circuits.CircuitID(t.CircuitID), t.ZkProof.PubSignals) - if err != nil { - return nil, err - } - - err = circuitVerifier.VerifyStates(ctx, v.stateResolver, opts...) + t, err = jwz.Parse(token) if err != nil { return nil, err } diff --git a/go.mod b/go.mod index e831e69..a2b7e0a 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,8 @@ require ( github.com/google/uuid v1.6.0 github.com/iden3/contracts-abi/state/go/abi v1.0.1 github.com/iden3/go-circuits/v2 v2.3.0 - github.com/iden3/go-iden3-core/v2 v2.2.0 - github.com/iden3/go-iden3-crypto v0.0.16 + github.com/iden3/go-iden3-core/v2 v2.3.1 + github.com/iden3/go-iden3-crypto v0.0.17 github.com/iden3/go-jwz/v2 v2.1.1 github.com/iden3/go-rapidsnark/types v0.0.3 github.com/iden3/go-rapidsnark/verifier v0.0.5 @@ -19,7 +19,7 @@ require ( github.com/ipfs/go-ipfs-api v0.7.0 github.com/piprate/json-gold v0.5.1-0.20230111113000-6ddbe6e6f19f github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 ) require ( diff --git a/go.sum b/go.sum index 6b2b5fe..ebdec82 100644 --- a/go.sum +++ b/go.sum @@ -110,10 +110,10 @@ github.com/iden3/contracts-abi/state/go/abi v1.0.1 h1:FsaLJSy3NSyJl5k1yfDxc5DhUH github.com/iden3/contracts-abi/state/go/abi v1.0.1/go.mod h1:TxgIrXCvxms3sbOdsy8kTvffUCIpEEifNy0fSXdkU4w= github.com/iden3/go-circuits/v2 v2.3.0 h1:xzDVuq4JkTgtz+AjatquuPgGVbOxRpcWMhUOcWEZJN4= github.com/iden3/go-circuits/v2 v2.3.0/go.mod h1:APhXQaRQr4txd+u0Y7liBjN/Wnox0d31wR40LkXywAE= -github.com/iden3/go-iden3-core/v2 v2.2.0 h1:PcMSxJRLAoJausj1gKstzgt25HS18K+IHLaSPeI9p8Q= -github.com/iden3/go-iden3-core/v2 v2.2.0/go.mod h1:L9PxhWPvoS9qTb3inEkZBm1RpjHBt+VTwvxssdzbAdw= -github.com/iden3/go-iden3-crypto v0.0.16 h1:zN867xiz6HgErXVIV/6WyteGcOukE9gybYTorBMEdsk= -github.com/iden3/go-iden3-crypto v0.0.16/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= +github.com/iden3/go-iden3-core/v2 v2.3.1 h1:ytQqiclnVAIWyRKR2LF31hfz4DGRBD6nMjiPILXGSKk= +github.com/iden3/go-iden3-core/v2 v2.3.1/go.mod h1:8vmG6y8k9VS7iNoxuiKukKbRQFsMyabCc+i8er07zOs= +github.com/iden3/go-iden3-crypto v0.0.17 h1:NdkceRLJo/pI4UpcjVah4lN/a3yzxRUGXqxbWcYh9mY= +github.com/iden3/go-iden3-crypto v0.0.17/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= github.com/iden3/go-jwz/v2 v2.1.1 h1:6274wip59HAi9GkKewG0kKj/WBJeT6T4B+IotQM8IrY= github.com/iden3/go-jwz/v2 v2.1.1/go.mod h1:1mEhNrtAO4eACWZeg9k6T0CxadN4XUkj/dfWUBk3exE= github.com/iden3/go-merkletree-sql/v2 v2.0.4 h1:Dp089P3YNX1BE8+T1tKQHWTtnk84Y/Kr7ZAGTqwscoY= @@ -238,8 +238,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tetratelabs/wazero v1.1.0 h1:EByoAhC+QcYpwSZJSs/aV0uokxPwBgKxfiokSUwAknQ= From be3f2691eb90373cb5463fe9d864c12fff990b6d Mon Sep 17 00:00:00 2001 From: ilya-korotya Date: Tue, 17 Sep 2024 14:56:12 +0200 Subject: [PATCH 2/3] add parse connection strung function; fix linter --- auth.go | 62 +++++++++++++++++++++++++++++++++++++++++--- auth_test.go | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 3 deletions(-) diff --git a/auth.go b/auth.go index da97909..24e7460 100644 --- a/auth.go +++ b/auth.go @@ -9,6 +9,9 @@ import ( "log" "math/big" "net/http" + "net/url" + "strconv" + "strings" "time" "github.com/ethereum/go-ethereum/common" @@ -20,6 +23,7 @@ import ( "github.com/iden3/go-iden3-auth/v2/proofs" "github.com/iden3/go-iden3-auth/v2/pubsignals" "github.com/iden3/go-iden3-auth/v2/state" + core "github.com/iden3/go-iden3-core/v2" "github.com/iden3/go-iden3-core/v2/w3c" "github.com/iden3/go-jwz/v2" schemaloaders "github.com/iden3/go-schema-processor/v2/loaders" @@ -153,6 +157,58 @@ func newOpts() verifierOpts { } } +// ParseConnectionString parses the connection string and returns a map of state resolvers. +// The connection string format is as follows: +// +// chainID1=rpcURL1|contractAddress1;chainID2=rpcURL2|contractAddress2;... +// +// Each chainID is an integer representing the blockchain ID. +// Each rpcURL is the URL of the RPC endpoint for the blockchain. +// Each contractAddress is the address of the contract on the blockchain. +// The function returns an error if the connection string is in an invalid format or if the contract address is invalid. +// If the length of the result is 0, it means no connection info was found and an error is returned. +func ParseConnectionString(str string) (map[string]pubsignals.StateResolver, error) { + str = strings.TrimSpace(str) + result := make(map[string]pubsignals.StateResolver) + connectionInfo := strings.Split(str, ";") + for _, chain := range connectionInfo { + parts := strings.Split(chain, "=") + if len(parts) != 2 { + return nil, errors.Errorf("invalid format: '%s'", chain) + } + chainIDstr := parts[0] + rpcToContractAddress := strings.Split(parts[1], "|") + if len(rpcToContractAddress) != 2 { + return nil, errors.Errorf("invalid format: '%s'", parts[1]) + } + + _, err := url.ParseRequestURI(rpcToContractAddress[0]) + if err != nil { + return nil, errors.Errorf("invalid rpc url: '%s'", rpcToContractAddress[0]) + } + if common.HexToAddress(rpcToContractAddress[1]).Hex() == (common.Address{}).Hex() { + return nil, errors.Errorf("invalid contract address: '%s'", rpcToContractAddress[1]) + } + + chainID, err := strconv.Atoi(chainIDstr) + if err != nil { + return nil, errors.Errorf("invalid chain id: '%s'", chainIDstr) + } + //nolint:gosec // integer overflow is not possible here + blockchain, network, err := core.NetworkByChainID(core.ChainID(chainID)) + if err != nil { + return nil, errors.Errorf("invalid chain id: '%s'", chainIDstr) + } + + c := state.NewETHResolver(rpcToContractAddress[0], rpcToContractAddress[1]) + result[fmt.Sprintf("%s:%s", blockchain, network)] = c + } + if len(result) == 0 { + return nil, errors.New("no connection info found") + } + return result, nil +} + // NewVerifier returns setup instance of auth library func NewVerifier( keyLoader loaders.VerificationKeyLoader, @@ -239,7 +295,7 @@ func (v *Verifier) SetupAuthV2ZKPPacker() error { // SetupJWSPacker sets the JWS packer for the VerifierBuilder. func (v *Verifier) SetupJWSPacker(didResolver packers.DIDResolverHandlerFunc) error { - signerFnStub := packers.SignerResolverHandlerFunc(func(kid string) (crypto.Signer, error) { + signerFnStub := packers.SignerResolverHandlerFunc(func(_ string) (crypto.Signer, error) { return nil, nil }) jwsPacker := packers.NewJWSPacker(didResolver, signerFnStub) @@ -519,9 +575,9 @@ func verifyGroupIDMathch(linkID *big.Int, groupID int, requestID uint32, groupID // VerifyJWZ performs verification of jwz token func (v *Verifier) VerifyJWZ( - ctx context.Context, + _ context.Context, token string, - opts ...pubsignals.VerifyOpt, + _ ...pubsignals.VerifyOpt, ) (t *jwz.Token, err error) { _, _, err = v.packageManager.Unpack([]byte(token)) diff --git a/auth_test.go b/auth_test.go index 7699c14..bda75df 100644 --- a/auth_test.go +++ b/auth_test.go @@ -1225,3 +1225,75 @@ func TestFullVerifyLinkedProofsVerification(t *testing.T) { require.NotNil(t, returnMsg) schemaLoader.assert(t) } + +func TestParseConnectionString(t *testing.T) { + tests := []struct { + name string + input string + want map[string]pubsignals.StateResolver + wantErr bool + errMsg string + }{ + { + name: "Valid input", + input: "1=http://localhost:8545|0x1234567890abcdef1234567890abcdef12345678", + want: map[string]pubsignals.StateResolver{"eth:main": state.NewETHResolver("http://localhost:8545", "0x1234567890abcdef1234567890abcdef12345678")}, + wantErr: false, + }, + { + name: "Invalid format - missing =", + input: "1http://localhost:8545|0x1234567890abcdef1234567890abcdef12345678", + wantErr: true, + errMsg: "invalid format: '1http://localhost:8545|0x1234567890abcdef1234567890abcdef12345678'", + }, + { + name: "Invalid format - missing |", + input: "1=http://localhost:85450x1234567890abcdef1234567890abcdef12345678", + wantErr: true, + errMsg: "invalid format: 'http://localhost:85450x1234567890abcdef1234567890abcdef12345678'", + }, + { + name: "Invalid RPC URL", + input: "1=invalid_url|0x1234567890abcdef1234567890abcdef12345678", + wantErr: true, + errMsg: "invalid rpc url: 'invalid_url'", + }, + { + name: "Invalid contract address", + input: "1=http://localhost:8545|invalid_address", + wantErr: true, + errMsg: "invalid contract address: 'invalid_address'", + }, + { + name: "Invalid chain ID", + input: "invalid_chain_id=http://localhost:8545|0x1234567890abcdef1234567890abcdef12345678", + wantErr: true, + errMsg: "invalid chain id: 'invalid_chain_id'", + }, + { + name: "Unknown chain ID", + input: "9999=http://localhost:8545|0x1234567890abcdef1234567890abcdef12345678", + wantErr: true, + errMsg: "invalid chain id: '9999'", + }, + { + name: "Empty input", + input: "", + wantErr: true, + errMsg: "invalid format: ''", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ParseConnectionString(tt.input) + if tt.wantErr { + require.Error(t, err) + assert.Contains(t, err.Error(), tt.errMsg) + } else { + require.NoError(t, err) + assert.Equal(t, tt.want, got) + } + }) + } +} From 3f0a6896dbe33f579deff5afbbf4b51f198e3d20 Mon Sep 17 00:00:00 2001 From: ilya-korotya Date: Tue, 17 Sep 2024 15:46:37 +0200 Subject: [PATCH 3/3] rollback VerifyJWZ function --- auth.go | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/auth.go b/auth.go index 24e7460..35e4ac4 100644 --- a/auth.go +++ b/auth.go @@ -575,16 +575,34 @@ func verifyGroupIDMathch(linkID *big.Int, groupID int, requestID uint32, groupID // VerifyJWZ performs verification of jwz token func (v *Verifier) VerifyJWZ( - _ context.Context, + ctx context.Context, token string, - _ ...pubsignals.VerifyOpt, + opts ...pubsignals.VerifyOpt, ) (t *jwz.Token, err error) { - _, _, err = v.packageManager.Unpack([]byte(token)) + t, err = jwz.Parse(token) if err != nil { return nil, err } - t, err = jwz.Parse(token) + + verificationKey, err := v.verificationKeyLoader.Load(circuits.CircuitID(t.CircuitID)) + if err != nil { + return nil, errors.Errorf("verification key for circuit with id %s not found", t.CircuitID) + } + isValid, err := t.Verify(verificationKey) + if err != nil { + return nil, err + } + if !isValid { + return nil, errors.New("zero knowledge proof of jwz is not valid") + } + + circuitVerifier, err := getPublicSignalsVerifier(circuits.CircuitID(t.CircuitID), t.ZkProof.PubSignals) + if err != nil { + return nil, err + } + + err = circuitVerifier.VerifyStates(ctx, v.stateResolver, opts...) if err != nil { return nil, err }