Skip to content
Draft
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
310 changes: 252 additions & 58 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,22 @@
},
"dependencies": {
"@tkey/common-types": "^15.1.0",
"@tkey/core": "^15.1.0",
"@tkey/core": "^15.2.0-alpha.0",
"@tkey/share-serialization": "^15.1.0",
"@tkey/storage-layer-torus": "^15.1.0",
"@tkey/tss": "^15.1.0",
"@tkey/tss": "^15.2.0-alpha.0",
"@toruslabs/constants": "^14.0.0",
"@toruslabs/customauth": "^20.3.0",
"@toruslabs/elliptic-wrapper": "^0.1.0",
"@toruslabs/fetch-node-details": "^14.0.1",
"@toruslabs/fnd-base": "^14.0.0",
"@toruslabs/metadata-helpers": "^6.0.0",
"@toruslabs/session-manager": "^3.1.0",
"@toruslabs/openlogin-utils": "^8.2.1",
"@toruslabs/torus.js": "^15.1.0",
"@toruslabs/tss-client": "^3.1.0",
"@toruslabs/tss-frost-client": "0.3.1",
"@toruslabs/tss-frost-common": "^1.0.1",
"@web3auth/auth": "^9.4.1",
"bn.js": "^5.2.1",
"bowser": "^2.11.0",
"elliptic": "^6.5.7",
Expand Down
16 changes: 13 additions & 3 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { KeyType, Point as TkeyPoint, ShareDescriptionMap } from "@tkey/common-types";
import { BNString, KeyType, Point as TkeyPoint, ShareDescriptionMap } from "@tkey/common-types";
import { TKeyTSS } from "@tkey/tss";
import type {
AGGREGATE_VERIFIER_TYPE,
Expand Down Expand Up @@ -92,7 +92,7 @@ export interface EnableMFAParams {
/**
* A BN used for encrypting your Device/ Recovery TSS Key Share. You can generate it using `generateFactorKey()` function or use an existing one.
*/
factorKey?: BN;
factorKey?: BNString;
/**
* Setting the Description of Share - Security Questions, Device Share, Seed Phrase, Password Share, Social Share, Other. Default is Other.
*/
Expand Down Expand Up @@ -229,7 +229,7 @@ export interface ICoreKit {
* Share. You can generate it using `generateFactorKey()` function or use an
* existing one.
*/
inputFactorKey(factorKey: BN): Promise<void>;
inputFactorKey(factorKey: BNString): Promise<void>;

/**
* Returns the current Factor Key and TssShareType in MPC Core Kit State
Expand Down Expand Up @@ -266,6 +266,16 @@ export interface ICoreKit {
*/
getKeyDetails(): MPCKeyDetails;

/**
* Get specific general domain's metadata which is used by plugin or modules.
*/
getGeneralStoreDomain<T>(domain: string): T;

/**
* Set specific general domain's metadata which is used by plugin or modules.
*/
setGeneralStoreDomain<T>(domain: string, value: T): void;

/**
* Commit the changes made to the user's account when in manual sync mode.
*/
Expand Down
84 changes: 74 additions & 10 deletions src/mpcCoreKit.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { BNString, KeyType, Point, secp256k1, SHARE_DELETED, ShareStore, StringifiedType } from "@tkey/common-types";
import { CoreError } from "@tkey/core";
import { ShareSerializationModule } from "@tkey/share-serialization";
import { TorusStorageLayer } from "@tkey/storage-layer-torus";
import { factorKeyCurve, getPubKeyPoint, lagrangeInterpolation, TKeyTSS, TSSTorusServiceProvider } from "@tkey/tss";
import { KEY_TYPE, SIGNER_MAP } from "@toruslabs/constants";
Expand Down Expand Up @@ -112,7 +111,10 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
if (options.enableLogging) {
log.enableAll();
this.enableLogging = true;
} else log.setLevel("error");
} else {
log.setLevel("error");
options.enableLogging = false;
}
if (typeof options.manualSync !== "boolean") options.manualSync = false;
if (!options.web3AuthNetwork) options.web3AuthNetwork = WEB3AUTH_NETWORK.MAINNET;
// if sessionTime is not provided, it is defaulted to 86400
Expand Down Expand Up @@ -197,6 +199,56 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
return this.keyType === KeyType.ed25519 && this.options.useClientGeneratedTSSKey === undefined ? true : !!this.options.useClientGeneratedTSSKey;
}

static async fromJSON(value: StringifiedType, options: Web3AuthOptions): Promise<Web3AuthMPCCoreKit> {
const coreKit = new Web3AuthMPCCoreKit(options);
const { state, serviceProvider, storageLayer, keyType, atomicCallStackCounter, ready, sessionId, tkey } = value;
coreKit.torusSp = TSSTorusServiceProvider.fromJSON(serviceProvider);
coreKit.storageLayer = TorusStorageLayer.fromJSON(storageLayer);

coreKit.tkey = await TKeyTSS.fromJSON(tkey, {
serviceProvider: coreKit.torusSp,
storageLayer: coreKit.storageLayer,
enableLogging: options.enableLogging,
tssKeyType: options.tssLib.keyType as KeyType,
});
await coreKit.tkey.reconstructKey();

if (state.factorKey) state.factorKey = new BN(state.factorKey, "hex");
if (state.tssPubKey) state.tssPubKey = Buffer.from(state.tssPubKey, "hex");
coreKit.state = state;
coreKit.sessionManager.sessionId = sessionId;
coreKit.atomicCallStackCounter = atomicCallStackCounter;
coreKit.ready = ready;

if (coreKit._keyType !== keyType) {
throw CoreKitError.invalidConfig();
}

// will be derived from option during constructor
// sessionManager
// enableLogging
// private _tssLib: TssLibType;
// private wasmLib: DKLSWasmLib | FrostWasmLib;
// private _keyType: KeyType;
return coreKit;
}

public toJSON(): StringifiedType {
const factorKey = this.state.factorKey ? this.state.factorKey.toString("hex") : undefined;
const tssPubKey = this.state.tssPubKey ? this.state.tssPubKey.toString("hex") : undefined;
return {
state: { ...this.state, factorKey, tssPubKey },
options: this.options,
serviceProvider: this.torusSp.toJSON(),
storageLayer: this.storageLayer.toJSON(),
tkey: this.tKey.toJSON(),
keyType: this.keyType,
sessionId: this.sessionManager.sessionId,
atomicCallStackCounter: this.atomicCallStackCounter,
ready: this.ready,
};
}

// RecoverTssKey only valid for user that enable MFA where user has 2 type shares :
// TssShareType.DEVICE and TssShareType.RECOVERY
// if the factors key provided is the same type recovery will not works
Expand Down Expand Up @@ -256,16 +308,11 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
enableLogging: this.enableLogging,
});

