diff --git a/demo/redirect-flow-example/package-lock.json b/demo/redirect-flow-example/package-lock.json index 7565d7d..c6980c1 100644 --- a/demo/redirect-flow-example/package-lock.json +++ b/demo/redirect-flow-example/package-lock.json @@ -52,39 +52,39 @@ }, "../..": { "name": "@web3auth/mpc-core-kit", - "version": "3.0.0-alpha.4", + "version": "3.1.0", "license": "ISC", "dependencies": { - "@tkey/common-types": "13.0.0-alpha.6", - "@tkey/core": "13.0.0-alpha.6", - "@tkey/share-serialization": "13.0.0-alpha.6", - "@tkey/storage-layer-torus": "13.0.0-alpha.6", - "@tkey/tss": "13.0.0-alpha.5", - "@toruslabs/constants": "^13.4.0", - "@toruslabs/customauth": "19.0.0-alpha.7", + "@tkey/common-types": "^15.0.2", + "@tkey/core": "^15.0.2", + "@tkey/share-serialization": "^15.0.2", + "@tkey/storage-layer-torus": "^15.0.2", + "@tkey/tss": "^15.0.2", + "@toruslabs/constants": "^14.0.0", + "@toruslabs/customauth": "^20.1.0", "@toruslabs/elliptic-wrapper": "^0.1.0", - "@toruslabs/fetch-node-details": "^13.4.0", - "@toruslabs/fnd-base": "^13.4.0", - "@toruslabs/metadata-helpers": "^5.x", - "@toruslabs/openlogin-session-manager": "^3.1.1", - "@toruslabs/openlogin-utils": "^8.1.2", - "@toruslabs/torus.js": "13.0.0-alpha.7", - "@toruslabs/tss-client": "3.0.0-alpha.0", - "@toruslabs/tss-frost-client": "0.1.1-alpha.0", + "@toruslabs/fetch-node-details": "^14.0.1", + "@toruslabs/fnd-base": "^14.0.0", + "@toruslabs/metadata-helpers": "^6.0.0", + "@toruslabs/openlogin-utils": "^8.2.1", + "@toruslabs/session-manager": "^2.0.0", + "@toruslabs/torus.js": "^15.0.2", + "@toruslabs/tss-client": "^3.0.0", + "@toruslabs/tss-frost-client": "0.2.0", "@toruslabs/tss-frost-common": "^1.0.0", "bn.js": "^5.2.1", "bowser": "^2.11.0", - "elliptic": "^6.5.5", + "elliptic": "^6.5.7", "loglevel": "^1.9.1" }, "devDependencies": { "@babel/register": "^7.24.6", - "@toruslabs/config": "^2.0.2", - "@toruslabs/eslint-config-typescript": "^3.2.0", + "@toruslabs/config": "^2.2.0", + "@toruslabs/eslint-config-typescript": "^3.3.3", "@toruslabs/torus-scripts": "^5.3.1", - "@toruslabs/tss-dkls-lib": "3.0.0-alpha.0", - "@toruslabs/tss-frost-lib": "^0.1.1-alpha.0", - "@toruslabs/tss-lib-node": "^1.1.3", + "@toruslabs/tss-dkls-lib": "^3.0.0", + "@toruslabs/tss-frost-lib": "^0.2.0", + "@toruslabs/tss-lib-node": "^1.2.0", "@types/chai": "^4.3.16", "@types/elliptic": "^6.4.18", "@types/jsonwebtoken": "^9.0.6", @@ -93,20 +93,20 @@ "chai": "^5.1.1", "cross-env": "^7.0.3", "dotenv": "^16.4.5", - "esbuild-register": "^3.5.0", + "esbuild-register": "^3.6.0", "eslint": "^8.56.0", - "husky": "^9.0.11", + "husky": "^9.1.4", "jsonwebtoken": "^9.0.2", - "lint-staged": "^15.2.5", - "mocha": "^10.4.0", + "lint-staged": "^15.2.9", + "mocha": "^10.7.3", "node-fetch": "^3.3.2", - "prettier": "^3.3.0", - "rimraf": "^5.0.7", + "prettier": "^3.3.3", + "rimraf": "^6.0.1", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", "tsconfig-paths-webpack-plugin": "^4.1.0", - "tslib": "^2.6.2", - "typescript": "^5.4.5" + "tslib": "^2.6.3", + "typescript": "^5.5.4" }, "engines": { "node": ">=20.x" diff --git a/demo/redirect-flow-example/src/App.tsx b/demo/redirect-flow-example/src/App.tsx index ccd520c..51c2716 100644 --- a/demo/redirect-flow-example/src/App.tsx +++ b/demo/redirect-flow-example/src/App.tsx @@ -43,6 +43,7 @@ const coreKitInstance = new Web3AuthMPCCoreKit( storage: window.localStorage, // sessionTime: 3600, // <== can provide variable session time based on user subscribed plan tssLib, + useDkg: false } ); diff --git a/src/interfaces.ts b/src/interfaces.ts index 0715138..8bb23fc 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -79,7 +79,7 @@ export type MPCKeyDetails = { tssPubKey?: TkeyPoint; }; -export type OAuthLoginParams = (SubVerifierDetailsParams | AggregateVerifierLoginParams) & { importTssKey?: string; useDkg?: boolean }; +export type OAuthLoginParams = (SubVerifierDetailsParams | AggregateVerifierLoginParams) & { importTssKey?: string }; export type UserInfo = TorusVerifierResponse & LoginWindowResponse; export interface EnableMFAParams { @@ -407,7 +407,7 @@ export interface Web3AuthOptions { /** * Set this flag to false to generate keys on client side * by default keys are generated on using dkg protocol on a distributed network - * @defaultValue undefined + * @defaultValue true if keyType is ed25519, false for secp256k1 keys */ useDkg?: boolean; } diff --git a/src/mpcCoreKit.ts b/src/mpcCoreKit.ts index e7a016b..45a12d2 100644 --- a/src/mpcCoreKit.ts +++ b/src/mpcCoreKit.ts @@ -53,6 +53,7 @@ import { Web3AuthState, } from "./interfaces"; import { + bytesToHex, deriveShareCoefficients, ed25519, generateFactorKey, @@ -62,6 +63,7 @@ import { getSessionId, log, parseToken, + randomBytes, sampleEndpoints, scalarBNToBufferSEC1, } from "./utils"; @@ -245,7 +247,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit { locationReplaceOnRedirect: true, serverTimeOffset: this.options.serverTimeOffset, keyType: this.keyType, - useDkg: this.options.useDkg, + useDkg: this.keyType === KeyType.ed25519 && this.options.useDkg === undefined ? true : this.options.useDkg, }, }); @@ -312,9 +314,22 @@ export class Web3AuthMPCCoreKit implements ICoreKit { if (this.isNodejsOrRN(this.options.uxMode)) { throw CoreKitError.oauthLoginUnsupported(`Oauth login is NOT supported in ${this.options.uxMode} mode.`); } - const { importTssKey } = params; + const { importTssKey: providedImportTssKey } = params; const tkeyServiceProvider = this.torusSp; + let importTssKey = providedImportTssKey; + + // use import key flow by default for ed25519 + if (!importTssKey && !this.options.useDkg) { + if (this.keyType === KeyType.ed25519) { + importTssKey = bytesToHex(randomBytes(32)); + } else if (this.keyType === KeyType.secp256k1) { + importTssKey = generateFactorKey().private.toString("hex", 64); + } else { + throw CoreKitError.default("Unsupported key type"); + } + } + try { // oAuth login. const verifierParams = params as SubVerifierDetailsParams; @@ -643,7 +658,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit { */ public getPubKeyEd25519(): Buffer { const p = this.tkey.tssCurve.keyFromPublic(this.getPubKey()).getPublic(); - return ed25519.keyFromPublic(p).getPublic(); + return ed25519().keyFromPublic(p).getPublic(); } public async sign(data: Buffer, hashed: boolean = false): Promise { diff --git a/src/utils.ts b/src/utils.ts index b149144..04cc3a2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -11,8 +11,35 @@ import loglevel from "loglevel"; import { DELIMITERS, SCALAR_LEN } from "./constants"; import { CoreKitSigner, EthereumSigner, IAsyncStorage, IStorage } from "./interfaces"; -export const ed25519 = new EDDSA("ed25519"); +export const ed25519 = () => { + return new EDDSA("ed25519"); +}; + +const cr = () => + // We support: 1) browsers 2) node.js 19+ + typeof globalThis === "object" && "crypto" in globalThis ? globalThis.crypto : undefined; + +// Array where index 0xf0 (240) is mapped to string 'f0' +const hexes = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0")); +/** + * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' + */ +export function bytesToHex(bytes: Uint8Array): string { + let hex = ""; + for (let i = 0; i < bytes.length; i++) { + hex += hexes[bytes[i]]; + } + return hex; +} +export const randomBytes = (len = 32): Uint8Array => { + // CSPRNG (random number generator) + const crypto = cr(); // Can be shimmed in node.js <= 18 to prevent error: + // import { webcrypto } from 'node:crypto'; + // if (!globalThis.crypto) globalThis.crypto = webcrypto; + if (!crypto || !crypto.getRandomValues) throw new Error("crypto.getRandomValues must be defined"); + return crypto.getRandomValues(new Uint8Array(len)); +}; export const generateFactorKey = (): { private: BN; pub: TkeyPoint } => { const keyPair = factorKeyCurve.genKeyPair(); const pub = Point.fromElliptic(keyPair.getPublic()); diff --git a/tests/ed25519.spec.ts b/tests/ed25519.spec.ts index 23bf958..208beb5 100644 --- a/tests/ed25519.spec.ts +++ b/tests/ed25519.spec.ts @@ -143,8 +143,8 @@ variable.forEach((testVariable) => { const msg = "hello world"; const msgBuffer = Buffer.from(msg); - const signature = ed25519.makeSignature((await coreKitInstance.sign(msgBuffer)).toString("hex")); - const valid = ed25519.verify(msgBuffer, signature, coreKitInstance.getPubKeyEd25519()); + const signature = ed25519().makeSignature((await coreKitInstance.sign(msgBuffer)).toString("hex")); + const valid = ed25519().verify(msgBuffer, signature, coreKitInstance.getPubKeyEd25519()); assert(valid); }); });