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.
This commit is contained in:
Oliver Gugger 2019-12-10 09:48:49 +01:00
parent d47f67d260
commit 9a73b9be78
No known key found for this signature in database
GPG Key ID: 8E4256593F177720
3 changed files with 471 additions and 50 deletions

@ -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",

@ -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
@ -145,4 +177,22 @@ service Signer {
index.
*/
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);
}

@ -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
}