@@ -28,6 +28,7 @@ import (
28
28
29
29
"github.com/babylonlabs-io/covenant-emulator/covenant-signer/signerapp"
30
30
"github.com/babylonlabs-io/covenant-emulator/covenant-signer/signerservice"
31
+ "github.com/babylonlabs-io/covenant-emulator/covenant-signer/signerservice/middlewares"
31
32
"github.com/babylonlabs-io/covenant-emulator/covenant-signer/signerservice/types"
32
33
)
33
34
@@ -130,24 +131,24 @@ func buildDataToSign(t *testing.T, covnenantPublicKey *btcec.PublicKey) signerap
130
131
}
131
132
132
133
func TestGetPublicKey (t * testing.T ) {
133
- tm := StartManager (t , 100 , false )
134
+ tm := StartManager (t , 100 , false , "" )
134
135
// default passphrase is empty in non encrypted keyring
135
- err := signerservice .Unlock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "" )
136
+ err := signerservice .Unlock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "" , "" )
136
137
require .NoError (t , err )
137
138
138
- pubKey , err := signerservice .GetPublicKey (context .Background (), tm .SigningServerUrl (), 10 * time .Second )
139
+ pubKey , err := signerservice .GetPublicKey (context .Background (), tm .SigningServerUrl (), 10 * time .Second , tm . hmacKey )
139
140
require .NoError (t , err )
140
141
require .NotNil (t , pubKey )
141
142
142
143
}
143
144
144
145
func TestSigningTransactions (t * testing.T ) {
145
- tm := StartManager (t , 100 , false )
146
+ tm := StartManager (t , 100 , false , "" )
146
147
// default passphrase is empty in non encrypted keyring
147
- err := signerservice .Unlock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "" )
148
+ err := signerservice .Unlock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "" , "" )
148
149
require .NoError (t , err )
149
150
150
- pubKey , err := signerservice .GetPublicKey (context .Background (), tm .SigningServerUrl (), 10 * time .Second )
151
+ pubKey , err := signerservice .GetPublicKey (context .Background (), tm .SigningServerUrl (), 10 * time .Second , tm . hmacKey )
151
152
require .NoError (t , err )
152
153
require .NotNil (t , pubKey )
153
154
@@ -158,6 +159,7 @@ func TestSigningTransactions(t *testing.T) {
158
159
tm .SigningServerUrl (),
159
160
10 * time .Second ,
160
161
& dataToSign ,
162
+ "" ,
161
163
)
162
164
163
165
require .NoError (t , err )
@@ -168,7 +170,7 @@ func TestSigningTransactions(t *testing.T) {
168
170
}
169
171
170
172
func TestRejectToLargeRequest (t * testing.T ) {
171
- tm := StartManager (t , 100 , false )
173
+ tm := StartManager (t , 100 , false , "" )
172
174
r := rand .New (rand .NewSource (time .Now ().UnixNano ()))
173
175
tmContentLimit := tm .signerConfig .Server .MaxContentLength
174
176
size := tmContentLimit + 1
@@ -200,12 +202,12 @@ func TestRejectToLargeRequest(t *testing.T) {
200
202
}
201
203
202
204
func TestSigningTransactionsUsingEncryptedFileKeyRing (t * testing.T ) {
203
- tm := StartManager (t , 100 , true )
205
+ tm := StartManager (t , 100 , true , "" )
204
206
205
- err := signerservice .Unlock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "testtest" )
207
+ err := signerservice .Unlock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "testtest" , "" )
206
208
require .NoError (t , err )
207
209
208
- pubKey , err := signerservice .GetPublicKey (context .Background (), tm .SigningServerUrl (), 10 * time .Second )
210
+ pubKey , err := signerservice .GetPublicKey (context .Background (), tm .SigningServerUrl (), 10 * time .Second , tm . hmacKey )
209
211
require .NoError (t , err )
210
212
require .NotNil (t , pubKey )
211
213
@@ -216,6 +218,7 @@ func TestSigningTransactionsUsingEncryptedFileKeyRing(t *testing.T) {
216
218
tm .SigningServerUrl (),
217
219
10 * time .Second ,
218
220
& dataToSign ,
221
+ "" ,
219
222
)
220
223
221
224
require .NoError (t , err )
@@ -226,19 +229,19 @@ func TestSigningTransactionsUsingEncryptedFileKeyRing(t *testing.T) {
226
229
}
227
230
228
231
func TestLockingKeyring (t * testing.T ) {
229
- tm := StartManager (t , 100 , true )
232
+ tm := StartManager (t , 100 , true , "" )
230
233
231
- err := signerservice .Unlock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "testtest" )
234
+ err := signerservice .Unlock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "testtest" , "" )
232
235
require .NoError (t , err )
233
236
234
- pubKey , err := signerservice .GetPublicKey (context .Background (), tm .SigningServerUrl (), 10 * time .Second )
237
+ pubKey , err := signerservice .GetPublicKey (context .Background (), tm .SigningServerUrl (), 10 * time .Second , tm . hmacKey )
235
238
require .NoError (t , err )
236
239
require .NotNil (t , pubKey )
237
240
238
241
dataToSign := buildDataToSign (t , pubKey )
239
242
240
243
// lock the keyring, and clear the private key from memory
241
- err = signerservice .Lock (context .Background (), tm .SigningServerUrl (), 10 * time .Second )
244
+ err = signerservice .Lock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "" )
242
245
require .NoError (t , err )
243
246
244
247
// try to sign a transaction with a locked keyring, it should fail
@@ -247,9 +250,164 @@ func TestLockingKeyring(t *testing.T) {
247
250
tm .SigningServerUrl (),
248
251
10 * time .Second ,
249
252
& dataToSign ,
253
+ "" ,
250
254
)
251
255
252
256
require .Error (t , err )
253
257
require .Nil (t , sigs )
258
+ }
259
+
260
+ func TestHMACAuthentication (t * testing.T ) {
261
+ // Test with valid HMAC key
262
+ testHMACKey := "test-hmac-key-for-authentication"
263
+ tm := StartManager (t , 100 , false , testHMACKey )
264
+
265
+ err := signerservice .Unlock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "" , testHMACKey )
266
+ require .NoError (t , err , "Unlock should succeed with valid HMAC key" )
267
+
268
+ pubKey , err := signerservice .GetPublicKey (context .Background (), tm .SigningServerUrl (), 10 * time .Second , testHMACKey )
269
+ require .NoError (t , err )
270
+ require .NotNil (t , pubKey )
271
+
272
+ dataToSign := buildDataToSign (t , pubKey )
273
+
274
+ sigs , err := signerservice .RequestCovenantSignaure (
275
+ context .Background (),
276
+ tm .SigningServerUrl (),
277
+ 10 * time .Second ,
278
+ & dataToSign ,
279
+ testHMACKey ,
280
+ )
281
+ require .NoError (t , err , "Signing should succeed with valid HMAC key" )
282
+ require .NotNil (t , sigs )
283
+
284
+ _ , err = signerservice .RequestCovenantSignaure (
285
+ context .Background (),
286
+ tm .SigningServerUrl (),
287
+ 10 * time .Second ,
288
+ & dataToSign ,
289
+ "invalid-hmac-key" ,
290
+ )
291
+ require .Error (t , err , "Signing should fail with invalid HMAC key" )
292
+ require .Contains (t , err .Error (), "401" , "Error should be a 401 Unauthorized" )
293
+
294
+ err = signerservice .Lock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , testHMACKey )
295
+ require .NoError (t , err , "Lock should succeed with valid HMAC key" )
296
+
297
+ err = signerservice .Lock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "invalid-hmac-key" )
298
+ require .Error (t , err , "Lock should fail with invalid HMAC key" )
299
+ require .Contains (t , err .Error (), "401" , "Error should be a 401 Unauthorized" )
300
+ }
301
+
302
+ func TestHMACDirectRequest (t * testing.T ) {
303
+ testHMACKey := "test-hmac-key-for-direct-request"
304
+ tm := StartManager (t , 100 , false , testHMACKey )
305
+
306
+ err := signerservice .Unlock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "" , testHMACKey )
307
+ require .NoError (t , err )
308
+
309
+ body := []byte (`{"passphrase":""}` )
310
+ route := fmt .Sprintf ("%s/v1/unlock" , tm .SigningServerUrl ())
311
+
312
+ hmacValue , err := middlewares .GenerateHMAC (testHMACKey , body )
313
+ require .NoError (t , err )
314
+
315
+ httpRequest , err := http .NewRequestWithContext (context .Background (), "POST" , route , bytes .NewReader (body ))
316
+ require .NoError (t , err )
317
+ httpRequest .Header .Set ("Content-Type" , "application/json" )
318
+ httpRequest .Header .Set (middlewares .HeaderCovenantHMAC , hmacValue )
319
+
320
+ client := http.Client {Timeout : 10 * time .Second }
321
+ res , err := client .Do (httpRequest )
322
+ require .NoError (t , err )
323
+ defer res .Body .Close ()
324
+ require .Equal (t , http .StatusOK , res .StatusCode , "Request with valid HMAC should succeed" )
325
+
326
+ httpRequest , err = http .NewRequestWithContext (context .Background (), "POST" , route , bytes .NewReader (body ))
327
+ require .NoError (t , err )
328
+ httpRequest .Header .Set ("Content-Type" , "application/json" )
329
+ httpRequest .Header .Set (middlewares .HeaderCovenantHMAC , "invalidhmacvalue" )
330
+
331
+ res , err = client .Do (httpRequest )
332
+ require .NoError (t , err )
333
+ defer res .Body .Close ()
334
+ require .Equal (t , http .StatusUnauthorized , res .StatusCode , "Request with invalid HMAC should fail with 401" )
335
+
336
+ httpRequest , err = http .NewRequestWithContext (context .Background (), "POST" , route , bytes .NewReader (body ))
337
+ require .NoError (t , err )
338
+ httpRequest .Header .Set ("Content-Type" , "application/json" )
339
+
340
+ res , err = client .Do (httpRequest )
341
+ require .NoError (t , err )
342
+ defer res .Body .Close ()
343
+ require .Equal (t , http .StatusUnauthorized , res .StatusCode , "Request with missing HMAC should fail with 401" )
344
+
345
+ pkRoute := fmt .Sprintf ("%s/v1/public-key" , tm .SigningServerUrl ())
254
346
347
+ httpRequest , err = http .NewRequestWithContext (context .Background (), "GET" , pkRoute , nil )
348
+ require .NoError (t , err )
349
+
350
+ res , err = client .Do (httpRequest )
351
+ require .NoError (t , err )
352
+ defer res .Body .Close ()
353
+ require .Equal (t , http .StatusUnauthorized , res .StatusCode , "Public key request without HMAC should fail with 401" )
354
+
355
+ emptyBody := []byte {}
356
+ hmacValue , err = middlewares .GenerateHMAC (testHMACKey , emptyBody )
357
+ require .NoError (t , err )
358
+
359
+ httpRequest , err = http .NewRequestWithContext (context .Background (), "GET" , pkRoute , nil )
360
+ require .NoError (t , err )
361
+ httpRequest .Header .Set (middlewares .HeaderCovenantHMAC , hmacValue )
362
+
363
+ res , err = client .Do (httpRequest )
364
+ require .NoError (t , err )
365
+ defer res .Body .Close ()
366
+ require .Equal (t , http .StatusOK , res .StatusCode , "Public key request with valid HMAC should succeed" )
367
+
368
+ var respData map [string ]interface {}
369
+ err = json .NewDecoder (res .Body ).Decode (& respData )
370
+ require .NoError (t , err , "Should receive valid JSON response" )
371
+
372
+ dataObj , exists := respData ["data" ]
373
+ require .True (t , exists , "Response should contain a 'data' object" )
374
+
375
+ dataMap , ok := dataObj .(map [string ]interface {})
376
+ require .True (t , ok , "Data should be an object" )
377
+
378
+ _ , exists = dataMap ["public_key_hex" ]
379
+ require .True (t , exists , "Response should contain a public key" )
380
+ }
381
+
382
+ func TestHMACMismatchedKeys (t * testing.T ) {
383
+ // Test scenario where client and server have different HMAC keys
384
+ serverKey := "server-hmac-key"
385
+ clientKey := "different-client-hmac-key"
386
+
387
+ tm := StartManager (t , 100 , false , serverKey )
388
+
389
+ err := signerservice .Unlock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "" , clientKey )
390
+ require .Error (t , err , "Unlock should fail with mismatched HMAC keys" )
391
+ require .Contains (t , err .Error (), "401" , "Error should be a 401 Unauthorized" )
392
+
393
+ _ , err = signerservice .GetPublicKey (context .Background (), tm .SigningServerUrl (), 10 * time .Second , clientKey )
394
+ require .Error (t , err , "GetPublicKey should require HMAC" )
395
+ require .Contains (t , err .Error (), "401" , "Error should be a 401 Unauthorized" )
396
+
397
+ err = signerservice .Unlock (context .Background (), tm .SigningServerUrl (), 10 * time .Second , "" , serverKey )
398
+ require .NoError (t , err , "Unlock should succeed with matching HMAC key" )
399
+
400
+ route := fmt .Sprintf ("%s/v1/public-key" , tm .SigningServerUrl ())
401
+ httpRequest , err := http .NewRequestWithContext (context .Background (), "GET" , route , nil )
402
+ require .NoError (t , err )
403
+
404
+ hmacValue , err := middlewares .GenerateHMAC (serverKey , []byte {})
405
+ require .NoError (t , err )
406
+ httpRequest .Header .Set (middlewares .HeaderCovenantHMAC , hmacValue )
407
+
408
+ client := http.Client {Timeout : 10 * time .Second }
409
+ res , err := client .Do (httpRequest )
410
+ require .NoError (t , err )
411
+ defer res .Body .Close ()
412
+ require .Equal (t , http .StatusOK , res .StatusCode , "Request with valid HMAC should succeed" )
255
413
}
0 commit comments