diff --git a/src/mpcCoreKit.ts b/src/mpcCoreKit.ts index 3cae7ff..01774c2 100644 --- a/src/mpcCoreKit.ts +++ b/src/mpcCoreKit.ts @@ -86,6 +86,10 @@ export class Web3AuthMPCCoreKit implements ICoreKit { public torusSp: TSSTorusServiceProvider | null = null; + // new user indication + // only true during new user sign up, after reinit or rehydration, the flag will be always false + public newUser: boolean = false; + private options: Web3AuthOptionsWithDefaults; private storageLayer: TorusStorageLayer | null = null; @@ -1093,6 +1097,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit { // mutation function private async handleNewUser(importTssKey?: string, isSfaKey?: boolean) { + this.newUser = true; await this.atomicSync(async () => { // Generate or use hash factor and initialize tkey with it. let factorKey: BN; @@ -1146,6 +1151,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit { } private async handleExistingUser() { + this.newUser = false; await this.tKey.initialize({ neverInitializeNewKey: true }); if (this.options.disableHashedFactorKey) { return; @@ -1283,6 +1289,12 @@ export class Web3AuthMPCCoreKit implements ICoreKit { private async checkIfFactorKeyValid(factorKey: BN): Promise { this.checkReady(); + const factorKeyPrivate = factorKeyCurve.keyFromPrivate(factorKey.toBuffer()); + const factorPubX = factorKeyPrivate.getPublic().getX().toString("hex").padStart(64, "0"); + const existingFactorEnc = this.tkey.metadata.factorEncs?.[this.tkey.tssTag]?.[factorPubX]; + if (!existingFactorEnc) { + return false; + } const factorKeyMetadata = await this.tKey?.readMetadata(factorKey); if (!factorKeyMetadata || factorKeyMetadata.message === "KEY_NOT_FOUND" || factorKeyMetadata.message === "SHARE_DELETED") { return false; @@ -1403,6 +1415,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit { this.tkey = null; this.torusSp = null; this.storageLayer = null; + this.newUser = false; this.state = { accountIndex: 0 }; } diff --git a/tests/factors.spec.ts b/tests/factors.spec.ts index 539e892..659802b 100644 --- a/tests/factors.spec.ts +++ b/tests/factors.spec.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import test from "node:test"; -import { EllipticPoint, KeyType, Point, secp256k1 } from "@tkey/common-types"; +import { EllipticPoint, getPubKeyPoint, KeyType, Point, secp256k1 } from "@tkey/common-types"; import { factorKeyCurve } from "@tkey/tss"; import { tssLib as tssLibDKLS } from "@toruslabs/tss-dkls-lib"; import { tssLib as tssLibFROST } from "@toruslabs/tss-frost-lib"; @@ -158,7 +158,7 @@ export const FactorManipulationTest = async (testVariable: FactorTestVariable) = }); // enable mfa - + let browserFactor: string; await t.test("enable MFA", async function () { const instance = await newInstance(); assert.strictEqual(instance.status, COREKIT_STATUS.LOGGED_IN); @@ -179,7 +179,7 @@ export const FactorManipulationTest = async (testVariable: FactorTestVariable) = const instance2 = await newInstance(); assert.strictEqual(instance2.status, COREKIT_STATUS.REQUIRED_SHARE); - const browserFactor = await instance2.getDeviceFactor(); + browserFactor = await instance2.getDeviceFactor(); const factorBN = new BN(recoverFactor, "hex") @@ -210,9 +210,32 @@ export const FactorManipulationTest = async (testVariable: FactorTestVariable) = } else { await signSecp256k1Data({ coreKitInstance: instance3, msg: "hello world" }); } - }); + // replace factor + await t.test("replace factor", async function () { + const instance = await newInstance(); + + const deviceFactorKeyBN = new BN(browserFactor, "hex") + await instance.inputFactorKey(deviceFactorKeyBN); + assert.strictEqual(instance.status, COREKIT_STATUS.LOGGED_IN); + + const newFactorkey = await instance.createFactor({ shareType: TssShareType.DEVICE }); + await instance.inputFactorKey(new BN(newFactorkey, "hex")); + + assert.strictEqual(instance.status, COREKIT_STATUS.LOGGED_IN); + + + const deviceFactorPub = getPubKeyPoint(deviceFactorKeyBN); + await instance.deleteFactor(deviceFactorPub, browserFactor); + + try { + await instance.inputFactorKey(deviceFactorKeyBN); + throw Error("should not be able to deleted input factor"); + } catch (e) { + assert(e instanceof Error); + } + }); }); };