@@ -13,6 +13,8 @@ use crate::error::LdkServerError;
1313use crate :: error:: LdkServerErrorCode :: {
1414 AuthError , InternalError , InternalServerError , InvalidRequestError , LightningError ,
1515} ;
16+ use bitcoin_hashes:: hmac:: { Hmac , HmacEngine } ;
17+ use bitcoin_hashes:: { sha256, Hash , HashEngine } ;
1618use ldk_server_protos:: api:: {
1719 Bolt11ReceiveRequest , Bolt11ReceiveResponse , Bolt11SendRequest , Bolt11SendResponse ,
1820 Bolt12ReceiveRequest , Bolt12ReceiveResponse , Bolt12SendRequest , Bolt12SendResponse ,
@@ -32,6 +34,7 @@ use ldk_server_protos::endpoints::{
3234use ldk_server_protos:: error:: { ErrorCode , ErrorResponse } ;
3335use reqwest:: header:: CONTENT_TYPE ;
3436use reqwest:: Client ;
37+ use std:: time:: { SystemTime , UNIX_EPOCH } ;
3538
3639const APPLICATION_OCTET_STREAM : & str = "application/octet-stream" ;
3740
@@ -40,12 +43,31 @@ const APPLICATION_OCTET_STREAM: &str = "application/octet-stream";
4043pub struct LdkServerClient {
4144 base_url : String ,
4245 client : Client ,
46+ api_key : String ,
4347}
4448
4549impl LdkServerClient {
4650 /// Constructs a [`LdkServerClient`] using `base_url` as the ldk-server endpoint.
47- pub fn new ( base_url : String ) -> Self {
48- Self { base_url, client : Client :: new ( ) }
51+ /// `api_key` is used for HMAC-based authentication.
52+ pub fn new ( base_url : String , api_key : String ) -> Self {
53+ Self { base_url, client : Client :: new ( ) , api_key }
54+ }
55+
56+ /// Computes the HMAC-SHA256 authentication header value.
57+ /// Format: "HMAC <timestamp>:<hmac_hex>"
58+ fn compute_auth_header ( & self , body : & [ u8 ] ) -> String {
59+ let timestamp = SystemTime :: now ( )
60+ . duration_since ( UNIX_EPOCH )
61+ . expect ( "System time should be after Unix epoch" )
62+ . as_secs ( ) ;
63+
64+ // Compute HMAC-SHA256(api_key, timestamp_bytes || body)
65+ let mut hmac_engine: HmacEngine < sha256:: Hash > = HmacEngine :: new ( self . api_key . as_bytes ( ) ) ;
66+ hmac_engine. input ( & timestamp. to_be_bytes ( ) ) ;
67+ hmac_engine. input ( body) ;
68+ let hmac_result = Hmac :: < sha256:: Hash > :: from_engine ( hmac_engine) ;
69+
70+ format ! ( "HMAC {}:{}" , timestamp, hmac_result)
4971 }
5072
5173 /// Retrieve the latest node info like `node_id`, `current_best_block` etc.
@@ -196,10 +218,12 @@ impl LdkServerClient {
196218 & self , request : & Rq , url : & str ,
197219 ) -> Result < Rs , LdkServerError > {
198220 let request_body = request. encode_to_vec ( ) ;
221+ let auth_header = self . compute_auth_header ( & request_body) ;
199222 let response_raw = self
200223 . client
201224 . post ( url)
202225 . header ( CONTENT_TYPE , APPLICATION_OCTET_STREAM )
226+ . header ( "X-Auth" , auth_header)
203227 . body ( request_body)
204228 . send ( )
205229 . await
0 commit comments