diff --git a/mock/proving.go b/mock/proving.go index b6be26a..fe45c6e 100644 --- a/mock/proving.go +++ b/mock/proving.go @@ -82,11 +82,6 @@ func PrepareAuthInputs(hash []byte, _ *w3c.DID, _ circuits.CircuitID) ([]byte, e return j, err } -// VerifyState return no error always -func VerifyState(_ circuits.CircuitID, _ []string) error { - return nil -} - // MockRecipientKeyID is mocked key id for recipient const MockRecipientKeyID = "123456789" diff --git a/packager.go b/packager.go index 8b7765d..12c92f5 100644 --- a/packager.go +++ b/packager.go @@ -16,7 +16,7 @@ type Packer interface { // Pack a payload of type ContentType in an Iden3 compliant format using the packer identity Pack(payload []byte, params PackerParams) ([]byte, error) // Unpack an envelope in Iden3 compliant format. - Unpack(envelope []byte) (*BasicMessage, error) + Unpack(envelope []byte, params ...PackerParams) (*BasicMessage, error) // MediaType returns content type of message MediaType() MediaType } @@ -65,14 +65,14 @@ func (r *PackageManager) Pack(mediaType MediaType, payload []byte, params Packer // Unpack returns iden3 message method from envelope // if it's not valid or can't be decrypted error is returned -func (r *PackageManager) Unpack(envelope []byte) (*BasicMessage, MediaType, error) { +func (r *PackageManager) Unpack(envelope []byte, params ...PackerParams) (*BasicMessage, MediaType, error) { safeEnvelope := strings.Trim(strings.TrimSpace(string(envelope)), "\"") mediaType, err := r.GetMediaType([]byte(safeEnvelope)) if err != nil { return nil, "", err } - msg, err := r.unpackSafeEnvelope(mediaType, []byte(safeEnvelope)) + msg, err := r.unpackSafeEnvelope(mediaType, []byte(safeEnvelope), params...) if err != nil { return nil, mediaType, err } @@ -85,14 +85,14 @@ func (r *PackageManager) UnpackWithType(mediaType MediaType, envelope []byte) (* return r.unpackSafeEnvelope(mediaType, []byte(safeEnvelope)) } -func (r *PackageManager) unpackSafeEnvelope(mediaType MediaType, envelope []byte) (*BasicMessage, error) { +func (r *PackageManager) unpackSafeEnvelope(mediaType MediaType, envelope []byte, params ...PackerParams) (*BasicMessage, error) { p, ok := r.packers[mediaType] if !ok { return nil, errors.Errorf("packer for media type %s doesn't exist", mediaType) } // safeEnvelope can be rather base64 encoded or valid json - msg, err := p.Unpack(envelope) + msg, err := p.Unpack(envelope, params...) if err != nil { return nil, err } diff --git a/packager_test.go b/packager_test.go index b00adc9..13f8b95 100644 --- a/packager_test.go +++ b/packager_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/google/uuid" + "github.com/iden3/go-circuits/v2" "github.com/iden3/go-iden3-core/v2/w3c" "github.com/iden3/go-jwz/v2" "github.com/iden3/iden3comm/v2" @@ -182,7 +183,7 @@ func initPackageManager(t *testing.T) *iden3comm.PackageManager { mockVerificationParam := make(map[jwz.ProvingMethodAlg]packers.VerificationParams) mockVerificationParam[mockedProvingMethod.ProvingMethodAlg] = packers.NewVerificationParams([]byte(""), - mock.VerifyState) + verifyStateMock) mockProvingParamMap := make(map[jwz.ProvingMethodAlg]packers.ProvingParams) mockProvingParamMap[mockedProvingMethod.ProvingMethodAlg] = packers.NewProvingParams(mock.PrepareAuthInputs, @@ -193,3 +194,8 @@ func initPackageManager(t *testing.T) *iden3comm.PackageManager { return pm } + +// VerifyState return no error always +func verifyStateMock(_ circuits.CircuitID, _ []string, _ ...packers.ZKPPUnpackerParams) error { + return nil +} diff --git a/packers/anoncrypt.go b/packers/anoncrypt.go index f0fb353..df6cf56 100644 --- a/packers/anoncrypt.go +++ b/packers/anoncrypt.go @@ -65,7 +65,7 @@ func (p *AnoncryptPacker) Pack(payload []byte, params iden3comm.PackerParams) ([ } // Unpack returns unpacked message from transport envelope -func (p *AnoncryptPacker) Unpack(envelope []byte) (*iden3comm.BasicMessage, error) { +func (p *AnoncryptPacker) Unpack(envelope []byte, _ ...iden3comm.PackerParams) (*iden3comm.BasicMessage, error) { jwe, err := jose.ParseEncrypted(string(envelope)) if err != nil { diff --git a/packers/jws.go b/packers/jws.go index 0d271b9..ca1c698 100644 --- a/packers/jws.go +++ b/packers/jws.go @@ -200,7 +200,7 @@ func (p *JWSPacker) Pack( } // Unpack returns unpacked message from transport envelope with verification of signature -func (p *JWSPacker) Unpack(envelope []byte) (*iden3comm.BasicMessage, error) { +func (p *JWSPacker) Unpack(envelope []byte, _ ...iden3comm.PackerParams) (*iden3comm.BasicMessage, error) { token, err := jws.Parse(envelope) if err != nil { diff --git a/packers/plain.go b/packers/plain.go index 99eb589..10a4312 100644 --- a/packers/plain.go +++ b/packers/plain.go @@ -32,7 +32,7 @@ func (p *PlainMessagePacker) Pack(payload []byte, _ iden3comm.PackerParams) ([]b } // Unpack returns unpacked message from transport envelope -func (p *PlainMessagePacker) Unpack(envelope []byte) (*iden3comm.BasicMessage, error) { +func (p *PlainMessagePacker) Unpack(envelope []byte, _ ...iden3comm.PackerParams) (*iden3comm.BasicMessage, error) { var msg iden3comm.BasicMessage err := json.Unmarshal(envelope, &msg) diff --git a/packers/zkp.go b/packers/zkp.go index ec95640..4570932 100644 --- a/packers/zkp.go +++ b/packers/zkp.go @@ -30,11 +30,14 @@ func (f DataPreparerHandlerFunc) Prepare(hash []byte, id *w3c.DID, circuitID cir } // VerificationHandlerFunc registers the handler function for state verification. -type VerificationHandlerFunc func(id circuits.CircuitID, pubsignals []string) error +type VerificationHandlerFunc func(id circuits.CircuitID, pubsignals []string, opts ...ZKPPUnpackerParams) error // Verify function is responsible to call provided handler for outputs verification -func (f VerificationHandlerFunc) Verify(id circuits.CircuitID, pubsignals []string) error { - return f(id, pubsignals) +func (f VerificationHandlerFunc) Verify(id circuits.CircuitID, pubsignals []string, params ...ZKPPUnpackerParams) error { + if len(params) > 1 { + return errors.New("expecting no more than one parameter in VerificationHandlerFunc.Verify") + } + return f(id, pubsignals, params...) } // VerificationParams defined the verification function and the verification key for ZKP full verification @@ -133,14 +136,31 @@ func (p *ZKPPacker) Pack(payload []byte, params iden3comm.PackerParams) ([]byte, return []byte(tokenStr), nil } -// Unpack returns unpacked message from transport envelope with verification of zeroknowledge proof -func (p *ZKPPacker) Unpack(envelope []byte) (*iden3comm.BasicMessage, error) { +// ZKPPUnpackerParams is params for zkp unpacker +type ZKPPUnpackerParams struct { + authVerifyDelay time.Duration + iden3comm.PackerParams +} + +// NewZKPPUnpackerParams creates new zkp unpacker params +func NewZKPPUnpackerParams(authVerifyDelay time.Duration) ZKPPUnpackerParams { + return ZKPPUnpackerParams{ + authVerifyDelay: authVerifyDelay, + } +} + +// Unpack returns unpacked message from transport envelope with verification of zero knowledge proof +// params is variadic but only none or one is accepted +func (p *ZKPPacker) Unpack(envelope []byte, params ...iden3comm.PackerParams) (*iden3comm.BasicMessage, error) { + + if len(params) > 1 { + return nil, errors.New("expecting no more than one parameter in ZKPPacker Unpack") + } token, err := jwz.Parse(string(envelope)) if err != nil { return nil, err } - verificationKey, ok := p.Verification[jwz.ProvingMethodAlg{Alg: token.Alg, CircuitID: token.CircuitID}] if !ok { return nil, fmt.Errorf("message was packed with unsupported circuit `%s` and alg `%s`", token.CircuitID, @@ -155,7 +175,13 @@ func (p *ZKPPacker) Unpack(envelope []byte) (*iden3comm.BasicMessage, error) { return nil, errors.New("message proof is invalid") } - err = verificationKey.VerificationFn.Verify(circuits.CircuitID(token.CircuitID), token.ZkProof.PubSignals) + var zkParams []ZKPPUnpackerParams + for _, param := range params { + if zkpParam, ok := param.(ZKPPUnpackerParams); ok { + zkParams = append(zkParams, zkpParam) + } + } + err = verificationKey.VerificationFn.Verify(circuits.CircuitID(token.CircuitID), token.ZkProof.PubSignals, zkParams...) if err != nil { return nil, err } @@ -237,33 +263,21 @@ func (p *ZKPPacker) MediaType() iden3comm.MediaType { return MediaTypeZKPMessage } -// DefaultZKPUnpackerOption is a function that sets the default ZKP unpacker options -type DefaultZKPUnpackerOption func(*defaultZKPUnpacker) - -// WithAuthVerifyDelay sets the delay for the auth verification -func WithAuthVerifyDelay(delay time.Duration) DefaultZKPUnpackerOption { - return func(p *defaultZKPUnpacker) { - p.authVerifyDelay = delay - } -} - type defaultZKPUnpacker struct { - resolvers map[int]eth.Resolver - authVerifyDelay time.Duration + resolvers map[int]eth.Resolver } // DefaultZKPUnpacker creates a default ZKP unpacker with the provided verification key and resolvers -func DefaultZKPUnpacker(verificationKey []byte, resolvers map[int]eth.Resolver, opts ...DefaultZKPUnpackerOption) *ZKPPacker { - def := &defaultZKPUnpacker{resolvers, time.Minute * 5} - for _, opt := range opts { - opt(def) +func DefaultZKPUnpacker(verificationKey []byte, resolvers map[int]eth.Resolver) *ZKPPacker { + def := &defaultZKPUnpacker{ + resolvers: resolvers, } verifications := make(map[jwz.ProvingMethodAlg]VerificationParams) verifications[jwz.AuthV2Groth16Alg] = NewVerificationParams(verificationKey, def.defaultZkpUnpackerVerificationFn) return NewZKPPacker(nil, verifications) } -func (d *defaultZKPUnpacker) defaultZkpUnpackerVerificationFn(id circuits.CircuitID, pubsignals []string) error { +func (d *defaultZKPUnpacker) defaultZkpUnpackerVerificationFn(id circuits.CircuitID, pubsignals []string, opts ...ZKPPUnpackerParams) error { if id != circuits.AuthV2CircuitID { return errors.Errorf("circuit ID '%s' is not supported", id) } @@ -291,7 +305,10 @@ func (d *defaultZKPUnpacker) defaultZkpUnpackerVerificationFn(id circuits.Circui userDID.String(), err) } - resolver := d.resolvers[int(chainID)] + resolver, found := d.resolvers[int(chainID)] + if !found { + return errors.Errorf("resolver for chainID '%d' not found", chainID) + } globalState := authPubSignals.GISTRoot.BigInt() globalStateInfo, err := resolver.ResolveGist(context.Background(), &services.ResolverOpts{GistRoot: globalState}) @@ -305,8 +322,13 @@ func (d *defaultZKPUnpacker) defaultZkpUnpackerVerificationFn(id circuits.Circui globalState.String(), globalStateInfo.Root.String()) } + authVerifyDelay := time.Minute * 5 + if len(opts) > 0 { + authVerifyDelay = opts[0].authVerifyDelay + } + if (big.NewInt(0)).Cmp(globalStateInfo.ReplacedByRoot) != 0 && - time.Since(time.Unix(globalStateInfo.ReplacedAtTimestamp.Int64(), 0)) > d.authVerifyDelay { + time.Since(time.Unix(globalStateInfo.ReplacedAtTimestamp.Int64(), 0)) > authVerifyDelay { return errors.Errorf("global state is too old, replaced timestamp is %v", globalStateInfo.ReplacedAtTimestamp.Int64()) } diff --git a/packers/zkp_test.go b/packers/zkp_test.go index dbe39f7..cf3faf7 100644 --- a/packers/zkp_test.go +++ b/packers/zkp_test.go @@ -28,7 +28,7 @@ func TestZKPPacker_Pack(t *testing.T) { }) mockVerificationParam := make(map[jwz.ProvingMethodAlg]VerificationParams) - mockVerificationParam[mockedProvingMethod.ProvingMethodAlg] = NewVerificationParams([]byte(""), mock.VerifyState) + mockVerificationParam[mockedProvingMethod.ProvingMethodAlg] = NewVerificationParams([]byte(""), verifyStateMock) mockProvingParamMap := make(map[jwz.ProvingMethodAlg]ProvingParams) mockProvingParamMap[mockedProvingMethod.ProvingMethodAlg] = @@ -77,7 +77,7 @@ func TestPlainMessagePacker_Unpack(t *testing.T) { }) mockVerificationParam := make(map[jwz.ProvingMethodAlg]VerificationParams) - mockVerificationParam[mockedProvingMethod.ProvingMethodAlg] = NewVerificationParams([]byte(""), mock.VerifyState) + mockVerificationParam[mockedProvingMethod.ProvingMethodAlg] = NewVerificationParams([]byte(""), verifyStateMock) mockProvingParamMap := make(map[jwz.ProvingMethodAlg]ProvingParams) mockProvingParamMap[mockedProvingMethod.ProvingMethodAlg] = @@ -101,3 +101,7 @@ func TestPlainMessagePacker_Unpack(t *testing.T) { assert.Len(t, authResponse.Body.Scope, 0) } + +func verifyStateMock(_ circuits.CircuitID, _ []string, _ ...ZKPPUnpackerParams) error { + return nil +}