From 9a73b9be7865002e406904cf5b84da8ca3942e43 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 10 Dec 2019 09:48:49 +0100 Subject: [PATCH] signrpc: sign and verify messages with custom key To allow signing of messages with any key in the key chain we add two new methods to the signer RPC. These behave differently to the methods with the same name in the main RPC as described in the documentation comment. --- lnrpc/signrpc/signer.pb.go | 363 +++++++++++++++++++++++++++++---- lnrpc/signrpc/signer.proto | 74 +++++-- lnrpc/signrpc/signer_server.go | 84 +++++++- 3 files changed, 471 insertions(+), 50 deletions(-) diff --git a/lnrpc/signrpc/signer.pb.go b/lnrpc/signrpc/signer.pb.go index 854a14fd..aa9b56fd 100644 --- a/lnrpc/signrpc/signer.pb.go +++ b/lnrpc/signrpc/signer.pb.go @@ -472,6 +472,194 @@ func (m *InputScriptResp) GetInputScripts() []*InputScript { return nil } +type SignMessageReq struct { + /// The message to be signed. + Msg []byte `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"` + /// The key locator that identifies which key to use for signing. + KeyLoc *KeyLocator `protobuf:"bytes,2,opt,name=key_loc,json=keyLoc,proto3" json:"key_loc,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SignMessageReq) Reset() { *m = SignMessageReq{} } +func (m *SignMessageReq) String() string { return proto.CompactTextString(m) } +func (*SignMessageReq) ProtoMessage() {} +func (*SignMessageReq) Descriptor() ([]byte, []int) { + return fileDescriptor_4ecd772f6c7ffacf, []int{8} +} + +func (m *SignMessageReq) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SignMessageReq.Unmarshal(m, b) +} +func (m *SignMessageReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SignMessageReq.Marshal(b, m, deterministic) +} +func (m *SignMessageReq) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignMessageReq.Merge(m, src) +} +func (m *SignMessageReq) XXX_Size() int { + return xxx_messageInfo_SignMessageReq.Size(m) +} +func (m *SignMessageReq) XXX_DiscardUnknown() { + xxx_messageInfo_SignMessageReq.DiscardUnknown(m) +} + +var xxx_messageInfo_SignMessageReq proto.InternalMessageInfo + +func (m *SignMessageReq) GetMsg() []byte { + if m != nil { + return m.Msg + } + return nil +} + +func (m *SignMessageReq) GetKeyLoc() *KeyLocator { + if m != nil { + return m.KeyLoc + } + return nil +} + +type SignMessageResp struct { + //* + //The signature for the given message in the DER format. + Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SignMessageResp) Reset() { *m = SignMessageResp{} } +func (m *SignMessageResp) String() string { return proto.CompactTextString(m) } +func (*SignMessageResp) ProtoMessage() {} +func (*SignMessageResp) Descriptor() ([]byte, []int) { + return fileDescriptor_4ecd772f6c7ffacf, []int{9} +} + +func (m *SignMessageResp) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SignMessageResp.Unmarshal(m, b) +} +func (m *SignMessageResp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SignMessageResp.Marshal(b, m, deterministic) +} +func (m *SignMessageResp) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignMessageResp.Merge(m, src) +} +func (m *SignMessageResp) XXX_Size() int { + return xxx_messageInfo_SignMessageResp.Size(m) +} +func (m *SignMessageResp) XXX_DiscardUnknown() { + xxx_messageInfo_SignMessageResp.DiscardUnknown(m) +} + +var xxx_messageInfo_SignMessageResp proto.InternalMessageInfo + +func (m *SignMessageResp) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +type VerifyMessageReq struct { + /// The message over which the signature is to be verified. + Msg []byte `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"` + /// The DER encoded signature to be verified over the given message. + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` + /// The public key the signature has to be valid for. + Pubkey []byte `protobuf:"bytes,3,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *VerifyMessageReq) Reset() { *m = VerifyMessageReq{} } +func (m *VerifyMessageReq) String() string { return proto.CompactTextString(m) } +func (*VerifyMessageReq) ProtoMessage() {} +func (*VerifyMessageReq) Descriptor() ([]byte, []int) { + return fileDescriptor_4ecd772f6c7ffacf, []int{10} +} + +func (m *VerifyMessageReq) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VerifyMessageReq.Unmarshal(m, b) +} +func (m *VerifyMessageReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VerifyMessageReq.Marshal(b, m, deterministic) +} +func (m *VerifyMessageReq) XXX_Merge(src proto.Message) { + xxx_messageInfo_VerifyMessageReq.Merge(m, src) +} +func (m *VerifyMessageReq) XXX_Size() int { + return xxx_messageInfo_VerifyMessageReq.Size(m) +} +func (m *VerifyMessageReq) XXX_DiscardUnknown() { + xxx_messageInfo_VerifyMessageReq.DiscardUnknown(m) +} + +var xxx_messageInfo_VerifyMessageReq proto.InternalMessageInfo + +func (m *VerifyMessageReq) GetMsg() []byte { + if m != nil { + return m.Msg + } + return nil +} + +func (m *VerifyMessageReq) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +func (m *VerifyMessageReq) GetPubkey() []byte { + if m != nil { + return m.Pubkey + } + return nil +} + +type VerifyMessageResp struct { + /// Whether the signature was valid over the given message. + Valid bool `protobuf:"varint,1,opt,name=valid,proto3" json:"valid,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *VerifyMessageResp) Reset() { *m = VerifyMessageResp{} } +func (m *VerifyMessageResp) String() string { return proto.CompactTextString(m) } +func (*VerifyMessageResp) ProtoMessage() {} +func (*VerifyMessageResp) Descriptor() ([]byte, []int) { + return fileDescriptor_4ecd772f6c7ffacf, []int{11} +} + +func (m *VerifyMessageResp) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VerifyMessageResp.Unmarshal(m, b) +} +func (m *VerifyMessageResp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VerifyMessageResp.Marshal(b, m, deterministic) +} +func (m *VerifyMessageResp) XXX_Merge(src proto.Message) { + xxx_messageInfo_VerifyMessageResp.Merge(m, src) +} +func (m *VerifyMessageResp) XXX_Size() int { + return xxx_messageInfo_VerifyMessageResp.Size(m) +} +func (m *VerifyMessageResp) XXX_DiscardUnknown() { + xxx_messageInfo_VerifyMessageResp.DiscardUnknown(m) +} + +var xxx_messageInfo_VerifyMessageResp proto.InternalMessageInfo + +func (m *VerifyMessageResp) GetValid() bool { + if m != nil { + return m.Valid + } + return false +} + func init() { proto.RegisterType((*KeyLocator)(nil), "signrpc.KeyLocator") proto.RegisterType((*KeyDescriptor)(nil), "signrpc.KeyDescriptor") @@ -481,48 +669,59 @@ func init() { proto.RegisterType((*SignResp)(nil), "signrpc.SignResp") proto.RegisterType((*InputScript)(nil), "signrpc.InputScript") proto.RegisterType((*InputScriptResp)(nil), "signrpc.InputScriptResp") + proto.RegisterType((*SignMessageReq)(nil), "signrpc.SignMessageReq") + proto.RegisterType((*SignMessageResp)(nil), "signrpc.SignMessageResp") + proto.RegisterType((*VerifyMessageReq)(nil), "signrpc.VerifyMessageReq") + proto.RegisterType((*VerifyMessageResp)(nil), "signrpc.VerifyMessageResp") } func init() { proto.RegisterFile("signrpc/signer.proto", fileDescriptor_4ecd772f6c7ffacf) } var fileDescriptor_4ecd772f6c7ffacf = []byte{ - // 562 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x53, 0x4f, 0x8f, 0xd3, 0x3e, - 0x10, 0x55, 0xb7, 0xbf, 0x36, 0xdd, 0x49, 0xd2, 0x1f, 0x98, 0x0a, 0x02, 0x08, 0x51, 0x22, 0x2d, - 0xea, 0x01, 0x5a, 0x51, 0x10, 0x12, 0x9c, 0xd0, 0x82, 0x56, 0xac, 0xba, 0xd2, 0x4a, 0x6e, 0x4f, - 0x5c, 0xa2, 0x34, 0x35, 0xa9, 0x95, 0x34, 0xf1, 0xc6, 0x0e, 0x69, 0x6e, 0x7c, 0x07, 0xbe, 0x30, - 0x1a, 0x3b, 0xfd, 0x07, 0x9c, 0x9a, 0xf7, 0x3c, 0x33, 0xef, 0x79, 0x5e, 0x0d, 0x03, 0xc9, 0xe3, - 0xac, 0x10, 0xd1, 0x04, 0x7f, 0x59, 0x31, 0x16, 0x45, 0xae, 0x72, 0x62, 0x35, 0xac, 0xff, 0x15, - 0x60, 0xc6, 0xea, 0x9b, 0x3c, 0x0a, 0x55, 0x5e, 0x90, 0x67, 0x00, 0x09, 0xab, 0x83, 0xef, 0xe1, - 0x86, 0xa7, 0xb5, 0xd7, 0x1a, 0xb6, 0x46, 0x1d, 0x7a, 0x9e, 0xb0, 0xfa, 0x4a, 0x13, 0xe4, 0x29, - 0x20, 0x08, 0x78, 0xb6, 0x62, 0x5b, 0xef, 0x4c, 0x9f, 0xf6, 0x12, 0x56, 0x5f, 0x23, 0xf6, 0x43, - 0x70, 0x67, 0xac, 0xfe, 0xc2, 0x64, 0x54, 0x70, 0x81, 0xc3, 0x7c, 0x70, 0x8b, 0xb0, 0x0a, 0xb0, - 0x63, 0x59, 0x2b, 0x26, 0xf5, 0x3c, 0x87, 0xda, 0x45, 0x58, 0xcd, 0x58, 0x7d, 0x89, 0x14, 0x79, - 0x05, 0x16, 0x9e, 0xa7, 0x79, 0xa4, 0xe7, 0xd9, 0xd3, 0x07, 0xe3, 0xc6, 0xd9, 0xf8, 0x60, 0x8b, - 0x76, 0x13, 0xfd, 0xed, 0x7f, 0x84, 0xce, 0x62, 0x7b, 0x5b, 0x2a, 0x32, 0x80, 0xce, 0x8f, 0x30, - 0x2d, 0x99, 0x1e, 0xd9, 0xa6, 0x06, 0xa0, 0x3d, 0x91, 0x04, 0x46, 0x5f, 0x8f, 0x73, 0x68, 0x4f, - 0x24, 0x73, 0x8d, 0xfd, 0x5f, 0x67, 0xd0, 0x9f, 0xf3, 0x38, 0x3b, 0x32, 0xf8, 0x06, 0xd0, 0x7d, - 0xb0, 0x62, 0x32, 0xd2, 0x83, 0xec, 0xe9, 0xc3, 0x63, 0xf5, 0x43, 0x25, 0x45, 0x93, 0x08, 0xc9, - 0x0b, 0x70, 0x24, 0xcf, 0xe2, 0x94, 0x05, 0xaa, 0x62, 0x61, 0xd2, 0xa8, 0xd8, 0x86, 0x5b, 0x20, - 0x85, 0x25, 0xab, 0xbc, 0x5c, 0xee, 0x4b, 0xda, 0xa6, 0xc4, 0x70, 0xa6, 0xe4, 0x02, 0xfa, 0x15, - 0x57, 0x19, 0x93, 0x72, 0xe7, 0xf6, 0x3f, 0x5d, 0xe4, 0x36, 0xac, 0xb1, 0x4c, 0x5e, 0x42, 0x37, - 0x2f, 0x95, 0x28, 0x95, 0xd7, 0xd1, 0xee, 0xfa, 0x7b, 0x77, 0x7a, 0x0b, 0xb4, 0x39, 0x25, 0x1e, - 0x60, 0x9c, 0xeb, 0x50, 0xae, 0x3d, 0x6b, 0xd8, 0x1a, 0xb9, 0x74, 0x07, 0xc9, 0x73, 0xb0, 0x79, - 0x26, 0x4a, 0xd5, 0x44, 0xd6, 0xd3, 0x91, 0x81, 0xa6, 0x4c, 0x68, 0x11, 0x58, 0xb8, 0x14, 0xca, - 0xee, 0xc8, 0x10, 0x1c, 0x8c, 0x4b, 0x6d, 0x4f, 0xd2, 0x82, 0x22, 0xac, 0x16, 0x5b, 0x13, 0xd6, - 0x7b, 0x00, 0x34, 0xa0, 0x17, 0x26, 0xbd, 0xb3, 0x61, 0x7b, 0x64, 0x4f, 0x1f, 0xed, 0x3d, 0x9d, - 0x2e, 0x97, 0x9e, 0xcb, 0x06, 0x4b, 0xff, 0x02, 0x7a, 0x46, 0x44, 0x0a, 0xf2, 0x18, 0x7a, 0xa8, - 0x22, 0x79, 0x8c, 0x0a, 0xed, 0x91, 0x43, 0xad, 0x22, 0xac, 0xe6, 0x3c, 0x96, 0xfe, 0x15, 0xd8, - 0xd7, 0xe8, 0xac, 0xb9, 0xbd, 0x07, 0x56, 0xb3, 0x8e, 0x5d, 0x61, 0x03, 0xf1, 0x5f, 0x2a, 0x79, - 0x7c, 0x1a, 0x34, 0xca, 0x35, 0x49, 0xdf, 0xc0, 0xff, 0x47, 0x73, 0xb4, 0xea, 0x07, 0x70, 0xcd, - 0x1e, 0x4c, 0x8f, 0x99, 0x68, 0x4f, 0x07, 0x7b, 0xf3, 0xc7, 0x0d, 0x0e, 0x3f, 0x00, 0x39, 0xfd, - 0xd9, 0x82, 0xee, 0x5c, 0x3f, 0x1d, 0xf2, 0x0e, 0x5c, 0xfc, 0xba, 0xd5, 0x5b, 0xa7, 0x61, 0x45, - 0xee, 0x9d, 0x5c, 0x9e, 0xb2, 0xbb, 0x27, 0xf7, 0xff, 0x60, 0xa4, 0x20, 0x9f, 0x80, 0x7c, 0xce, - 0x37, 0xa2, 0x54, 0xec, 0xf8, 0x76, 0x7f, 0xb7, 0x7a, 0xff, 0x34, 0xc3, 0xa4, 0xb8, 0x9c, 0x7c, - 0x7b, 0x1d, 0x73, 0xb5, 0x2e, 0x97, 0xe3, 0x28, 0xdf, 0x4c, 0x52, 0x1e, 0xaf, 0x55, 0xc6, 0xb3, - 0x38, 0x63, 0xaa, 0xca, 0x8b, 0x64, 0x92, 0x66, 0xab, 0x49, 0xba, 0x7f, 0xe2, 0x85, 0x88, 0x96, - 0x5d, 0xfd, 0xc8, 0xdf, 0xfe, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x80, 0x01, 0xce, 0xe1, 0xfc, 0x03, - 0x00, 0x00, + // 676 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xcb, 0x6e, 0xd3, 0x40, + 0x14, 0x55, 0x13, 0xf2, 0xe8, 0x75, 0xdc, 0xc7, 0x50, 0x15, 0xb7, 0x80, 0x08, 0x96, 0x8a, 0x82, + 0x04, 0x89, 0x08, 0x08, 0x09, 0x56, 0xa8, 0xa0, 0x8a, 0xaa, 0x45, 0x45, 0x93, 0x8a, 0x45, 0x37, + 0x91, 0xe3, 0x4c, 0x9d, 0x91, 0x1d, 0x7b, 0xea, 0x19, 0xe3, 0xf8, 0x17, 0xd8, 0xf2, 0xc3, 0x68, + 0x1e, 0x49, 0xec, 0xf0, 0x90, 0x58, 0xc5, 0xe7, 0xce, 0x9d, 0x73, 0x8f, 0xcf, 0xb9, 0x31, 0x1c, + 0x70, 0x1a, 0xc4, 0x29, 0xf3, 0x07, 0xf2, 0x97, 0xa4, 0x7d, 0x96, 0x26, 0x22, 0x41, 0x2d, 0x53, + 0x75, 0x3f, 0x03, 0x5c, 0x90, 0xe2, 0x32, 0xf1, 0x3d, 0x91, 0xa4, 0xe8, 0x31, 0x40, 0x48, 0x8a, + 0xf1, 0xad, 0x37, 0xa7, 0x51, 0xe1, 0x6c, 0x75, 0xb7, 0x7a, 0x0d, 0xbc, 0x1d, 0x92, 0xe2, 0x4c, + 0x15, 0xd0, 0x43, 0x90, 0x60, 0x4c, 0xe3, 0x29, 0x59, 0x38, 0x35, 0x75, 0xda, 0x0e, 0x49, 0x71, + 0x2e, 0xb1, 0xeb, 0x81, 0x7d, 0x41, 0x8a, 0x4f, 0x84, 0xfb, 0x29, 0x65, 0x92, 0xcc, 0x05, 0x3b, + 0xf5, 0xf2, 0xb1, 0xbc, 0x31, 0x29, 0x04, 0xe1, 0x8a, 0xaf, 0x83, 0xad, 0xd4, 0xcb, 0x2f, 0x48, + 0x71, 0x2a, 0x4b, 0xe8, 0x05, 0xb4, 0xe4, 0x79, 0x94, 0xf8, 0x8a, 0xcf, 0x1a, 0xde, 0xef, 0x1b, + 0x65, 0xfd, 0xb5, 0x2c, 0xdc, 0x0c, 0xd5, 0xb3, 0xfb, 0x1e, 0x1a, 0xd7, 0x8b, 0xab, 0x4c, 0xa0, + 0x03, 0x68, 0x7c, 0xf7, 0xa2, 0x8c, 0x28, 0xca, 0x3a, 0xd6, 0x40, 0xca, 0x63, 0xe1, 0x58, 0xcf, + 0x57, 0x74, 0x1d, 0xdc, 0x66, 0xe1, 0x48, 0x61, 0xf7, 0x67, 0x0d, 0x76, 0x46, 0x34, 0x88, 0x4b, + 0x02, 0x5f, 0x81, 0x54, 0x3f, 0x9e, 0x12, 0xee, 0x2b, 0x22, 0x6b, 0x78, 0x58, 0x9e, 0xbe, 0xee, + 0xc4, 0x52, 0xa4, 0x84, 0xe8, 0x29, 0x74, 0x38, 0x8d, 0x83, 0x88, 0x8c, 0x45, 0x4e, 0xbc, 0xd0, + 0x4c, 0xb1, 0x74, 0xed, 0x5a, 0x96, 0x64, 0xcb, 0x34, 0xc9, 0x26, 0xab, 0x96, 0xba, 0x6e, 0xd1, + 0x35, 0xdd, 0x72, 0x02, 0x3b, 0x39, 0x15, 0x31, 0xe1, 0x7c, 0xa9, 0xf6, 0x9e, 0x6a, 0xb2, 0x4d, + 0x55, 0x4b, 0x46, 0xcf, 0xa0, 0x99, 0x64, 0x82, 0x65, 0xc2, 0x69, 0x28, 0x75, 0x3b, 0x2b, 0x75, + 0xca, 0x05, 0x6c, 0x4e, 0x91, 0x03, 0x32, 0xce, 0x99, 0xc7, 0x67, 0x4e, 0xab, 0xbb, 0xd5, 0xb3, + 0xf1, 0x12, 0xa2, 0x27, 0x60, 0xd1, 0x98, 0x65, 0xc2, 0x44, 0xd6, 0x56, 0x91, 0x81, 0x2a, 0xe9, + 0xd0, 0x7c, 0x68, 0x49, 0x53, 0x30, 0xb9, 0x43, 0x5d, 0xe8, 0xc8, 0xb8, 0xc4, 0xa2, 0x92, 0x16, + 0xa4, 0x5e, 0x7e, 0xbd, 0xd0, 0x61, 0xbd, 0x05, 0x90, 0x02, 0x94, 0x61, 0xdc, 0xa9, 0x75, 0xeb, + 0x3d, 0x6b, 0xf8, 0x60, 0xa5, 0xa9, 0x6a, 0x2e, 0xde, 0xe6, 0x06, 0x73, 0xf7, 0x04, 0xda, 0x7a, + 0x08, 0x67, 0xe8, 0x08, 0xda, 0x72, 0x0a, 0xa7, 0x81, 0x9c, 0x50, 0xef, 0x75, 0x70, 0x2b, 0xf5, + 0xf2, 0x11, 0x0d, 0xb8, 0x7b, 0x06, 0xd6, 0xb9, 0x54, 0x66, 0xde, 0xde, 0x81, 0x96, 0xb1, 0x63, + 0xd9, 0x68, 0xa0, 0xdc, 0x52, 0x4e, 0x83, 0x6a, 0xd0, 0x72, 0x9c, 0x49, 0xfa, 0x12, 0x76, 0x4b, + 0x3c, 0x6a, 0xea, 0x3b, 0xb0, 0xb5, 0x0f, 0xfa, 0x8e, 0x66, 0xb4, 0x86, 0x07, 0x2b, 0xf1, 0xe5, + 0x0b, 0x1d, 0xba, 0x06, 0xdc, 0xfd, 0xaa, 0xd7, 0xe6, 0x0b, 0xe1, 0xdc, 0x0b, 0x88, 0x34, 0x6a, + 0x0f, 0xea, 0x73, 0x1e, 0x18, 0x7f, 0xe4, 0xe3, 0x7f, 0x6e, 0xf1, 0x00, 0x76, 0x2b, 0x8c, 0x9c, + 0xa1, 0x47, 0xa0, 0xec, 0xf2, 0x44, 0x96, 0x12, 0x43, 0xbc, 0x2e, 0xb8, 0x37, 0xb0, 0xf7, 0x8d, + 0xa4, 0xf4, 0xb6, 0xf8, 0xa7, 0x88, 0x0a, 0x47, 0x6d, 0x83, 0x03, 0x1d, 0x42, 0x93, 0x65, 0x93, + 0x90, 0x14, 0x66, 0x1f, 0x0d, 0x72, 0x9f, 0xc3, 0xfe, 0x06, 0x37, 0x67, 0xe6, 0xef, 0x45, 0xa7, + 0x8a, 0xbe, 0x8d, 0x35, 0x18, 0xfe, 0xa8, 0x41, 0x73, 0xa4, 0x3e, 0x22, 0xe8, 0x0d, 0xd8, 0xf2, + 0xe9, 0x4a, 0xed, 0x1f, 0xf6, 0x72, 0xb4, 0x57, 0x59, 0x03, 0x4c, 0xee, 0x8e, 0xf7, 0x37, 0x2a, + 0x9c, 0xa1, 0x0f, 0x80, 0x3e, 0x26, 0x73, 0x96, 0x09, 0x52, 0xce, 0xf9, 0xf7, 0xab, 0xce, 0x1f, + 0x63, 0xd1, 0x0c, 0x56, 0xc9, 0x3a, 0x54, 0x5d, 0xbe, 0xb5, 0x3b, 0x25, 0x86, 0x4d, 0xa7, 0xcf, + 0xc0, 0xae, 0xbc, 0x2f, 0x3a, 0x5a, 0xb5, 0x6e, 0x7a, 0x7c, 0x7c, 0xfc, 0xb7, 0x23, 0xce, 0x4e, + 0x07, 0x37, 0x2f, 0x03, 0x2a, 0x66, 0xd9, 0xa4, 0xef, 0x27, 0xf3, 0x41, 0x44, 0x83, 0x99, 0x88, + 0x69, 0x1c, 0xc4, 0x44, 0xe4, 0x49, 0x1a, 0x0e, 0xa2, 0x78, 0x3a, 0x88, 0x56, 0x9f, 0xdd, 0x94, + 0xf9, 0x93, 0xa6, 0xfa, 0xf0, 0xbe, 0xfe, 0x15, 0x00, 0x00, 0xff, 0xff, 0x09, 0xde, 0xe5, 0x7f, + 0x90, 0x05, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -559,6 +758,20 @@ type SignerClient interface { //in the TxOut field, the value in that same field, and finally the input //index. ComputeInputScript(ctx context.Context, in *SignReq, opts ...grpc.CallOption) (*InputScriptResp, error) + //* + //SignMessage signs a message with the key specified in the key locator. The + //returned signature is DER encoded. + // + //The main difference to SignMessage in the main RPC is that a specific key is + //used to sign the message instead of the node identity private key. + SignMessage(ctx context.Context, in *SignMessageReq, opts ...grpc.CallOption) (*SignMessageResp, error) + //* + //VerifyMessage verifies a signature over a message using the public key + //provided. The signature must be DER encoded. + // + //The main difference to VerifyMessage in the main RPC is that the public key + //used to sign the message does not have to be a node known to the network. + VerifyMessage(ctx context.Context, in *VerifyMessageReq, opts ...grpc.CallOption) (*VerifyMessageResp, error) } type signerClient struct { @@ -587,6 +800,24 @@ func (c *signerClient) ComputeInputScript(ctx context.Context, in *SignReq, opts return out, nil } +func (c *signerClient) SignMessage(ctx context.Context, in *SignMessageReq, opts ...grpc.CallOption) (*SignMessageResp, error) { + out := new(SignMessageResp) + err := c.cc.Invoke(ctx, "/signrpc.Signer/SignMessage", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *signerClient) VerifyMessage(ctx context.Context, in *VerifyMessageReq, opts ...grpc.CallOption) (*VerifyMessageResp, error) { + out := new(VerifyMessageResp) + err := c.cc.Invoke(ctx, "/signrpc.Signer/VerifyMessage", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // SignerServer is the server API for Signer service. type SignerServer interface { //* @@ -611,6 +842,20 @@ type SignerServer interface { //in the TxOut field, the value in that same field, and finally the input //index. ComputeInputScript(context.Context, *SignReq) (*InputScriptResp, error) + //* + //SignMessage signs a message with the key specified in the key locator. The + //returned signature is DER encoded. + // + //The main difference to SignMessage in the main RPC is that a specific key is + //used to sign the message instead of the node identity private key. + SignMessage(context.Context, *SignMessageReq) (*SignMessageResp, error) + //* + //VerifyMessage verifies a signature over a message using the public key + //provided. The signature must be DER encoded. + // + //The main difference to VerifyMessage in the main RPC is that the public key + //used to sign the message does not have to be a node known to the network. + VerifyMessage(context.Context, *VerifyMessageReq) (*VerifyMessageResp, error) } func RegisterSignerServer(s *grpc.Server, srv SignerServer) { @@ -653,6 +898,42 @@ func _Signer_ComputeInputScript_Handler(srv interface{}, ctx context.Context, de return interceptor(ctx, in, info, handler) } +func _Signer_SignMessage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SignMessageReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SignerServer).SignMessage(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/signrpc.Signer/SignMessage", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SignerServer).SignMessage(ctx, req.(*SignMessageReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Signer_VerifyMessage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(VerifyMessageReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SignerServer).VerifyMessage(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/signrpc.Signer/VerifyMessage", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SignerServer).VerifyMessage(ctx, req.(*VerifyMessageReq)) + } + return interceptor(ctx, in, info, handler) +} + var _Signer_serviceDesc = grpc.ServiceDesc{ ServiceName: "signrpc.Signer", HandlerType: (*SignerServer)(nil), @@ -665,6 +946,14 @@ var _Signer_serviceDesc = grpc.ServiceDesc{ MethodName: "ComputeInputScript", Handler: _Signer_ComputeInputScript_Handler, }, + { + MethodName: "SignMessage", + Handler: _Signer_SignMessage_Handler, + }, + { + MethodName: "VerifyMessage", + Handler: _Signer_VerifyMessage_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "signrpc/signer.proto", diff --git a/lnrpc/signrpc/signer.proto b/lnrpc/signrpc/signer.proto index 6e2b0002..11c707bd 100644 --- a/lnrpc/signrpc/signer.proto +++ b/lnrpc/signrpc/signer.proto @@ -13,17 +13,17 @@ message KeyLocator { } message KeyDescriptor { - /** - The raw bytes of the key being identified. Either this or the KeyLocator - must be specified. - */ - bytes raw_key_bytes = 1; + /** + The raw bytes of the key being identified. Either this or the KeyLocator + must be specified. + */ + bytes raw_key_bytes = 1; - /** - The key locator that identifies which key to use for signing. Either this - or the raw bytes of the target key must be specified. - */ - KeyLocator key_loc = 2; + /** + The key locator that identifies which key to use for signing. Either this + or the raw bytes of the target key must be specified. + */ + KeyLocator key_loc = 2; } message TxOut { @@ -119,6 +119,38 @@ message InputScriptResp { repeated InputScript input_scripts = 1; } +message SignMessageReq { + /// The message to be signed. + bytes msg = 1; + + /// The key locator that identifies which key to use for signing. + KeyLocator key_loc = 2; +} +message SignMessageResp { + /** + The signature for the given message in the fixed-size LN wire format. + */ + bytes signature = 1; +} + +message VerifyMessageReq { + /// The message over which the signature is to be verified. + bytes msg = 1; + + /** + The fixed-size LN wire encoded signature to be verified over the given + message. + */ + bytes signature = 2; + + /// The public key the signature has to be valid for. + bytes pubkey = 3; +} +message VerifyMessageResp { + /// Whether the signature was valid over the given message. + bool valid = 1; +} + service Signer { /** SignOutputRaw is a method that can be used to generated a signature for a @@ -130,7 +162,7 @@ service Signer { If we are unable to sign using the specified keys, then an error will be returned. */ - rpc SignOutputRaw(SignReq) returns (SignResp); + rpc SignOutputRaw (SignReq) returns (SignResp); /** ComputeInputScript generates a complete InputIndex for the passed @@ -144,5 +176,23 @@ service Signer { in the TxOut field, the value in that same field, and finally the input index. */ - rpc ComputeInputScript(SignReq) returns (InputScriptResp); + rpc ComputeInputScript (SignReq) returns (InputScriptResp); + + /** + SignMessage signs a message with the key specified in the key locator. The + returned signature is fixed-size LN wire format encoded. + + The main difference to SignMessage in the main RPC is that a specific key is + used to sign the message instead of the node identity private key. + */ + rpc SignMessage (SignMessageReq) returns (SignMessageResp); + + /** + VerifyMessage verifies a signature over a message using the public key + provided. The signature must be fixed-size LN wire format encoded. + + The main difference to VerifyMessage in the main RPC is that the public key + used to sign the message does not have to be a node known to the network. + */ + rpc VerifyMessage (VerifyMessageReq) returns (VerifyMessageResp); } diff --git a/lnrpc/signrpc/signer_server.go b/lnrpc/signrpc/signer_server.go index 20abf43b..9ef07592 100644 --- a/lnrpc/signrpc/signer_server.go +++ b/lnrpc/signrpc/signer_server.go @@ -11,12 +11,13 @@ import ( "path/filepath" "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnrpc" - + "github.com/lightningnetwork/lnd/lnwire" "google.golang.org/grpc" "gopkg.in/macaroon-bakery.v2/bakery" ) @@ -383,3 +384,84 @@ func (s *Server) ComputeInputScript(ctx context.Context, return resp, nil } + +// SignMessage signs a message with the key specified in the key locator. The +// returned signature is fixed-size LN wire format encoded. +func (s *Server) SignMessage(ctx context.Context, + in *SignMessageReq) (*SignMessageResp, error) { + + if in.Msg == nil { + return nil, fmt.Errorf("a message to sign MUST be passed in") + } + if in.KeyLoc == nil { + return nil, fmt.Errorf("a key locator MUST be passed in") + } + + // Derive the private key we'll be using for signing. + keyLocator := keychain.KeyLocator{ + Family: keychain.KeyFamily(in.KeyLoc.KeyFamily), + Index: uint32(in.KeyLoc.KeyIndex), + } + privKey, err := s.cfg.KeyRing.DerivePrivKey(keychain.KeyDescriptor{ + KeyLocator: keyLocator, + }) + if err != nil { + return nil, fmt.Errorf("can't derive private key: %v", err) + } + + // The signature is over the sha256 hash of the message. + digest := chainhash.HashB(in.Msg) + + // Create the raw ECDSA signature first and convert it to the final wire + // format after. + sig, err := privKey.Sign(digest) + if err != nil { + return nil, fmt.Errorf("can't sign the hash: %v", err) + } + wireSig, err := lnwire.NewSigFromSignature(sig) + if err != nil { + return nil, fmt.Errorf("can't convert to wire format: %v", err) + } + return &SignMessageResp{ + Signature: wireSig.ToSignatureBytes(), + }, nil +} + +// VerifyMessage verifies a signature over a message using the public key +// provided. The signature must be fixed-size LN wire format encoded. +func (s *Server) VerifyMessage(ctx context.Context, + in *VerifyMessageReq) (*VerifyMessageResp, error) { + + if in.Msg == nil { + return nil, fmt.Errorf("a message to verify MUST be passed in") + } + if in.Signature == nil { + return nil, fmt.Errorf("a signature to verify MUST be passed " + + "in") + } + if in.Pubkey == nil { + return nil, fmt.Errorf("a pubkey to verify MUST be passed in") + } + pubkey, err := btcec.ParsePubKey(in.Pubkey, btcec.S256()) + if err != nil { + return nil, fmt.Errorf("unable to parse pubkey: %v", err) + } + + // The signature must be fixed-size LN wire format encoded. + wireSig, err := lnwire.NewSigFromRawSignature(in.Signature) + if err != nil { + return nil, fmt.Errorf("failed to decode signature: %v", err) + } + sig, err := wireSig.ToSignature() + if err != nil { + return nil, fmt.Errorf("failed to convert from wire format: %v", + err) + } + + // The signature is over the sha256 hash of the message. + digest := chainhash.HashB(in.Msg) + valid := sig.Verify(digest, pubkey) + return &VerifyMessageResp{ + Valid: valid, + }, nil +}