From a4349f6692a52a5484a84070eda52ca860db4b9e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 22 Feb 2022 14:25:43 +0300 Subject: [PATCH] [#55] refs: Add Scheme field to Signature Signed-off-by: Evgenii Stratonikov --- refs/convert.go | 2 + refs/grpc/types.go | 20 +++++ refs/grpc/types.pb.go | 151 ++++++++++++++++++++++++++++---------- refs/marshal.go | 15 +++- refs/string.go | 21 ++++++ refs/test/generate.go | 3 + refs/types.go | 22 ++++++ signature/sign.go | 19 +---- util/signature/data.go | 39 +++++----- util/signature/options.go | 45 ++++++++++-- 10 files changed, 252 insertions(+), 85 deletions(-) diff --git a/refs/convert.go b/refs/convert.go index 80b03d2..bb6e988 100644 --- a/refs/convert.go +++ b/refs/convert.go @@ -260,6 +260,7 @@ func (s *Signature) ToGRPCMessage() grpc.Message { m.SetKey(s.key) m.SetSign(s.sign) + m.SetScheme(refs.SignatureScheme(s.scheme)) } return m @@ -273,6 +274,7 @@ func (s *Signature) FromGRPCMessage(m grpc.Message) error { s.key = v.GetKey() s.sign = v.GetSign() + s.scheme = SignatureScheme(v.GetScheme()) return nil } diff --git a/refs/grpc/types.go b/refs/grpc/types.go index 7b0a9b9..b1c48c1 100644 --- a/refs/grpc/types.go +++ b/refs/grpc/types.go @@ -77,6 +77,26 @@ func (x *Signature) SetSign(v []byte) { } } +// SetScheme sets signature scheme. +func (x *Signature) SetScheme(s SignatureScheme) { + if x != nil { + x.Scheme = s + } +} + +// FromString parses SignatureScheme from a string representation, +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (x *SignatureScheme) FromString(s string) bool { + i, ok := SignatureScheme_value[s] + if ok { + *x = SignatureScheme(i) + } + + return ok +} + // FromString parses ChecksumType from a string representation, // It is a reverse action to String(). // diff --git a/refs/grpc/types.pb.go b/refs/grpc/types.pb.go index 6c0345f..7df2f05 100644 --- a/refs/grpc/types.pb.go +++ b/refs/grpc/types.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.19.1 +// protoc v3.19.4 // source: refs/grpc/types.proto package refs @@ -20,6 +20,59 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// Signature scheme describes digital signing scheme used for (key, signature) pair. +type SignatureScheme int32 + +const ( + // Unknown. The default interpretation depends on a particular structure type. + SignatureScheme_UNSPECIFIED SignatureScheme = 0 + // ECDSA with SHA-512 hashing (FIPS 186-3). + SignatureScheme_ECDSA_SHA512 SignatureScheme = 1 + // Deterministic ECDSA with SHA-256 hashing (RFC 6979) + SignatureScheme_ECDSA_RFC6979_SHA256 SignatureScheme = 2 +) + +// Enum value maps for SignatureScheme. +var ( + SignatureScheme_name = map[int32]string{ + 0: "UNSPECIFIED", + 1: "ECDSA_SHA512", + 2: "ECDSA_RFC6979_SHA256", + } + SignatureScheme_value = map[string]int32{ + "UNSPECIFIED": 0, + "ECDSA_SHA512": 1, + "ECDSA_RFC6979_SHA256": 2, + } +) + +func (x SignatureScheme) Enum() *SignatureScheme { + p := new(SignatureScheme) + *p = x + return p +} + +func (x SignatureScheme) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SignatureScheme) Descriptor() protoreflect.EnumDescriptor { + return file_refs_grpc_types_proto_enumTypes[0].Descriptor() +} + +func (SignatureScheme) Type() protoreflect.EnumType { + return &file_refs_grpc_types_proto_enumTypes[0] +} + +func (x SignatureScheme) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SignatureScheme.Descriptor instead. +func (SignatureScheme) EnumDescriptor() ([]byte, []int) { + return file_refs_grpc_types_proto_rawDescGZIP(), []int{0} +} + // Checksum algorithm type. type ChecksumType int32 @@ -57,11 +110,11 @@ func (x ChecksumType) String() string { } func (ChecksumType) Descriptor() protoreflect.EnumDescriptor { - return file_refs_grpc_types_proto_enumTypes[0].Descriptor() + return file_refs_grpc_types_proto_enumTypes[1].Descriptor() } func (ChecksumType) Type() protoreflect.EnumType { - return &file_refs_grpc_types_proto_enumTypes[0] + return &file_refs_grpc_types_proto_enumTypes[1] } func (x ChecksumType) Number() protoreflect.EnumNumber { @@ -70,7 +123,7 @@ func (x ChecksumType) Number() protoreflect.EnumNumber { // Deprecated: Use ChecksumType.Descriptor instead. func (ChecksumType) EnumDescriptor() ([]byte, []int) { - return file_refs_grpc_types_proto_rawDescGZIP(), []int{0} + return file_refs_grpc_types_proto_rawDescGZIP(), []int{1} } // Objects in NeoFS are addressed by their ContainerID and ObjectID. @@ -448,6 +501,8 @@ type Signature struct { Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` // Signature Sign []byte `protobuf:"bytes,2,opt,name=sign,json=signature,proto3" json:"sign,omitempty"` + // Scheme contains digital signature scheme identifier. + Scheme SignatureScheme `protobuf:"varint,3,opt,name=scheme,proto3,enum=neo.fs.v2.refs.SignatureScheme" json:"scheme,omitempty"` } func (x *Signature) Reset() { @@ -496,6 +551,13 @@ func (x *Signature) GetSign() []byte { return nil } +func (x *Signature) GetScheme() SignatureScheme { + if x != nil { + return x.Scheme + } + return SignatureScheme_UNSPECIFIED +} + // Checksum message. // Depending on checksum algorithm type the string presentation may vary: // @@ -585,25 +647,34 @@ var file_refs_grpc_types_proto_rawDesc = []byte{ 0x61, 0x6c, 0x75, 0x65, 0x22, 0x35, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x22, 0x36, 0x0a, 0x09, 0x53, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x22, 0x6f, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x17, 0x0a, 0x04, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x22, 0x4e, 0x0a, 0x08, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, - 0x30, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, - 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, - 0x73, 0x75, 0x6d, 0x2a, 0x41, 0x0a, 0x0c, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x53, 0x55, 0x4d, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x54, 0x5a, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x48, - 0x41, 0x32, 0x35, 0x36, 0x10, 0x02, 0x42, 0x50, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6e, 0x73, 0x70, 0x63, 0x63, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x6e, - 0x65, 0x6f, 0x66, 0x73, 0x2d, 0x61, 0x70, 0x69, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x72, - 0x65, 0x66, 0x73, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x3b, 0x72, 0x65, 0x66, 0x73, 0xaa, 0x02, 0x18, - 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, - 0x41, 0x50, 0x49, 0x2e, 0x52, 0x65, 0x66, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x75, 0x72, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, 0x76, 0x32, 0x2e, + 0x72, 0x65, 0x66, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x65, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x22, 0x4e, 0x0a, 0x08, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x30, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x6e, 0x65, 0x6f, 0x2e, 0x66, 0x73, 0x2e, + 0x76, 0x32, 0x2e, 0x72, 0x65, 0x66, 0x73, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x75, + 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x73, 0x75, 0x6d, 0x2a, 0x4e, 0x0a, 0x0f, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x12, + 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x53, 0x48, 0x41, 0x35, 0x31, 0x32, + 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x45, 0x43, 0x44, 0x53, 0x41, 0x5f, 0x52, 0x46, 0x43, 0x36, + 0x39, 0x37, 0x39, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x02, 0x2a, 0x41, 0x0a, 0x0c, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, + 0x43, 0x48, 0x45, 0x43, 0x4b, 0x53, 0x55, 0x4d, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x54, + 0x5a, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x02, 0x42, + 0x50, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6e, 0x73, + 0x70, 0x63, 0x63, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x6e, 0x65, 0x6f, 0x66, 0x73, 0x2d, 0x61, 0x70, + 0x69, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x72, 0x65, 0x66, 0x73, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x3b, 0x72, 0x65, 0x66, 0x73, 0xaa, 0x02, 0x18, 0x4e, 0x65, 0x6f, 0x2e, 0x46, 0x69, 0x6c, + 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x41, 0x50, 0x49, 0x2e, 0x52, 0x65, 0x66, + 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -618,28 +689,30 @@ func file_refs_grpc_types_proto_rawDescGZIP() []byte { return file_refs_grpc_types_proto_rawDescData } -var file_refs_grpc_types_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_refs_grpc_types_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_refs_grpc_types_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_refs_grpc_types_proto_goTypes = []interface{}{ - (ChecksumType)(0), // 0: neo.fs.v2.refs.ChecksumType - (*Address)(nil), // 1: neo.fs.v2.refs.Address - (*ObjectID)(nil), // 2: neo.fs.v2.refs.ObjectID - (*ContainerID)(nil), // 3: neo.fs.v2.refs.ContainerID - (*OwnerID)(nil), // 4: neo.fs.v2.refs.OwnerID - (*SubnetID)(nil), // 5: neo.fs.v2.refs.SubnetID - (*Version)(nil), // 6: neo.fs.v2.refs.Version - (*Signature)(nil), // 7: neo.fs.v2.refs.Signature - (*Checksum)(nil), // 8: neo.fs.v2.refs.Checksum + (SignatureScheme)(0), // 0: neo.fs.v2.refs.SignatureScheme + (ChecksumType)(0), // 1: neo.fs.v2.refs.ChecksumType + (*Address)(nil), // 2: neo.fs.v2.refs.Address + (*ObjectID)(nil), // 3: neo.fs.v2.refs.ObjectID + (*ContainerID)(nil), // 4: neo.fs.v2.refs.ContainerID + (*OwnerID)(nil), // 5: neo.fs.v2.refs.OwnerID + (*SubnetID)(nil), // 6: neo.fs.v2.refs.SubnetID + (*Version)(nil), // 7: neo.fs.v2.refs.Version + (*Signature)(nil), // 8: neo.fs.v2.refs.Signature + (*Checksum)(nil), // 9: neo.fs.v2.refs.Checksum } var file_refs_grpc_types_proto_depIdxs = []int32{ - 3, // 0: neo.fs.v2.refs.Address.container_id:type_name -> neo.fs.v2.refs.ContainerID - 2, // 1: neo.fs.v2.refs.Address.object_id:type_name -> neo.fs.v2.refs.ObjectID - 0, // 2: neo.fs.v2.refs.Checksum.type:type_name -> neo.fs.v2.refs.ChecksumType - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 4, // 0: neo.fs.v2.refs.Address.container_id:type_name -> neo.fs.v2.refs.ContainerID + 3, // 1: neo.fs.v2.refs.Address.object_id:type_name -> neo.fs.v2.refs.ObjectID + 0, // 2: neo.fs.v2.refs.Signature.scheme:type_name -> neo.fs.v2.refs.SignatureScheme + 1, // 3: neo.fs.v2.refs.Checksum.type:type_name -> neo.fs.v2.refs.ChecksumType + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name } func init() { file_refs_grpc_types_proto_init() } @@ -750,7 +823,7 @@ func file_refs_grpc_types_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_refs_grpc_types_proto_rawDesc, - NumEnums: 1, + NumEnums: 2, NumMessages: 8, NumExtensions: 0, NumServices: 0, diff --git a/refs/marshal.go b/refs/marshal.go index 148ad58..c496221 100644 --- a/refs/marshal.go +++ b/refs/marshal.go @@ -19,8 +19,9 @@ const ( checksumTypeField = 1 checksumValueField = 2 - signatureKeyField = 1 - signatureValueField = 2 + signatureKeyField = 1 + signatureValueField = 2 + signatureSchemeField = 3 versionMajorField = 1 versionMinorField = 2 @@ -250,7 +251,14 @@ func (s *Signature) StableMarshal(buf []byte) ([]byte, error) { offset += n - _, err = proto.BytesMarshal(signatureValueField, buf[offset:], s.sign) + n, err = proto.BytesMarshal(signatureValueField, buf[offset:], s.sign) + if err != nil { + return nil, err + } + + offset += n + + _, err = proto.EnumMarshal(signatureSchemeField, buf[offset:], int32(s.scheme)) if err != nil { return nil, err } @@ -265,6 +273,7 @@ func (s *Signature) StableSize() (size int) { size += proto.BytesSize(signatureKeyField, s.key) size += proto.BytesSize(signatureValueField, s.sign) + size += proto.EnumSize(signatureSchemeField, int32(s.scheme)) return size } diff --git a/refs/string.go b/refs/string.go index b27e07f..1b98600 100644 --- a/refs/string.go +++ b/refs/string.go @@ -24,3 +24,24 @@ func (t *ChecksumType) FromString(s string) bool { return ok } + +// String returns string representation of SignatureScheme. +func (t SignatureScheme) String() string { + return refs.SignatureScheme(t).String() +} + +// FromString parses SignatureScheme from a string representation. +// It is a reverse action to String(). +// +// Returns true if s was parsed successfully. +func (t *SignatureScheme) FromString(s string) bool { + var g refs.SignatureScheme + + ok := g.FromString(s) + + if ok { + *t = SignatureScheme(g) + } + + return ok +} diff --git a/refs/test/generate.go b/refs/test/generate.go index 835f358..3912ffa 100644 --- a/refs/test/generate.go +++ b/refs/test/generate.go @@ -1,6 +1,8 @@ package refstest import ( + "math/rand" + "github.com/nspcc-dev/neofs-api-go/v2/refs" ) @@ -88,6 +90,7 @@ func GenerateSignature(empty bool) *refs.Signature { if !empty { m.SetKey([]byte{1}) m.SetSign([]byte{2}) + m.SetScheme(refs.SignatureScheme(rand.Int31() % 3)) } return m diff --git a/refs/types.go b/refs/types.go index cd7ba5d..93a814a 100644 --- a/refs/types.go +++ b/refs/types.go @@ -31,8 +31,17 @@ type Checksum struct { type ChecksumType uint32 +type SignatureScheme uint32 + +const ( + UnspecifiedScheme SignatureScheme = iota + ECDSA_SHA512 + ECDSA_RFC6979_SHA256 +) + type Signature struct { key, sign []byte + scheme SignatureScheme } type SubnetID struct { @@ -175,6 +184,19 @@ func (s *Signature) SetSign(v []byte) { } } +func (s *Signature) GetScheme() SignatureScheme { + if s != nil { + return s.scheme + } + return UnspecifiedScheme +} + +func (s *Signature) SetScheme(scheme SignatureScheme) { + if s != nil { + s.scheme = scheme + } +} + func (s *SubnetID) SetValue(id uint32) { if s != nil { s.value = id diff --git a/signature/sign.go b/signature/sign.go index 7054416..c954891 100644 --- a/signature/sign.go +++ b/signature/sign.go @@ -131,19 +131,6 @@ func (s StableMarshalerWrapper) SignedDataSize() int { return 0 } -func keySignatureHandler(s *refs.Signature) signature.KeySignatureHandler { - return func(key []byte, sig []byte) { - s.SetKey(key) - s.SetSign(sig) - } -} - -func keySignatureSource(s *refs.Signature) signature.KeySignatureSource { - return func() ([]byte, []byte) { - return s.GetKey(), s.GetSign() - } -} - func SignServiceMessage(key *ecdsa.PrivateKey, msg interface{}) error { var ( body, meta, verifyOrigin stableMarshaler @@ -213,7 +200,9 @@ func signServiceMessagePart(key *ecdsa.PrivateKey, part stableMarshaler, sigWrit if err := signature.SignDataWithHandler( key, &StableMarshalerWrapper{part}, - keySignatureHandler(sig), + func(s *refs.Signature) { + *sig = *s + }, ); err != nil { return err } @@ -285,7 +274,7 @@ func verifyMatryoshkaLevel(body stableMarshaler, meta metaHeader, verify verific func verifyServiceMessagePart(part stableMarshaler, sigRdr func() *refs.Signature) error { return signature.VerifyDataWithSource( &StableMarshalerWrapper{part}, - keySignatureSource(sigRdr()), + sigRdr, ) } diff --git a/util/signature/data.go b/util/signature/data.go index 00d591e..ee2d7ad 100644 --- a/util/signature/data.go +++ b/util/signature/data.go @@ -3,6 +3,7 @@ package signature import ( "crypto/ecdsa" + "github.com/nspcc-dev/neofs-api-go/v2/refs" crypto "github.com/nspcc-dev/neofs-crypto" ) @@ -13,24 +14,24 @@ type DataSource interface { type DataWithSignature interface { DataSource - GetSignatureWithKey() (key, sig []byte) - SetSignatureWithKey(key, sig []byte) + GetSignature() *refs.Signature + SetSignature(*refs.Signature) } type SignOption func(*cfg) -type KeySignatureHandler func(key []byte, sig []byte) +type KeySignatureHandler func(*refs.Signature) -type KeySignatureSource func() (key, sig []byte) +type KeySignatureSource func() *refs.Signature -func DataSignature(key *ecdsa.PrivateKey, src DataSource, opts ...SignOption) ([]byte, error) { +func SignDataWithHandler(key *ecdsa.PrivateKey, src DataSource, handler KeySignatureHandler, opts ...SignOption) error { if key == nil { - return nil, crypto.ErrEmptyPrivateKey + return crypto.ErrEmptyPrivateKey } data, err := dataForSignature(src) if err != nil { - return nil, err + return err } defer bytesPool.Put(data) @@ -40,16 +41,16 @@ func DataSignature(key *ecdsa.PrivateKey, src DataSource, opts ...SignOption) ([ opts[i](cfg) } - return cfg.signFunc(key, data) -} - -func SignDataWithHandler(key *ecdsa.PrivateKey, src DataSource, handler KeySignatureHandler, opts ...SignOption) error { - sig, err := DataSignature(key, src, opts...) + sigData, err := sign(cfg, cfg.defaultScheme, key, data) if err != nil { return err } - handler(crypto.MarshalPublicKey(&key.PublicKey), sig) + sig := new(refs.Signature) + sig.SetScheme(cfg.defaultScheme) + sig.SetKey(crypto.MarshalPublicKey(&key.PublicKey)) + sig.SetSign(sigData) + handler(sig) return nil } @@ -67,19 +68,13 @@ func VerifyDataWithSource(dataSrc DataSource, sigSrc KeySignatureSource, opts .. opts[i](cfg) } - key, sig := sigSrc() - - return cfg.verifyFunc( - crypto.UnmarshalPublicKey(key), - data, - sig, - ) + return verify(cfg, data, sigSrc()) } func SignData(key *ecdsa.PrivateKey, v DataWithSignature, opts ...SignOption) error { - return SignDataWithHandler(key, v, v.SetSignatureWithKey, opts...) + return SignDataWithHandler(key, v, v.SetSignature, opts...) } func VerifyData(src DataWithSignature, opts ...SignOption) error { - return VerifyDataWithSource(src, src.GetSignatureWithKey, opts...) + return VerifyDataWithSource(src, src.GetSignature, opts...) } diff --git a/util/signature/options.go b/util/signature/options.go index 16d6330..c77c290 100644 --- a/util/signature/options.go +++ b/util/signature/options.go @@ -2,25 +2,58 @@ package signature import ( "crypto/ecdsa" + "fmt" + "github.com/nspcc-dev/neofs-api-go/v2/refs" crypto "github.com/nspcc-dev/neofs-crypto" ) type cfg struct { - signFunc func(key *ecdsa.PrivateKey, msg []byte) ([]byte, error) - verifyFunc func(key *ecdsa.PublicKey, msg []byte, sig []byte) error + defaultScheme refs.SignatureScheme + restrictScheme refs.SignatureScheme } func defaultCfg() *cfg { return &cfg{ - signFunc: crypto.Sign, - verifyFunc: crypto.Verify, + defaultScheme: refs.ECDSA_SHA512, + restrictScheme: refs.UnspecifiedScheme, + } +} + +func verify(cfg *cfg, data []byte, sig *refs.Signature) error { + scheme := sig.GetScheme() + if scheme == refs.UnspecifiedScheme { + scheme = cfg.defaultScheme + } + if cfg.restrictScheme != refs.UnspecifiedScheme && scheme != cfg.restrictScheme { + return fmt.Errorf("%w: unexpected signature scheme", crypto.ErrInvalidSignature) + } + + pub := crypto.UnmarshalPublicKey(sig.GetKey()) + switch scheme { + case refs.ECDSA_SHA512: + return crypto.Verify(pub, data, sig.GetSign()) + case refs.ECDSA_RFC6979_SHA256: + return crypto.VerifyRFC6979(pub, data, sig.GetSign()) + default: + return crypto.ErrInvalidSignature + } +} + +func sign(cfg *cfg, scheme refs.SignatureScheme, key *ecdsa.PrivateKey, data []byte) ([]byte, error) { + switch scheme { + case refs.ECDSA_SHA512: + return crypto.Sign(key, data) + case refs.ECDSA_RFC6979_SHA256: + return crypto.SignRFC6979(key, data) + default: + panic("unsupported scheme") } } func SignWithRFC6979() SignOption { return func(c *cfg) { - c.signFunc = crypto.SignRFC6979 - c.verifyFunc = crypto.VerifyRFC6979 + c.defaultScheme = refs.ECDSA_RFC6979_SHA256 + c.restrictScheme = refs.ECDSA_RFC6979_SHA256 } }