Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,15 +199,20 @@
**/
status: COREKIT_STATUS;

/**
* True only during new user sign up. After reinit or rehydration this is always false.
*/
isNewUser(): boolean;

/**
* The current sdk state.
*/
state: Web3AuthState;

Check warning on line 210 in src/interfaces.ts

View workflow job for this annotation

GitHub Actions / run tests (20.x, ubuntu-latest)

Member state should be declared before all method definitions

/**
* The current session id.
*/
sessionId: string;

Check warning on line 215 in src/interfaces.ts

View workflow job for this annotation

GitHub Actions / run tests (20.x, ubuntu-latest)

Member sessionId should be declared before all method definitions

/**
* The function used to initailise the state of MPCCoreKit
Expand Down
16 changes: 16 additions & 0 deletions src/mpcCoreKit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@

private ready = false;

// only true during new user sign up; after reinit or rehydration this is always false
private newUser: boolean = false;

private _tssLib: TssLibType;

private wasmLib: DKLSWasmLib | FrostWasmLib;
Expand Down Expand Up @@ -193,22 +196,26 @@
return this._keyType !== KeyType.ed25519;
}

public isNewUser(): boolean {
return this.newUser;
}

private get verifier(): string {

Check warning on line 203 in src/mpcCoreKit.ts

View workflow job for this annotation

GitHub Actions / run tests (20.x, ubuntu-latest)

Member verifier should be declared before all public instance method definitions
if (this.state.userInfo?.aggregateVerifier) {
return this.state.userInfo.aggregateVerifier;
}
return this.state?.userInfo?.verifier ? this.state.userInfo.verifier : "";
}

private get verifierId(): string {

Check warning on line 210 in src/mpcCoreKit.ts

View workflow job for this annotation

GitHub Actions / run tests (20.x, ubuntu-latest)

Member verifierId should be declared before all public instance method definitions
return this.state?.userInfo?.verifierId ? this.state.userInfo.verifierId : "";
}

private get isRedirectMode(): boolean {

Check warning on line 214 in src/mpcCoreKit.ts

View workflow job for this annotation

GitHub Actions / run tests (20.x, ubuntu-latest)

Member isRedirectMode should be declared before all public instance method definitions
return this.options.uxMode === UX_MODE.REDIRECT;
}

private get useClientGeneratedTSSKey(): boolean {

Check warning on line 218 in src/mpcCoreKit.ts

View workflow job for this annotation

GitHub Actions / run tests (20.x, ubuntu-latest)

Member useClientGeneratedTSSKey should be declared before all public instance method definitions
return this.keyType === KeyType.ed25519 && this.options.useClientGeneratedTSSKey === undefined ? true : !!this.options.useClientGeneratedTSSKey;
}

Expand Down Expand Up @@ -1093,6 +1100,7 @@

// 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;
Expand Down Expand Up @@ -1146,6 +1154,7 @@
}

private async handleExistingUser() {
this.newUser = false;
await this.tKey.initialize({ neverInitializeNewKey: true });
if (this.options.disableHashedFactorKey) {
return;
Expand Down Expand Up @@ -1283,6 +1292,12 @@

private async checkIfFactorKeyValid(factorKey: BN): Promise<boolean> {
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<StringifiedType>(factorKey);
if (!factorKeyMetadata || factorKeyMetadata.message === "KEY_NOT_FOUND" || factorKeyMetadata.message === "SHARE_DELETED") {
return false;
Expand Down Expand Up @@ -1403,6 +1418,7 @@
this.tkey = null;
this.torusSp = null;
this.storageLayer = null;
this.newUser = false;
this.state = { accountIndex: 0 };
}

Expand Down
53 changes: 44 additions & 9 deletions tests/factors.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import assert from "node:assert";
import test from "node:test";

import { EllipticPoint, KeyType, Point, secp256k1 } from "@tkey/common-types";
import { factorKeyCurve } from "@tkey/tss";
import { factorKeyCurve, getPubKeyPoint } from "@tkey/tss";
import { tssLib as tssLibDKLS } from "@toruslabs/tss-dkls-lib";
import { tssLib as tssLibFROST } from "@toruslabs/tss-frost-lib";
import BN from "bn.js";
Expand Down Expand Up @@ -83,6 +83,20 @@ export const FactorManipulationTest = async (testVariable: FactorTestVariable) =
await test(`#Factor manipulation - manualSync ${testVariable.manualSync} `, async function (t) {
await beforeTest();

await t.test("hashed factor auto login", async function () {
const instance = await newInstance();
assert.strictEqual(instance.status, COREKIT_STATUS.LOGGED_IN);
assert.strictEqual(instance.getTssFactorPub().length, 1);
if (testVariable.manualSync) {
await instance.commitChanges();
}
await instance.logout();

const instance2 = await newInstance();
assert.strictEqual(instance2.status, COREKIT_STATUS.LOGGED_IN);
assert.strictEqual(instance2.getTssFactorPub().length, 1);
});

await t.test("should be able to create factor", async function () {
const coreKitInstance = await newInstance();
assert.equal(coreKitInstance.status, COREKIT_STATUS.LOGGED_IN);
Expand Down Expand Up @@ -158,7 +172,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);
Expand All @@ -179,7 +193,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")

Expand All @@ -195,24 +209,45 @@ export const FactorManipulationTest = async (testVariable: FactorTestVariable) =



try {
await assert.rejects(async () => {
await instance3.inputFactorKey(factorBN.subn(1));
throw Error("should not be able to input factor");
} catch (e) {
assert(e instanceof Error);
}
});

await instance3.inputFactorKey(new BN(browserFactor, "hex"));
assert.strictEqual(instance3.status, COREKIT_STATUS.LOGGED_IN);

await assert.rejects(async () => {
await instance3.enableMFA({});
}, /MFA is already enabled/);

if ( tssLib && tssLib.keyType === KeyType.ed25519) {
await signEd25519Data({ coreKitInstance: instance3, msg: "hello world" });
} 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, factorKeyCurve);
await instance.deleteFactor(deviceFactorPub, browserFactor);

await assert.rejects(async () => {
await instance.inputFactorKey(deviceFactorKeyBN);
});
});
});
};

Expand Down
Loading