From 7488e6080c4fa2064fbd464af8d4e96924b2abc1 Mon Sep 17 00:00:00 2001 From: Viktor Nosov Date: Thu, 19 Jan 2023 17:48:04 +0300 Subject: [PATCH 1/4] rename token.Store interface to token.BalanceStore Signed-off-by: Viktor Nosov --- examples/erc20_utxo/service/allowance/allowance.go | 4 ++-- extensions/token/balance.go | 4 ++-- extensions/token/balance_account.go | 2 +- extensions/token/balance_store.go | 2 +- extensions/token/balance_utxo.go | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/erc20_utxo/service/allowance/allowance.go b/examples/erc20_utxo/service/allowance/allowance.go index ca62b6b..af50990 100644 --- a/examples/erc20_utxo/service/allowance/allowance.go +++ b/examples/erc20_utxo/service/allowance/allowance.go @@ -16,11 +16,11 @@ var ( ) type Service struct { - balance token.Store + balance token.BalanceStore account account.Getter } -func NewService(account account.Getter, balance token.Store) *Service { +func NewService(account account.Getter, balance token.BalanceStore) *Service { return &Service{ account: account, balance: balance, diff --git a/extensions/token/balance.go b/extensions/token/balance.go index 0c99bac..700ab62 100644 --- a/extensions/token/balance.go +++ b/extensions/token/balance.go @@ -10,13 +10,13 @@ import ( type BalanceService struct { Account account.Getter Token TokenGetter - Store Store + Store BalanceStore } func NewBalanceService( accountResolver account.Getter, tokenGetter TokenGetter, - store Store) *BalanceService { + store BalanceStore) *BalanceService { return &BalanceService{ Account: accountResolver, diff --git a/extensions/token/balance_account.go b/extensions/token/balance_account.go index 7e66a30..d087daf 100644 --- a/extensions/token/balance_account.go +++ b/extensions/token/balance_account.go @@ -9,7 +9,7 @@ import ( "github.com/hyperledger-labs/cckit/state" ) -var _ Store = &AccountStore{} +var _ BalanceStore = &AccountStore{} type AccountStore struct { } diff --git a/extensions/token/balance_store.go b/extensions/token/balance_store.go index 91ddc07..28fffd4 100644 --- a/extensions/token/balance_store.go +++ b/extensions/token/balance_store.go @@ -12,7 +12,7 @@ type ( TxId string } - Store interface { + BalanceStore interface { Get(router.Context, *BalanceId) (*Balance, error) GetLocked(router.Context, *BalanceId) (*Balance, error) List(router.Context, *TokenId) ([]*Balance, error) diff --git a/extensions/token/balance_utxo.go b/extensions/token/balance_utxo.go index 748eeef..748fc84 100644 --- a/extensions/token/balance_utxo.go +++ b/extensions/token/balance_utxo.go @@ -9,7 +9,7 @@ import ( "github.com/hyperledger-labs/cckit/state" ) -var _ Store = &UTXOStore{} +var _ BalanceStore = &UTXOStore{} var ( ErrSenderRecipientEqual = errors.New(`sender recipient equal`) From 1a6b6d837d153300aee3addb7f0d73b4dc15c986 Mon Sep 17 00:00:00 2001 From: Viktor Nosov Date: Sun, 15 Oct 2023 12:56:13 +0300 Subject: [PATCH 2/4] label extesion Signed-off-by: Viktor Nosov --- extensions/label/label.go | 57 ++++++++++++++++++++++++++++++++++++ extensions/label/label.proto | 18 ++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 extensions/label/label.go create mode 100644 extensions/label/label.proto diff --git a/extensions/label/label.go b/extensions/label/label.go new file mode 100644 index 0000000..4a7475b --- /dev/null +++ b/extensions/label/label.go @@ -0,0 +1,57 @@ +package label + +func BlankMetadata() *Metadata { + return &Metadata{ + Labels: []*Label{}, + } +} + +func (m *Metadata) MatchLabel(expectLabel *Label) bool { + for _, l := range m.GetLabels() { + if l.Value == expectLabel.Value && l.Key == expectLabel.Key { + return true + } + } + return false +} + +func (m *Metadata) GetLabelByKey(key string) *Label { + for _, l := range m.GetLabels() { + if l.Key == key { + return l + } + } + return nil +} + +func (m *Metadata) GetLabelsByKey(key string) []*Label { + var labels []*Label + for _, l := range m.GetLabels() { + if l.Key == key { + labels = append(labels, l) + } + } + return labels +} + +func (m *Metadata) RemoveLabel(expectLabel *Label) bool { + var ( + i int + l *Label + ) + for i, l = range m.GetLabels() { + if l.Key == expectLabel.Key && l.Value == expectLabel.Value { + break + } + } + m.Labels = append(m.Labels[i:], m.Labels[i+1:]...) + return false +} + +func (m *Metadata) AddLabel(newLabel *Label) error { + if err := newLabel.Validate(); err != nil { + return err + } + m.Labels = append(m.Labels, newLabel) + return nil +} diff --git a/extensions/label/label.proto b/extensions/label/label.proto new file mode 100644 index 0000000..58c5dc7 --- /dev/null +++ b/extensions/label/label.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package extensions.label; + +option go_package = "github.com/hyperledger-labs/cckit/extensions/label"; + +import "mwitkow/go-proto-validators/validator.proto"; + +// label - container for name/value content +message Label { + string key = 1 [(validator.field) = {length_gt: 1}]; + string value = 2 [(validator.field) = {length_gt: 1}]; +} + +// Metadata - type for integrate to other objects +message Metadata { + repeated Label labels = 1; +} \ No newline at end of file From 56fa9e29d3fa139dbe6795253a6628f7199ef90f Mon Sep 17 00:00:00 2001 From: Viktor Nosov Date: Sun, 15 Oct 2023 12:58:02 +0300 Subject: [PATCH 3/4] label extesion Signed-off-by: Viktor Nosov --- extensions/label/label.pb.go | 225 +++++++++++++++++++++++++ extensions/label/label.swagger.json | 49 ++++++ extensions/label/label.validator.pb.go | 37 ++++ 3 files changed, 311 insertions(+) create mode 100644 extensions/label/label.pb.go create mode 100644 extensions/label/label.swagger.json create mode 100644 extensions/label/label.validator.pb.go diff --git a/extensions/label/label.pb.go b/extensions/label/label.pb.go new file mode 100644 index 0000000..3470345 --- /dev/null +++ b/extensions/label/label.pb.go @@ -0,0 +1,225 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc (unknown) +// source: label/label.proto + +package label + +import ( + _ "github.com/mwitkow/go-proto-validators" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// label - container for name/value content +type Label struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *Label) Reset() { + *x = Label{} + if protoimpl.UnsafeEnabled { + mi := &file_label_label_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Label) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Label) ProtoMessage() {} + +func (x *Label) ProtoReflect() protoreflect.Message { + mi := &file_label_label_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Label.ProtoReflect.Descriptor instead. +func (*Label) Descriptor() ([]byte, []int) { + return file_label_label_proto_rawDescGZIP(), []int{0} +} + +func (x *Label) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *Label) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +// Metadata - type for integrate to other objects +type Metadata struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Labels []*Label `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty"` +} + +func (x *Metadata) Reset() { + *x = Metadata{} + if protoimpl.UnsafeEnabled { + mi := &file_label_label_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Metadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Metadata) ProtoMessage() {} + +func (x *Metadata) ProtoReflect() protoreflect.Message { + mi := &file_label_label_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Metadata.ProtoReflect.Descriptor instead. +func (*Metadata) Descriptor() ([]byte, []int) { + return file_label_label_proto_rawDescGZIP(), []int{1} +} + +func (x *Metadata) GetLabels() []*Label { + if x != nil { + return x.Labels + } + return nil +} + +var File_label_label_proto protoreflect.FileDescriptor + +var file_label_label_proto_rawDesc = []byte{ + 0x0a, 0x11, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x1a, 0x2b, 0x6d, 0x77, 0x69, 0x74, 0x6b, 0x6f, 0x77, 0x2f, 0x67, + 0x6f, 0x2d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0x3f, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xe2, 0xdf, 0x1f, 0x02, 0x70, 0x01, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xe2, 0xdf, 0x1f, 0x02, 0x70, 0x01, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x22, 0x3b, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, + 0x2f, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, + 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, + 0x79, 0x70, 0x65, 0x72, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, + 0x63, 0x63, 0x6b, 0x69, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x2f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_label_label_proto_rawDescOnce sync.Once + file_label_label_proto_rawDescData = file_label_label_proto_rawDesc +) + +func file_label_label_proto_rawDescGZIP() []byte { + file_label_label_proto_rawDescOnce.Do(func() { + file_label_label_proto_rawDescData = protoimpl.X.CompressGZIP(file_label_label_proto_rawDescData) + }) + return file_label_label_proto_rawDescData +} + +var file_label_label_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_label_label_proto_goTypes = []interface{}{ + (*Label)(nil), // 0: extensions.label.Label + (*Metadata)(nil), // 1: extensions.label.Metadata +} +var file_label_label_proto_depIdxs = []int32{ + 0, // 0: extensions.label.Metadata.labels:type_name -> extensions.label.Label + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_label_label_proto_init() } +func file_label_label_proto_init() { + if File_label_label_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_label_label_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Label); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_label_label_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Metadata); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_label_label_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_label_label_proto_goTypes, + DependencyIndexes: file_label_label_proto_depIdxs, + MessageInfos: file_label_label_proto_msgTypes, + }.Build() + File_label_label_proto = out.File + file_label_label_proto_rawDesc = nil + file_label_label_proto_goTypes = nil + file_label_label_proto_depIdxs = nil +} diff --git a/extensions/label/label.swagger.json b/extensions/label/label.swagger.json new file mode 100644 index 0000000..576f9b3 --- /dev/null +++ b/extensions/label/label.swagger.json @@ -0,0 +1,49 @@ +{ + "swagger": "2.0", + "info": { + "title": "label/label.proto", + "version": "version not set" + }, + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": {}, + "definitions": { + "protobufAny": { + "type": "object", + "properties": { + "type_url": { + "type": "string" + }, + "value": { + "type": "string", + "format": "byte" + } + } + }, + "runtimeError": { + "type": "object", + "properties": { + "error": { + "type": "string" + }, + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "$ref": "#/definitions/protobufAny" + } + } + } + } + } +} diff --git a/extensions/label/label.validator.pb.go b/extensions/label/label.validator.pb.go new file mode 100644 index 0000000..f81e19b --- /dev/null +++ b/extensions/label/label.validator.pb.go @@ -0,0 +1,37 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: label/label.proto + +package label + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + _ "github.com/mwitkow/go-proto-validators" + github_com_mwitkow_go_proto_validators "github.com/mwitkow/go-proto-validators" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +func (this *Label) Validate() error { + if !(len(this.Key) > 1) { + return github_com_mwitkow_go_proto_validators.FieldError("Key", fmt.Errorf(`value '%v' must have a length greater than '1'`, this.Key)) + } + if !(len(this.Value) > 1) { + return github_com_mwitkow_go_proto_validators.FieldError("Value", fmt.Errorf(`value '%v' must have a length greater than '1'`, this.Value)) + } + return nil +} +func (this *Metadata) Validate() error { + for _, item := range this.Labels { + if item != nil { + if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil { + return github_com_mwitkow_go_proto_validators.FieldError("Labels", err) + } + } + } + return nil +} From 9cc17a8a743382c08cc414677a995a24480d3e17 Mon Sep 17 00:00:00 2001 From: Viktor Nosov Date: Mon, 24 Jun 2024 12:48:35 +0300 Subject: [PATCH 4/4] crypto/signer abstractions Signed-off-by: Viktor Nosov --- extensions/envelope/crypto.go | 52 +++++++++++++++ extensions/envelope/envelope.pb.go | 28 +++++--- extensions/envelope/envelope.proto | 1 + extensions/envelope/envelope_test.go | 74 +++++++++++---------- extensions/envelope/middleware.go | 45 +++++++------ extensions/envelope/signature.go | 56 ---------------- extensions/envelope/signer.go | 59 ++++++++++++++++ extensions/envelope/testdata/cc_envelope.go | 4 +- 8 files changed, 195 insertions(+), 124 deletions(-) create mode 100644 extensions/envelope/crypto.go delete mode 100644 extensions/envelope/signature.go create mode 100644 extensions/envelope/signer.go diff --git a/extensions/envelope/crypto.go b/extensions/envelope/crypto.go new file mode 100644 index 0000000..d485634 --- /dev/null +++ b/extensions/envelope/crypto.go @@ -0,0 +1,52 @@ +package envelope + +import ( + "crypto/ed25519" + "crypto/rand" + "crypto/sha256" + "fmt" +) + +type Crypto interface { + GenerateKey() (publicKey, privateKey []byte, err error) + Hash([]byte) []byte + Sign(hash, privateKey []byte) ([]byte, error) + Verify([]byte) bool + PublicKey(privateKey []byte) ([]byte, error) +} + +func NewEd25519() *Ed25519 { + return &Ed25519{} +} + +type Ed25519 struct{} + +func (ed *Ed25519) GenerateKey() (publicKey, privateKey []byte, err error) { + publicKey, privateKey, err = ed25519.GenerateKey(rand.Reader) + if err != nil { + return nil, nil, err + } + return publicKey, privateKey, nil +} + +func (ed *Ed25519) Sign(hash, privateKey []byte) (signature []byte, err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("sign: %v", r) + } + }() + return ed25519.Sign(privateKey, hash), nil +} + +func (ed *Ed25519) Hash(msg []byte) []byte { + h := sha256.Sum256(msg) + return h[:] +} + +func (ed *Ed25519) Verify([]byte) bool { + return false +} + +func (ed *Ed25519) PublicKey(privateKey []byte) ([]byte, error) { + return ed25519.PrivateKey(privateKey).Public().(ed25519.PublicKey), nil +} diff --git a/extensions/envelope/envelope.pb.go b/extensions/envelope/envelope.pb.go index b8551cd..837a5fc 100644 --- a/extensions/envelope/envelope.pb.go +++ b/extensions/envelope/envelope.pb.go @@ -35,9 +35,10 @@ type Envelope struct { HashFunc string `protobuf:"bytes,5,opt,name=hash_func,json=hashFunc,proto3" json:"hash_func,omitempty"` // function used for hashing Deadline *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=deadline,proto3" json:"deadline,omitempty"` // signature is not valid after deadline (EIP-2612) // channel + chaincode + method are used as domain separator to prevent replay attack from other domains (EIP-2612) - Channel string `protobuf:"bytes,7,opt,name=channel,proto3" json:"channel,omitempty"` - Chaincode string `protobuf:"bytes,8,opt,name=chaincode,proto3" json:"chaincode,omitempty"` - Method string `protobuf:"bytes,9,opt,name=method,proto3" json:"method,omitempty"` + Channel string `protobuf:"bytes,7,opt,name=channel,proto3" json:"channel,omitempty"` + Chaincode string `protobuf:"bytes,8,opt,name=chaincode,proto3" json:"chaincode,omitempty"` + Method string `protobuf:"bytes,9,opt,name=method,proto3" json:"method,omitempty"` + SignatureAlg string `protobuf:"bytes,10,opt,name=signature_alg,json=signatureAlg,proto3" json:"signature_alg,omitempty"` } func (x *Envelope) Reset() { @@ -135,6 +136,13 @@ func (x *Envelope) GetMethod() string { return "" } +func (x *Envelope) GetSignatureAlg() string { + if x != nil { + return x.SignatureAlg + } + return "" +} + var File_envelope_envelope_proto protoreflect.FileDescriptor var file_envelope_envelope_proto_rawDesc = []byte{ @@ -146,7 +154,7 @@ var file_envelope_envelope_proto_rawDesc = []byte{ 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xa4, 0x02, 0x0a, 0x08, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, + 0xc9, 0x02, 0x0a, 0x08, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, @@ -164,11 +172,13 @@ var file_envelope_envelope_proto_rawDesc = []byte{ 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x79, 0x70, 0x65, 0x72, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, - 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x63, 0x63, 0x6b, 0x69, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, - 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x5f, 0x61, 0x6c, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x41, 0x6c, 0x67, 0x42, 0x37, 0x5a, 0x35, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x79, 0x70, 0x65, 0x72, 0x6c, + 0x65, 0x64, 0x67, 0x65, 0x72, 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x63, 0x63, 0x6b, 0x69, 0x74, + 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x65, 0x6e, 0x76, 0x65, + 0x6c, 0x6f, 0x70, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/extensions/envelope/envelope.proto b/extensions/envelope/envelope.proto index c0a8cc3..382d6a2 100644 --- a/extensions/envelope/envelope.proto +++ b/extensions/envelope/envelope.proto @@ -18,4 +18,5 @@ message Envelope { string channel = 7; string chaincode = 8; string method = 9; + string signature_alg = 10; } \ No newline at end of file diff --git a/extensions/envelope/envelope_test.go b/extensions/envelope/envelope_test.go index 43d11f7..0368e1f 100644 --- a/extensions/envelope/envelope_test.go +++ b/extensions/envelope/envelope_test.go @@ -10,7 +10,7 @@ import ( "github.com/btcsuite/btcutil/base58" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" + "google.golang.org/protobuf/types/known/timestamppb" e "github.com/hyperledger-labs/cckit/extensions/envelope" "github.com/hyperledger-labs/cckit/extensions/envelope/testdata" @@ -38,12 +38,15 @@ var ( payload = []byte(`{"symbol":"GLD","decimals":"8","name":"Gold digital asset","type":"DM","underlying_asset":"gold","issuer_id":"GLDINC"}`) ) -var _ = Describe(`Envelop`, func() { +var _ = Describe(`Envelop with Ed25519`, func() { + + ed25519 := e.NewEd25519() + signer := e.NewSigner(ed25519) Describe("Signature methods", func() { It("Allow to create keys", func() { - publicKey, privateKey, err := e.CreateKeys() + publicKey, privateKey, err := ed25519.GenerateKey() Expect(err).NotTo(HaveOccurred()) Expect(len(publicKey)).To(Equal(32)) Expect(len(privateKey)).To(Equal(64)) @@ -59,34 +62,35 @@ var _ = Describe(`Envelop`, func() { }) It("Allow to create signature", func() { - _, privateKey, _ := e.CreateKeys() - _, sig := e.CreateSig(payload, e.CreateNonce(), channel, chaincode, methodInvoke, deadline.String(), privateKey) + _, privateKey, _ := ed25519.GenerateKey() + sig, err := signer.Sign(payload, e.CreateNonce(), channel, chaincode, methodInvoke, deadline.String(), privateKey) + Expect(err).NotTo(HaveOccurred()) Expect(len(sig)).To(Equal(64)) }) It("Allow to check valid signature", func() { nonce := e.CreateNonce() - publicKey, privateKey, _ := e.CreateKeys() - _, sig := e.CreateSig(payload, nonce, channel, chaincode, methodInvoke, deadline.String(), privateKey) - err := e.CheckSig(payload, nonce, channel, chaincode, methodInvoke, deadline.String(), publicKey, sig) + publicKey, privateKey, _ := ed25519.GenerateKey() + sig, err := signer.Sign(payload, nonce, channel, chaincode, methodInvoke, deadline.String(), privateKey) + Expect(err).NotTo(HaveOccurred()) + err = signer.CheckSignature(payload, nonce, channel, chaincode, methodInvoke, deadline.String(), publicKey, sig) Expect(err).NotTo(HaveOccurred()) }) It("Disallow to check signature with invalid payload", func() { nonce := e.CreateNonce() - publicKey, privateKey, _ := e.CreateKeys() - _, sig := e.CreateSig(payload, nonce, channel, chaincode, methodInvoke, deadline.String(), privateKey) + publicKey, privateKey, _ := ed25519.GenerateKey() + sig, _ := signer.Sign(payload, nonce, channel, chaincode, methodInvoke, deadline.String(), privateKey) invalidPayload := []byte("invalid payload") - err := e.CheckSig(invalidPayload, nonce, channel, chaincode, methodInvoke, deadline.String(), publicKey, sig) + err := signer.CheckSignature(invalidPayload, nonce, channel, chaincode, methodInvoke, deadline.String(), publicKey, sig) Expect(err).Should(MatchError(e.ErrSignatureCheckFailed)) }) - }) Describe("Handle base64 envelop", func() { It("Allow to parse base64 envelop", func() { - _, envelope := createEnvelope(payload, channel, chaincode, methodInvoke, deadline) + _, envelope := createEnvelope(signer, payload, channel, chaincode, methodInvoke, deadline) jj, _ := json.Marshal(envelope) b64 := base64.StdEncoding.EncodeToString(jj) bb, err := e.DecodeEnvelope([]byte(b64)) @@ -99,18 +103,18 @@ var _ = Describe(`Envelop`, func() { Describe("Signature verification", func() { It("Allow to verify valid signature", func() { - serializedEnvelope, _ := createEnvelope(payload, channel, chaincode, methodInvoke, deadline) + serializedEnvelope, _ := createEnvelope(signer, payload, channel, chaincode, methodInvoke, deadline) - envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(chaincode)).WithChannel(channel) + envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(signer, chaincode)).WithChannel(channel) resp := envelopCC.Invoke(methodInvoke, payload, serializedEnvelope) Expect(resp.Status).To(BeNumerically("==", 200)) }) It("Allow to verify valid signature without deadline", func() { - serializedEnvelope, _ := createEnvelope(payload, channel, chaincode, methodInvoke) + serializedEnvelope, _ := createEnvelope(signer, payload, channel, chaincode, methodInvoke) - envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(chaincode)).WithChannel(channel) + envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(signer, chaincode)).WithChannel(channel) resp := envelopCC.Invoke(methodInvoke, payload, serializedEnvelope) Expect(resp.Status).To(BeNumerically("==", 200)) @@ -122,7 +126,7 @@ var _ = Describe(`Envelop`, func() { decodedEnvelope, err := e.DecodeEnvelope([]byte(b64Envelope)) Expect(err).NotTo(HaveOccurred()) - envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(chaincode)).WithChannel(channel) + envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(signer, chaincode)).WithChannel(channel) resp := envelopCC.Invoke(methodInvoke, payload, decodedEnvelope) Expect(resp.Status).To(BeNumerically("==", 200)) @@ -134,16 +138,16 @@ var _ = Describe(`Envelop`, func() { decodedEnvelope, err := e.DecodeEnvelope([]byte(b64Envelope)) Expect(err).NotTo(HaveOccurred()) - envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(chaincode)).WithChannel(channel) + envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(signer, chaincode)).WithChannel(channel) resp := envelopCC.Invoke(methodInvoke, payload, decodedEnvelope) Expect(resp.Status).To(BeNumerically("==", 200)) }) It("Disallow to verify signature with invalid payload", func() { - serializedEnvelope, _ := createEnvelope(payload, channel, chaincode, methodInvoke, deadline) + serializedEnvelope, _ := createEnvelope(signer, payload, channel, chaincode, methodInvoke, deadline) - envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(chaincode)).WithChannel(channel) + envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(signer, chaincode)).WithChannel(channel) invalidPayload := []byte("invalid payload") resp := envelopCC.Invoke(methodInvoke, invalidPayload, serializedEnvelope) @@ -151,25 +155,25 @@ var _ = Describe(`Envelop`, func() { }) It("Disallow to verify signature with invalid method", func() { - serializedEnvelope, _ := createEnvelope(payload, channel, chaincode, "invalid method", deadline) + serializedEnvelope, _ := createEnvelope(signer, payload, channel, chaincode, "invalid method", deadline) - envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(chaincode)).WithChannel(channel) + envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(signer, chaincode)).WithChannel(channel) resp := envelopCC.Invoke(methodInvoke, payload, serializedEnvelope) Expect(resp.Status).To(BeNumerically("==", 500)) }) It("Disallow to verify signature with invalid channel", func() { - serializedEnvelope, _ := createEnvelope(payload, "invalid channel", chaincode, methodInvoke, deadline) + serializedEnvelope, _ := createEnvelope(signer, payload, "invalid channel", chaincode, methodInvoke, deadline) - envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(chaincode)).WithChannel(channel) + envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(signer, chaincode)).WithChannel(channel) resp := envelopCC.Invoke(methodInvoke, payload, serializedEnvelope) Expect(resp.Status).To(BeNumerically("==", 500)) }) It("Don't check signature for query method", func() { - envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(chaincode)).WithChannel(channel) + envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(signer, chaincode)).WithChannel(channel) resp := envelopCC.Query(methodQuery, payload) Expect(resp.Status).To(BeNumerically("==", 200)) @@ -179,12 +183,12 @@ var _ = Describe(`Envelop`, func() { Describe("Nonce verification (replay attack)", func() { It("Disallow to execute tx with the same parameters (nonce, payload, pubkey)", func() { - envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(chaincode)).WithChannel(channel) + envelopCC = testcc.NewMockStub(chaincode, testdata.NewEnvelopCC(signer, chaincode)).WithChannel(channel) - publicKey, privateKey, _ := e.CreateKeys() + publicKey, privateKey, _ := ed25519.GenerateKey() nonce := "thesamenonce" - hashToSign := e.Hash(payload, nonce, channel, chaincode, methodInvoke, deadline.AsTime().Format(e.TimeLayout), []byte(publicKey)) - _, sig := e.CreateSig(payload, nonce, channel, chaincode, methodInvoke, deadline.AsTime().Format(e.TimeLayout), privateKey) + hashToSign := signer.Hash(payload, nonce, channel, chaincode, methodInvoke, deadline.AsTime().Format(e.TimeLayout), publicKey) + sig, _ := signer.Sign(payload, nonce, channel, chaincode, methodInvoke, deadline.AsTime().Format(e.TimeLayout), privateKey) envelope := &e.Envelope{ PublicKey: base58.Encode([]byte(publicKey)), Signature: base58.Encode(sig), @@ -209,8 +213,8 @@ var _ = Describe(`Envelop`, func() { }) -func createEnvelope(payload []byte, channel, chaincode, method string, deadline ...*timestamppb.Timestamp) ([]byte, *e.Envelope) { - publicKey, privateKey, _ := e.CreateKeys() +func createEnvelope(signer *e.Signer, payload []byte, channel, chaincode, method string, deadline ...*timestamppb.Timestamp) ([]byte, *e.Envelope) { + publicKey, privateKey, _ := e.NewEd25519().GenerateKey() nonce := e.CreateNonce() envelope := &e.Envelope{ @@ -226,10 +230,10 @@ func createEnvelope(payload []byte, channel, chaincode, method string, deadline envelope.Deadline = deadline[0] formatDeadline = envelope.Deadline.AsTime().Format(e.TimeLayout) } - hashToSign := e.Hash(payload, nonce, channel, chaincode, method, formatDeadline, publicKey) - envelope.HashToSign = base58.Encode(hashToSign[:]) + hashToSign := signer.Hash(payload, nonce, channel, chaincode, method, formatDeadline, publicKey) + envelope.HashToSign = base58.Encode(hashToSign) - _, sig := e.CreateSig(payload, nonce, channel, chaincode, method, formatDeadline, privateKey) + sig, _ := signer.Sign(payload, nonce, channel, chaincode, method, formatDeadline, privateKey) envelope.Signature = base58.Encode(sig) serializedEnvelope, _ := serialize.PreferJSONSerializer.ToBytesFrom(envelope) diff --git a/extensions/envelope/middleware.go b/extensions/envelope/middleware.go index ba2d392..fdeada7 100644 --- a/extensions/envelope/middleware.go +++ b/extensions/envelope/middleware.go @@ -6,8 +6,9 @@ import ( "time" "github.com/btcsuite/btcutil/base58" - "github.com/hyperledger-labs/cckit/router" "go.uber.org/zap" + + "github.com/hyperledger-labs/cckit/router" ) const ( @@ -26,68 +27,68 @@ const ( ) // Verify is a middleware for checking signature in envelop -func Verify() router.MiddlewareFunc { +func Verify(signer *Signer) router.MiddlewareFunc { return func(next router.HandlerFunc, pos ...int) router.HandlerFunc { - return func(c router.Context) (interface{}, error) { - if c.Handler().Type == invokeType { - iArgs := c.GetArgs() + return func(ctx router.Context) (interface{}, error) { + if ctx.Handler().Type == invokeType { + iArgs := ctx.GetArgs() if string(iArgs[methodNamePos]) != initType { if len(iArgs) == 2 { - c.Logger().Sugar().Error(ErrSignatureNotFound) + ctx.Logger().Sugar().Error(ErrSignatureNotFound) return nil, ErrSignatureNotFound } else { var ( e *Envelope err error ) - if e, err = verifyEnvelope(c, iArgs[methodNamePos], iArgs[payloadPos], iArgs[envelopePos]); err != nil { + if e, err = verifyEnvelope(ctx, signer, iArgs[methodNamePos], iArgs[payloadPos], iArgs[envelopePos]); err != nil { return nil, err } // store correct pubkey in context - c.SetParam(PubKey, e.PublicKey) + ctx.SetParam(PubKey, e.PublicKey) } } } - return next(c) + return next(ctx) } } } -func verifyEnvelope(c router.Context, method, payload, envlp []byte) (*Envelope, error) { +func verifyEnvelope(ctx router.Context, signer *Signer, method, payload, envlp []byte) (*Envelope, error) { // parse json envelope format (json is original format for envelope from frontend) - data, err := c.Serializer().FromBytesTo(envlp, &Envelope{}) + data, err := ctx.Serializer().FromBytesTo(envlp, &Envelope{}) if err != nil { - c.Logger().Error(`convert from bytes failed:`, zap.Error(err)) + ctx.Logger().Error(`convert from bytes failed:`, zap.Error(err)) return nil, err } envelope := data.(*Envelope) if envelope.Deadline.AsTime().Unix() != 0 { if envelope.Deadline.AsTime().Unix() < time.Now().Unix() { - c.Logger().Sugar().Error(ErrDeadlineExpired) + ctx.Logger().Sugar().Error(ErrDeadlineExpired) return nil, ErrDeadlineExpired } } // check method and channel names because envelope can only be used once for channel+chaincode+method combination if string(method) != envelope.Method { - c.Logger().Sugar().Error(ErrInvalidMethod) + ctx.Logger().Sugar().Error(ErrInvalidMethod) return nil, ErrInvalidMethod } - if c.Stub().GetChannelID() != envelope.Channel { - c.Logger().Sugar().Error(ErrInvalidChannel) + if ctx.Stub().GetChannelID() != envelope.Channel { + ctx.Logger().Sugar().Error(ErrInvalidChannel) return nil, ErrInvalidChannel } // replay attack check txHash := txNonceKey(payload, envelope.Nonce, envelope.Channel, envelope.Chaincode, envelope.Method, envelope.PublicKey) - key, err := c.Stub().CreateCompositeKey(nonceObjectType, []string{txHash}) + key, err := ctx.Stub().CreateCompositeKey(nonceObjectType, []string{txHash}) if err != nil { return nil, err } - bb, err := c.Stub().GetState(key) + bb, err := ctx.Stub().GetState(key) if bb == nil && err == nil { - if err := c.Stub().PutState(key, []byte{'0'}); err != nil { + if err := ctx.Stub().PutState(key, []byte{'0'}); err != nil { return nil, err } // convert public key and sig from base58 @@ -98,13 +99,13 @@ func verifyEnvelope(c router.Context, method, payload, envlp []byte) (*Envelope, if envelope.Deadline != nil { deadline = envelope.Deadline.AsTime().Format(TimeLayout) } - if err := CheckSig(payload, envelope.Nonce, envelope.Channel, envelope.Chaincode, envelope.Method, deadline, pubkey, sig); err != nil { - c.Logger().Error(ErrCheckSignatureFailed.Error(), zap.String("payload", string(payload)), zap.Any("envelope", envelope)) + if err := signer.CheckSignature(payload, envelope.Nonce, envelope.Channel, envelope.Chaincode, envelope.Method, deadline, pubkey, sig); err != nil { + ctx.Logger().Error(ErrCheckSignatureFailed.Error(), zap.String("payload", string(payload)), zap.Any("envelope", envelope)) //c.Logger().Sugar().Error(ErrCheckSignatureFailed) return nil, ErrCheckSignatureFailed } } else { - c.Logger().Sugar().Error(ErrTxAlreadyExecuted) + ctx.Logger().Sugar().Error(ErrTxAlreadyExecuted) return nil, ErrTxAlreadyExecuted } return envelope, nil diff --git a/extensions/envelope/signature.go b/extensions/envelope/signature.go deleted file mode 100644 index 4a9312a..0000000 --- a/extensions/envelope/signature.go +++ /dev/null @@ -1,56 +0,0 @@ -package envelope - -import ( - "crypto/ed25519" - "crypto/rand" - "crypto/sha256" - "strconv" - "strings" - "time" - - "github.com/btcsuite/btcutil/base58" -) - -func CreateKeys() (ed25519.PublicKey, ed25519.PrivateKey, error) { - publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader) - if err != nil { - return nil, nil, err - } - return publicKey, privateKey, nil -} - -func CreateNonce() string { - return strconv.Itoa(int(time.Now().Unix())) -} - -func Hash(payload []byte, nonce, channel, chaincode, method, deadline string, pubkey []byte) [32]byte { - bb := append(removeSpacesBetweenCommaAndQuotes(payload), nonce...) // resolve the unclear json serialization behavior in protojson package - bb = append(bb, channel...) - bb = append(bb, chaincode...) - bb = append(bb, method...) - bb = append(bb, deadline...) - b58Pubkey := base58.Encode(pubkey) - bb = append(bb, b58Pubkey...) - return sha256.Sum256(bb) -} - -func CreateSig(payload []byte, nonce, channel, chaincode, method, deadline string, privateKey []byte) ([]byte, []byte) { - pubKey := ed25519.PrivateKey(privateKey).Public() - hashed := Hash(payload, nonce, channel, chaincode, method, deadline, []byte(pubKey.(ed25519.PublicKey))) - sig := ed25519.Sign(privateKey, hashed[:]) - return pubKey.(ed25519.PublicKey), sig -} - -func CheckSig(payload []byte, nonce, channel, chaincode, method, deadline string, pubKey []byte, sig []byte) error { - hashed := Hash(payload, nonce, channel, chaincode, method, deadline, pubKey) - if !ed25519.Verify(pubKey, hashed[:], sig) { - return ErrCheckSignatureFailed - } - return nil -} - -func removeSpacesBetweenCommaAndQuotes(s []byte) []byte { - removed := strings.ReplaceAll(string(s), `", "`, `","`) - removed = strings.ReplaceAll(removed, `"}, {"`, `"},{"`) - return []byte(strings.ReplaceAll(removed, `], "`, `],"`)) -} diff --git a/extensions/envelope/signer.go b/extensions/envelope/signer.go new file mode 100644 index 0000000..ddd1851 --- /dev/null +++ b/extensions/envelope/signer.go @@ -0,0 +1,59 @@ +package envelope + +import ( + "crypto/ed25519" + "fmt" + "strconv" + "strings" + "time" + + "github.com/btcsuite/btcutil/base58" +) + +type Signer struct { + crypto Crypto +} + +func NewSigner(crypto Crypto) *Signer { + return &Signer{crypto: crypto} +} + +func removeSpacesBetweenCommaAndQuotes(s []byte) []byte { + removed := strings.ReplaceAll(string(s), `", "`, `","`) + removed = strings.ReplaceAll(removed, `"}, {"`, `"},{"`) + return []byte(strings.ReplaceAll(removed, `], "`, `],"`)) +} + +func CreateNonce() string { + return strconv.Itoa(int(time.Now().Unix())) +} + +func (b *Signer) Hash(payload []byte, nonce, channel, chaincode, method, deadline string, pubkey []byte) []byte { + bb := append(removeSpacesBetweenCommaAndQuotes(payload), nonce...) // resolve the unclear json serialization behavior in protojson package + bb = append(bb, channel...) + bb = append(bb, chaincode...) + bb = append(bb, method...) + bb = append(bb, deadline...) + b58Pubkey := base58.Encode(pubkey) + bb = append(bb, b58Pubkey...) + return b.crypto.Hash(bb) +} + +func (b *Signer) Sign( + payload []byte, nonce, channel, chaincode, method, deadline string, privateKey []byte) ([]byte, error) { + pubKey, err := b.crypto.PublicKey(privateKey) + if err != nil { + return nil, fmt.Errorf(`extract public key: %w`, err) + } + + hashed := b.Hash(payload, nonce, channel, chaincode, method, deadline, pubKey) + return b.crypto.Sign(hashed, privateKey) +} + +func (b *Signer) CheckSignature(payload []byte, nonce, channel, chaincode, method, deadline string, pubKey []byte, sig []byte) error { + hashed := b.Hash(payload, nonce, channel, chaincode, method, deadline, pubKey) + if !ed25519.Verify(pubKey, hashed[:], sig) { + return ErrCheckSignatureFailed + } + return nil +} diff --git a/extensions/envelope/testdata/cc_envelope.go b/extensions/envelope/testdata/cc_envelope.go index f7d5930..57722b2 100755 --- a/extensions/envelope/testdata/cc_envelope.go +++ b/extensions/envelope/testdata/cc_envelope.go @@ -10,8 +10,8 @@ import ( type EnvelopCC struct { } -func NewEnvelopCC(chaincodeName string) *router.Chaincode { - r := router.New(chaincodeName, router.WithSerializer(serialize.PreferJSONSerializer)).Use(envelope.Verify()) +func NewEnvelopCC(signer *envelope.Signer, chaincodeName string) *router.Chaincode { + r := router.New(chaincodeName, router.WithSerializer(serialize.PreferJSONSerializer)).Use(envelope.Verify(signer)) r.Invoke("invokeWithEnvelope", func(c router.Context) (interface{}, error) { return nil, nil