const shareSerializationModule = new ShareSerializationModule();

this.tkey = new TKeyTSS({
enableLogging: this.enableLogging,
serviceProvider: this.torusSp,
storageLayer: this.storageLayer,
manualSync: this.options.manualSync,
modules: {
shareSerialization: shareSerializationModule,
},
tssKeyType: this.keyType,
});

Expand Down Expand Up @@ -473,19 +520,20 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
}
}

public async inputFactorKey(factorKey: BN): Promise<void> {
public async inputFactorKey(factorKey: BNString): Promise<void> {
const factorKeyBN = new BN(factorKey, "hex");
this.checkReady();
try {
// input tkey device share when required share > 0 ( or not reconstructed )
// assumption tkey shares will not changed
if (!this.tKey.secp256k1Key) {
const factorKeyMetadata = await this.getFactorKeyMetadata(factorKey);
const factorKeyMetadata = await this.getFactorKeyMetadata(factorKeyBN);
await this.tKey.inputShareStoreSafe(factorKeyMetadata, true);
}

// Finalize initialization.
await this.tKey.reconstructKey();
await this.finalizeTkey(factorKey);
await this.finalizeTkey(factorKeyBN);
} catch (err: unknown) {
log.error("login error", err);
if (err instanceof CoreError) {
Expand Down Expand Up @@ -590,6 +638,9 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
const { shareType } = createFactorParams;

let { factorKey, shareDescription, additionalMetadata } = createFactorParams;
if (typeof factorKey === "string") {
factorKey = new BN(factorKey, "hex");
}

if (!VALID_SHARE_INDICES.includes(shareType)) {
throw CoreKitError.newShareIndexInvalid(`Invalid share type provided (${shareType}). Valid share types are ${VALID_SHARE_INDICES}.`);
Expand Down Expand Up @@ -938,6 +989,19 @@ export class Web3AuthMPCCoreKit implements ICoreKit {
this.state = { ...this.state, ...newState };
}

public getGeneralStoreDomain<T>(domain: string): T {
return this.tkey.metadata.getGeneralStoreDomain(domain) as T;
}

public setGeneralStoreDomain<T>(domain: string, value: T): void {
// should we add check for root flag before allow to mutate metadata?
this.tkey.metadata.setGeneralStoreDomain(domain, value);
}

public getmetadataKey(): string | undefined {
return this.tkey?.secp256k1Key.toString(16);
}

protected async atomicSync<T>(f: () => Promise<T>): Promise<T> {
this.atomicCallStackCounter += 1;

Expand Down
2 changes: 1 addition & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { KeyType, Point, Point as TkeyPoint, secp256k1 } from "@tkey/common-type
import { generatePrivateBN } from "@tkey/core";
import { factorKeyCurve } from "@tkey/tss";
import { EllipticCurve } from "@toruslabs/elliptic-wrapper";
import { safeatob } from "@toruslabs/openlogin-utils";
import { keccak256 } from "@toruslabs/torus.js";
import { safeatob } from "@web3auth/auth";
import BN from "bn.js";
import { eddsa as EDDSA } from "elliptic";
import loglevel from "loglevel";
Expand Down
1 change: 1 addition & 0 deletions tests/ed25519.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ variable.forEach((testVariable) => {
const msgBuffer = Buffer.from(msg);

const signature = ed25519().makeSignature((await coreKitInstance.sign(msgBuffer)).toString("hex"));
msgBuffer.slice(1,2);
const valid = ed25519().verify(msgBuffer, signature, coreKitInstance.getPubKeyEd25519());
assert(valid);
});
Expand Down
24 changes: 24 additions & 0 deletions tests/serialize.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { describe, it } from "node:test";
import { defaultTestOptions, newCoreKitLogInInstance } from "./setup";
import { AsyncStorage, MemoryStorage, WEB3AUTH_NETWORK, Web3AuthMPCCoreKit } from "src";
import { deepEqual, deepStrictEqual, equal, strictEqual } from "node:assert";


describe('serialize deserialze mpc corekit', () => {
it('serialize', async () => {
const localMemoryStorage = new MemoryStorage();
const instance = await newCoreKitLogInInstance({
network: WEB3AUTH_NETWORK.DEVNET,
manualSync: true,
email: "[email protected]",
storageInstance: localMemoryStorage,
})
const options = defaultTestOptions({ network: WEB3AUTH_NETWORK.DEVNET, manualSync: true, storageInstance: localMemoryStorage });
const serialized = JSON.stringify(instance);
console.log(serialized)
const deserialized = await Web3AuthMPCCoreKit.fromJSON(JSON.parse(serialized), options);



});
});
21 changes: 19 additions & 2 deletions tests/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import BN from "bn.js";
import jwt, { Algorithm } from "jsonwebtoken";
import { tssLib as tssLibDKLS } from "@toruslabs/tss-dkls-lib";

import { IAsyncStorage, IStorage, parseToken, TssLib, WEB3AUTH_NETWORK_TYPE, Web3AuthMPCCoreKit } from "../src";
import { IAsyncStorage, IStorage, parseToken, TssLibType, WEB3AUTH_NETWORK_TYPE, Web3AuthMPCCoreKit, Web3AuthOptions } from "../src";

export const mockLogin2 = async (email: string) => {
const req = new Request("https://li6lnimoyrwgn2iuqtgdwlrwvq0upwtr.lambda-url.eu-west-1.on.aws/", {
Expand Down Expand Up @@ -84,6 +84,23 @@ export const mockLogin = async (email?: string) => {
};

export type LoginFunc = (email: string) => Promise<{ idToken: string, parsedToken: any }>;
export const defaultTestOptions = (params: {
network: WEB3AUTH_NETWORK_TYPE;
manualSync: boolean;
storageInstance: IStorage | IAsyncStorage;
tssLib?: TssLibType;
}) : Web3AuthOptions => {
const { network, manualSync, storageInstance, tssLib } = params;
return {
web3AuthClientId: "torus-key-test",
web3AuthNetwork: network,
baseUrl: "http://localhost:3000",
uxMode: "nodejs",
tssLib: tssLib || tssLibDKLS,
storage: storageInstance,
manualSync,
}
}

export const newCoreKitLogInInstance = async ({
network,
Expand All @@ -97,7 +114,7 @@ export const newCoreKitLogInInstance = async ({
manualSync: boolean;
email: string;
storageInstance: IStorage | IAsyncStorage;
tssLib?: TssLib;
tssLib?: TssLibType;
importTssKey?: string;
login?: LoginFunc;
}) => {
Expand Down