@@ -282,4 +282,210 @@ describe('DKLS Dkg 2x3', function () {
282282 assert . deepEqual ( DklsTypes . getCommonKeychain ( userKeyShare ) , DklsTypes . getCommonKeychain ( bitgoKeyShare ) ) ;
283283 assert . deepEqual ( DklsTypes . getCommonKeychain ( backupKeyShare ) , DklsTypes . getCommonKeychain ( bitgoKeyShare ) ) ;
284284 } ) ;
285+
286+ it ( 'should successfully finish DKG using restored sessions' , async function ( ) {
287+ const user = new DklsDkg . Dkg ( 3 , 2 , 0 ) ;
288+ const backup = new DklsDkg . Dkg ( 3 , 2 , 1 ) ;
289+ const bitgo = new DklsDkg . Dkg ( 3 , 2 , 2 ) ;
290+
291+ // Generate GPG keys for authenticated encryption
292+ openpgp . config . rejectCurves = new Set ( ) ;
293+ const userKey = await openpgp . generateKey ( {
294+ userIDs :
[ { name :
'user' , email :
'[email protected] ' } ] , 295+ curve : 'secp256k1' ,
296+ } ) ;
297+ const bitgoKey = await openpgp . generateKey ( {
298+ userIDs :
[ { name :
'bitgo' , email :
'[email protected] ' } ] , 299+ curve : 'secp256k1' ,
300+ } ) ;
301+ const backupKey = await openpgp . generateKey ( {
302+ userIDs :
[ { name :
'backup' , email :
'[email protected] ' } ] , 303+ curve : 'secp256k1' ,
304+ } ) ;
305+
306+ const userGpgPubKey : PartyGpgKey = { partyId : 0 , gpgKey : userKey . publicKey } ;
307+ const userGpgPrvKey : PartyGpgKey = { partyId : 0 , gpgKey : userKey . privateKey } ;
308+ const bitgoGpgPubKey : PartyGpgKey = { partyId : 2 , gpgKey : bitgoKey . publicKey } ;
309+ const bitgoGpgPrvKey : PartyGpgKey = { partyId : 2 , gpgKey : bitgoKey . privateKey } ;
310+ const backupGpgPubKey : PartyGpgKey = { partyId : 1 , gpgKey : backupKey . publicKey } ;
311+ const backupGpgPrvKey : PartyGpgKey = { partyId : 1 , gpgKey : backupKey . privateKey } ;
312+
313+ // Initialize DKG and get first round messages
314+ const userRound1Message = await user . initDkg ( ) ;
315+ const backupRound1Message = await backup . initDkg ( ) ;
316+ const bitgoRound1Message = await bitgo . initDkg ( ) ;
317+
318+ // Process round 1 messages to advance to round 2
319+ let serializedMessages = serializeMessages ( {
320+ broadcastMessages : [ userRound1Message , backupRound1Message ] ,
321+ p2pMessages : [ ] ,
322+ } ) ;
323+
324+ let authEncMessages = await encryptAndAuthOutgoingMessages (
325+ serializedMessages ,
326+ [ bitgoGpgPubKey ] ,
327+ [ userGpgPrvKey , backupGpgPrvKey ]
328+ ) ;
329+
330+ const restoredRound1User = await DklsDkg . Dkg . restoreSession ( 3 , 2 , 0 , user . getSessionData ( ) ) ;
331+ const restoredRound1Backup = await DklsDkg . Dkg . restoreSession ( 3 , 2 , 1 , backup . getSessionData ( ) ) ;
332+ const restoredRound1Bitgo = await DklsDkg . Dkg . restoreSession ( 3 , 2 , 2 , bitgo . getSessionData ( ) ) ;
333+
334+ // Round 2
335+ const userRound2Messages = restoredRound1User . handleIncomingMessages ( {
336+ p2pMessages : [ ] ,
337+ broadcastMessages : [ bitgoRound1Message , backupRound1Message ] ,
338+ } ) ;
339+ const userRound2Data = restoredRound1User . getSessionData ( ) ;
340+
341+ const backupRound2Messages = restoredRound1Backup . handleIncomingMessages ( {
342+ p2pMessages : [ ] ,
343+ broadcastMessages : [ userRound1Message , bitgoRound1Message ] ,
344+ } ) ;
345+ const backupRound2Data = restoredRound1Backup . getSessionData ( ) ;
346+
347+ const decryptedMessages = await decryptAndVerifyIncomingMessages (
348+ authEncMessages ,
349+ [ userGpgPubKey , backupGpgPubKey ] ,
350+ [ bitgoGpgPrvKey ]
351+ ) ;
352+
353+ const deserializedDecryptedMessages = deserializeMessages ( decryptedMessages ) ;
354+ const bitgoRound2Messages = restoredRound1Bitgo . handleIncomingMessages ( deserializedDecryptedMessages ) ;
355+ const bitgoRound2Data = restoredRound1Bitgo . getSessionData ( ) ;
356+
357+ // Restore sessions for Round 3
358+ const restoredRound2User = await DklsDkg . Dkg . restoreSession ( 3 , 2 , 0 , userRound2Data ) ;
359+ const restoredRound2Backup = await DklsDkg . Dkg . restoreSession ( 3 , 2 , 1 , backupRound2Data ) ;
360+ const restoredRound2Bitgo = await DklsDkg . Dkg . restoreSession ( 3 , 2 , 2 , bitgoRound2Data ) ;
361+
362+ // Round 3
363+ const restoredUserRound3Messages = restoredRound2User . handleIncomingMessages ( {
364+ p2pMessages : backupRound2Messages . p2pMessages
365+ . filter ( ( m ) => m . to === 0 )
366+ . concat ( bitgoRound2Messages . p2pMessages . filter ( ( m ) => m . to === 0 ) ) ,
367+ broadcastMessages : [ ] ,
368+ } ) ;
369+ const userRound3Data = restoredRound2User . getSessionData ( ) ;
370+
371+ const restoredBackupRound3Messages = restoredRound2Backup . handleIncomingMessages ( {
372+ p2pMessages : bitgoRound2Messages . p2pMessages
373+ . filter ( ( m ) => m . to === 1 )
374+ . concat ( userRound2Messages . p2pMessages . filter ( ( m ) => m . to === 1 ) ) ,
375+ broadcastMessages : [ ] ,
376+ } ) ;
377+ const backupRound3Data = restoredRound2Backup . getSessionData ( ) ;
378+
379+ // Encrypt messages for bitgo
380+ serializedMessages = serializeMessages ( {
381+ broadcastMessages : [ ] ,
382+ p2pMessages : userRound2Messages . p2pMessages
383+ . filter ( ( m ) => m . to === 2 )
384+ . concat ( backupRound2Messages . p2pMessages . filter ( ( m ) => m . to === 2 ) ) ,
385+ } ) ;
386+
387+ authEncMessages = await encryptAndAuthOutgoingMessages (
388+ serializedMessages ,
389+ [ bitgoGpgPubKey ] ,
390+ [ userGpgPrvKey , backupGpgPrvKey ]
391+ ) ;
392+
393+ const restoredBitgoRound3Messages = restoredRound2Bitgo . handleIncomingMessages (
394+ deserializeMessages (
395+ await decryptAndVerifyIncomingMessages ( authEncMessages , [ userGpgPubKey , backupGpgPubKey ] , [ bitgoGpgPrvKey ] )
396+ )
397+ ) ;
398+ const bitgoRound3Data = restoredRound2Bitgo . getSessionData ( ) ;
399+
400+ // Restore sessions for Round 4
401+ const restoredRound3User = await DklsDkg . Dkg . restoreSession ( 3 , 2 , 0 , userRound3Data ) ;
402+ const restoredRound3Backup = await DklsDkg . Dkg . restoreSession ( 3 , 2 , 1 , backupRound3Data ) ;
403+ const restoredRound3Bitgo = await DklsDkg . Dkg . restoreSession ( 3 , 2 , 2 , bitgoRound3Data ) ;
404+
405+ // Round 4
406+ const restoredUserRound4Messages = restoredRound3User . handleIncomingMessages ( {
407+ p2pMessages : restoredBackupRound3Messages . p2pMessages
408+ . filter ( ( m ) => m . to === 0 )
409+ . concat ( restoredBitgoRound3Messages . p2pMessages . filter ( ( m ) => m . to === 0 ) ) ,
410+ broadcastMessages : [ ] ,
411+ } ) ;
412+ const userRound4Data = restoredRound3User . getSessionData ( ) ;
413+
414+ const restoredBackupRound4Messages = restoredRound3Backup . handleIncomingMessages ( {
415+ p2pMessages : restoredBitgoRound3Messages . p2pMessages
416+ . filter ( ( m ) => m . to === 1 )
417+ . concat ( restoredUserRound3Messages . p2pMessages . filter ( ( m ) => m . to === 1 ) ) ,
418+ broadcastMessages : [ ] ,
419+ } ) ;
420+ const backupRound4Data = restoredRound3Backup . getSessionData ( ) ;
421+
422+ serializedMessages = serializeMessages ( {
423+ broadcastMessages : [ ] ,
424+ p2pMessages : restoredUserRound3Messages . p2pMessages
425+ . filter ( ( m ) => m . to === 2 )
426+ . concat ( restoredBackupRound3Messages . p2pMessages . filter ( ( m ) => m . to === 2 ) ) ,
427+ } ) ;
428+
429+ authEncMessages = await encryptAndAuthOutgoingMessages (
430+ serializedMessages ,
431+ [ bitgoGpgPubKey ] ,
432+ [ userGpgPrvKey , backupGpgPrvKey ]
433+ ) ;
434+
435+ const restoredBitgoRound4Messages = restoredRound3Bitgo . handleIncomingMessages (
436+ deserializeMessages (
437+ await decryptAndVerifyIncomingMessages ( authEncMessages , [ userGpgPubKey , backupGpgPubKey ] , [ bitgoGpgPrvKey ] )
438+ )
439+ ) ;
440+ const bitgoRound4Data = restoredRound3Bitgo . getSessionData ( ) ;
441+
442+ // Restore sessions for final messages
443+ const restoredRound4User = await DklsDkg . Dkg . restoreSession ( 3 , 2 , 0 , userRound4Data ) ;
444+ const restoredRound4Backup = await DklsDkg . Dkg . restoreSession ( 3 , 2 , 1 , backupRound4Data ) ;
445+ const restoredRound4Bitgo = await DklsDkg . Dkg . restoreSession ( 3 , 2 , 2 , bitgoRound4Data ) ;
446+
447+ // Final messages
448+ restoredRound4User . handleIncomingMessages ( {
449+ p2pMessages : [ ] ,
450+ broadcastMessages : restoredBitgoRound4Messages . broadcastMessages . concat (
451+ restoredBackupRound4Messages . broadcastMessages
452+ ) ,
453+ } ) ;
454+
455+ serializedMessages = serializeMessages ( {
456+ broadcastMessages : restoredBackupRound4Messages . broadcastMessages . concat (
457+ restoredUserRound4Messages . broadcastMessages
458+ ) ,
459+ p2pMessages : [ ] ,
460+ } ) ;
461+
462+ authEncMessages = await encryptAndAuthOutgoingMessages (
463+ serializedMessages ,
464+ [ bitgoGpgPubKey ] ,
465+ [ userGpgPrvKey , backupGpgPrvKey ]
466+ ) ;
467+
468+ restoredRound4Bitgo . handleIncomingMessages (
469+ deserializeMessages (
470+ await decryptAndVerifyIncomingMessages ( authEncMessages , [ userGpgPubKey , backupGpgPubKey ] , [ bitgoGpgPrvKey ] )
471+ )
472+ ) ;
473+
474+ restoredRound4Backup . handleIncomingMessages ( {
475+ p2pMessages : [ ] ,
476+ broadcastMessages : restoredBitgoRound4Messages . broadcastMessages . concat (
477+ restoredUserRound4Messages . broadcastMessages
478+ ) ,
479+ } ) ;
480+
481+ // Verify key shares
482+ const userKeyShare = restoredRound4User . getKeyShare ( ) ;
483+ const backupKeyShare = restoredRound4Backup . getKeyShare ( ) ;
484+ const bitgoKeyShare = restoredRound4Bitgo . getKeyShare ( ) ;
485+
486+ assert . deepEqual ( decode ( userKeyShare ) . public_key , decode ( bitgoKeyShare ) . public_key ) ;
487+ assert . deepEqual ( decode ( backupKeyShare ) . public_key , decode ( bitgoKeyShare ) . public_key ) ;
488+ assert . deepEqual ( DklsTypes . getCommonKeychain ( userKeyShare ) , DklsTypes . getCommonKeychain ( bitgoKeyShare ) ) ;
489+ assert . deepEqual ( DklsTypes . getCommonKeychain ( backupKeyShare ) , DklsTypes . getCommonKeychain ( bitgoKeyShare ) ) ;
490+ } ) ;
285491} ) ;
0 commit comments