@@ -135,6 +135,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client,
135
135
case WIRE_HSMD_GET_CHANNEL_BASEPOINTS :
136
136
case WIRE_HSMD_DEV_MEMLEAK :
137
137
case WIRE_HSMD_SIGN_MESSAGE :
138
+ case WIRE_HSMD_SIGN_MESSAGE_WITH_KEY :
138
139
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY :
139
140
case WIRE_HSMD_SIGN_BOLT12 :
140
141
case WIRE_HSMD_SIGN_BOLT12_2 :
@@ -181,6 +182,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client,
181
182
case WIRE_HSMD_GET_CHANNEL_BASEPOINTS_REPLY :
182
183
case WIRE_HSMD_DEV_MEMLEAK_REPLY :
183
184
case WIRE_HSMD_SIGN_MESSAGE_REPLY :
185
+ case WIRE_HSMD_SIGN_MESSAGE_WITH_KEY_REPLY :
184
186
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY :
185
187
case WIRE_HSMD_SIGN_BOLT12_REPLY :
186
188
case WIRE_HSMD_SIGN_BOLT12_2_REPLY :
@@ -701,6 +703,49 @@ static u8 *handle_sign_message(struct hsmd_client *c, const u8 *msg_in)
701
703
return towire_hsmd_sign_message_reply (NULL , & rsig );
702
704
}
703
705
706
+ /* Raw message signing with provided key using electrum's standard
707
+ * signature = base64(SigRec(SHA256(SHA256(
708
+ * "\x18Bitcoin Signed Message:\n" + var_int(len(message)) + message
709
+ * )))) */
710
+ static u8 * handle_sign_message_with_key (struct hsmd_client * c , const u8 * msg_in )
711
+ {
712
+ u8 * msg ;
713
+ u32 keyidx ;
714
+ struct sha256_ctx sctx = SHA256_INIT ;
715
+ struct sha256_double shad ;
716
+ secp256k1_ecdsa_recoverable_signature rsig ;
717
+ struct privkey privkey ;
718
+ struct pubkey pubkey ;
719
+
720
+ if (!fromwire_hsmd_sign_message_with_key (tmpctx , msg_in , & msg , & keyidx ))
721
+ return hsmd_status_malformed_request (c , msg_in );
722
+
723
+ /* double sha256 the message */
724
+ const char header [] = "\x18"
725
+ "Bitcoin Signed Message:\n" ;
726
+ sha256_update (& sctx , (const u8 * )header , strlen (header ));
727
+
728
+ u8 vt [VARINT_MAX_LEN ];
729
+ size_t msg_len = tal_count (msg );
730
+ size_t vtlen = varint_put (vt , msg_len );
731
+ sha256_update (& sctx , vt , vtlen );
732
+
733
+ sha256_update (& sctx , msg , msg_len );
734
+ sha256_double_done (& sctx , & shad );
735
+
736
+ /* get the private key BIP32 */
737
+ bitcoin_key (& privkey , & pubkey , keyidx );
738
+
739
+ if (!secp256k1_ecdsa_sign_recoverable (
740
+ secp256k1_ctx , & rsig , shad .sha .u .u8 , privkey .secret .data , NULL ,
741
+ NULL )) {
742
+ return hsmd_status_bad_request (c , msg_in ,
743
+ "Failed to sign message" );
744
+ }
745
+
746
+ return towire_hsmd_sign_message_with_key_reply (NULL , & rsig );
747
+ }
748
+
704
749
/*~ lightningd asks us to sign a liquidity ad offer */
705
750
static u8 * handle_sign_option_will_fund_offer (struct hsmd_client * c ,
706
751
const u8 * msg_in )
@@ -2167,6 +2212,8 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client,
2167
2212
return handle_preapprove_keysend (client , msg );
2168
2213
case WIRE_HSMD_SIGN_MESSAGE :
2169
2214
return handle_sign_message (client , msg );
2215
+ case WIRE_HSMD_SIGN_MESSAGE_WITH_KEY :
2216
+ return handle_sign_message_with_key (client , msg );
2170
2217
case WIRE_HSMD_GET_CHANNEL_BASEPOINTS :
2171
2218
return handle_get_channel_basepoints (client , msg );
2172
2219
case WIRE_HSMD_CANNOUNCEMENT_SIG_REQ :
@@ -2249,6 +2296,7 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client,
2249
2296
case WIRE_HSMD_GET_CHANNEL_BASEPOINTS_REPLY :
2250
2297
case WIRE_HSMD_DEV_MEMLEAK_REPLY :
2251
2298
case WIRE_HSMD_SIGN_MESSAGE_REPLY :
2299
+ case WIRE_HSMD_SIGN_MESSAGE_WITH_KEY_REPLY :
2252
2300
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY :
2253
2301
case WIRE_HSMD_SIGN_BOLT12_REPLY :
2254
2302
case WIRE_HSMD_SIGN_BOLT12_2_REPLY :
0 commit comments