11/* eslint-disable @typescript-eslint/member-ordering */
22import { BNString , encrypt , getPubKeyPoint , Point as TkeyPoint , SHARE_DELETED , ShareStore , StringifiedType } from "@tkey-mpc/common-types" ;
3- import ThresholdKey , { CoreError } from "@tkey-mpc/core" ;
3+ import ThresholdKey , { CoreError , lagrangeInterpolation } from "@tkey-mpc/core" ;
44import { TorusServiceProvider } from "@tkey-mpc/service-provider-torus" ;
55import { ShareSerializationModule } from "@tkey-mpc/share-serialization" ;
66import { TorusStorageLayer } from "@tkey-mpc/storage-layer-torus" ;
@@ -207,6 +207,39 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
207207 return this . options . uxMode === UX_MODE . REDIRECT ;
208208 }
209209
210+ // RecoverTssKey only valid for user that enable MFA where user has 2 type shares :
211+ // TssShareType.DEVICE and TssShareType.RECOVERY
212+ // if the factors key provided is the same type recovery will not works
213+ public async _UNSAFE_recoverTssKey ( factorKey : string [ ] ) {
214+ this . checkReady ( ) ;
215+ const factorKeyBN = new BN ( factorKey [ 0 ] , "hex" ) ;
216+ const shareStore0 = await this . getFactorKeyMetadata ( factorKeyBN ) ;
217+ await this . tKey . initialize ( { withShare : shareStore0 } ) ;
218+
219+ this . tkey . privKey = new BN ( factorKey [ 1 ] , "hex" ) ;
220+
221+ const tssShares : BN [ ] = [ ] ;
222+ const tssIndexes : number [ ] = [ ] ;
223+ const tssIndexesBN : BN [ ] = [ ] ;
224+ for ( let i = 0 ; i < factorKey . length ; i ++ ) {
225+ const factorKeyBNInput = new BN ( factorKey [ i ] , "hex" ) ;
226+ const { tssIndex, tssShare } = await this . tKey . getTSSShare ( factorKeyBNInput ) ;
227+ if ( tssIndexes . includes ( tssIndex ) ) {
228+ // reset instance before throw error
229+ await this . init ( ) ;
230+ throw new Error ( "Duplicate TSS Index" ) ;
231+ }
232+ tssIndexes . push ( tssIndex ) ;
233+ tssIndexesBN . push ( new BN ( tssIndex ) ) ;
234+ tssShares . push ( tssShare ) ;
235+ }
236+
237+ const finalKey = lagrangeInterpolation ( tssShares , tssIndexesBN ) ;
238+ // reset instance after recovery completed
239+ await this . init ( ) ;
240+ return finalKey . toString ( "hex" , 64 ) ;
241+ }
242+
210243 public async init ( params : InitParams = { handleRedirectResult : true } ) : Promise < void > {
211244 this . resetState ( ) ;
212245 if ( params . rehydrate === undefined ) params . rehydrate = true ;
@@ -274,7 +307,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
274307 public async loginWithOauth ( params : OauthLoginParams ) : Promise < void > {
275308 this . checkReady ( ) ;
276309 if ( this . isNodejsOrRN ( this . options . uxMode ) ) throw new Error ( `Oauth login is NOT supported in ${ this . options . uxMode } ` ) ;
277-
310+ const { importTssKey } = params ;
278311 const tkeyServiceProvider = this . tKey . serviceProvider as TorusServiceProvider ;
279312 try {
280313 // oAuth login.
@@ -307,7 +340,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
307340 } ) ;
308341 }
309342
310- await this . setupTkey ( ) ;
343+ await this . setupTkey ( importTssKey ) ;
311344 } catch ( err : unknown ) {
312345 log . error ( "login error" , err ) ;
313346 if ( err instanceof CoreError ) {
@@ -319,7 +352,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
319352
320353 public async loginWithJWT ( idTokenLoginParams : IdTokenLoginParams ) : Promise < void > {
321354 this . checkReady ( ) ;
322-
355+ const { importTssKey } = idTokenLoginParams ;
323356 const { verifier, verifierId, idToken } = idTokenLoginParams ;
324357 try {
325358 // oAuth login.
@@ -357,7 +390,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
357390 signatures : this . _getSignatures ( loginResponse . sessionData . sessionTokenData ) ,
358391 } ) ;
359392
360- await this . setupTkey ( ) ;
393+ await this . setupTkey ( importTssKey ) ;
361394 } catch ( err : unknown ) {
362395 log . error ( "login error" , err ) ;
363396 if ( err instanceof CoreError ) {
@@ -758,7 +791,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
758791 if ( ! this . state . signatures ) throw new Error ( "signatures not present" ) ;
759792
760793 const tssKeyBN = new BN ( tssKey , "hex" ) ;
761- this . tKey . importTssKey ( { tag : this . tKey . tssTag , importKey : tssKeyBN , factorPub, newTSSIndex } , { authSignatures : this . state . signatures } ) ;
794+ await this . tKey . importTssKey ( { tag : this . tKey . tssTag , importKey : tssKeyBN , factorPub, newTSSIndex } , { authSignatures : this . state . signatures } ) ;
762795 }
763796
764797 public async _UNSAFE_exportTssKey ( ) : Promise < string > {
@@ -780,7 +813,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
780813 return tssNonce ;
781814 }
782815
783- private async setupTkey ( ) : Promise < void > {
816+ private async setupTkey ( importTssKey ?: string ) : Promise < void > {
784817 if ( ! this . state . oAuthKey ) {
785818 throw new Error ( "user not logged in" ) ;
786819 }
@@ -797,10 +830,15 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
797830 } else {
798831 factorKey = getHashedPrivateKey ( this . state . oAuthKey , this . options . hashedFactorNonce ) ;
799832 }
800- const deviceTSSShare = new BN ( generatePrivate ( ) ) ;
801833 const deviceTSSIndex = TssShareType . DEVICE ;
802834 const factorPub = getPubKeyPoint ( factorKey ) ;
803- await this . tKey . initialize ( { useTSS : true , factorPub, deviceTSSShare, deviceTSSIndex } ) ;
835+ if ( ! importTssKey ) {
836+ const deviceTSSShare = new BN ( generatePrivate ( ) ) ;
837+ await this . tKey . initialize ( { useTSS : true , factorPub, deviceTSSShare, deviceTSSIndex } ) ;
838+ } else {
839+ await this . tKey . initialize ( ) ;
840+ await this . importTssKey ( importTssKey , factorPub , deviceTSSIndex ) ;
841+ }
804842
805843 // Finalize initialization.
806844 await this . tKey . reconstructKey ( ) ;
@@ -814,6 +852,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
814852 await this . addFactorDescription ( factorKey , FactorKeyTypeShareDescription . HashedShare ) ;
815853 }
816854 } else {
855+ if ( importTssKey ) throw new Error ( "Cannot import tss key for existing user" ) ;
817856 await this . tKey . initialize ( { neverInitializeNewKey : true } ) ;
818857 const hashedFactorKey = getHashedPrivateKey ( this . state . oAuthKey , this . options . hashedFactorNonce ) ;
819858 if ( ( await this . checkIfFactorKeyValid ( hashedFactorKey ) ) && ! this . options . disableHashedFactorKey ) {
0 commit comments