diff --git a/package-lock.json b/package-lock.json index 6abf0a10..4288105d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@toruslabs/eccrypto": "4.0.0", "@toruslabs/fetch-node-details": "^13.0.1", "@toruslabs/fnd-base": "^13.0.1", - "@toruslabs/metadata-helpers": "^5.x", + "@toruslabs/metadata-helpers": "^4.x", "@toruslabs/openlogin-session-manager": "^3.0.0", "@toruslabs/torus.js": "^11.0.6", "@toruslabs/tss-client": "^1.7.1", @@ -38,6 +38,7 @@ "@toruslabs/config": "^2.0.2", "@toruslabs/eslint-config-typescript": "^3.0.1", "@toruslabs/torus-scripts": "^5.0.5", + "@toruslabs/tss-lib-node": "file:///Users/apollo/works/crypto/torus/clone26/tss-server/packages/tss-lib", "@types/chai": "^4.3.6", "@types/elliptic": "^6.4.14", "@types/node": "^20.6.3", @@ -48,6 +49,7 @@ "esbuild-register": "^3.5.0", "eslint": "^8.49.0", "husky": "^8.0.3", + "jsonwebtoken": "^9.0.2", "lint-staged": "^14.0.1", "mocha": "^10.2.0", "node-fetch": "^3.3.2", @@ -64,6 +66,12 @@ "@toruslabs/metadata-helpers": "^4.x" } }, + "../tss-server/packages/tss-lib": { + "name": "tss-lib", + "version": "1.1.0", + "dev": true, + "license": "BSD" + }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "dev": true, @@ -3481,11 +3489,10 @@ } }, "node_modules/@tkey-mpc/service-provider-base": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@tkey-mpc/service-provider-base/-/service-provider-base-9.0.2.tgz", - "integrity": "sha512-Gk3xF1NFV/BqmwMNKDB//DNoN9nff4kGeNxXiVnlxhQKZuX9phzd/sxJljKc6tutOK5YdOcvot7ZuwJg2/vZjA==", + "version": "9.0.1", + "license": "MIT", "dependencies": { - "@tkey-mpc/common-types": "^9.0.2", + "@tkey-mpc/common-types": "^9.0.1", "bn.js": "^5.2.1", "elliptic": "^6.5.4" }, @@ -3502,10 +3509,10 @@ "resolved": "https://registry.npmjs.org/@tkey-mpc/service-provider-torus/-/service-provider-torus-9.0.3.tgz", "integrity": "sha512-9/OjTqjruR5AWMwJPRuR+ZxsZXzt9jQfzfNtde13VHSjtogcLwT12U1QTHJ7tsIZYckBy3ZVDbNpIcTOzz70tQ==", "dependencies": { - "@tkey-mpc/common-types": "^9.0.2", - "@tkey-mpc/service-provider-base": "^9.0.2", + "@tkey-mpc/common-types": "^9.0.1", + "@tkey-mpc/service-provider-base": "^9.0.1", "@toruslabs/customauth": "^16.0.6", - "@toruslabs/torus.js": "^11.0.6", + "@toruslabs/torus.js": "^11.0.5", "bn.js": "^5.2.1", "elliptic": "^6.5.4" }, @@ -3916,6 +3923,53 @@ } } }, + "node_modules/@toruslabs/customauth/node_modules/@noble/curves": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "dependencies": { + "@noble/hashes": "1.3.1" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@toruslabs/customauth/node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@toruslabs/customauth/node_modules/@scure/bip32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", + "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", + "dependencies": { + "@noble/curves": "~1.1.0", + "@noble/hashes": "~1.3.1", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@toruslabs/customauth/node_modules/@scure/bip39": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", + "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "dependencies": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@toruslabs/customauth/node_modules/@toruslabs/broadcast-channel": { "version": "8.0.0", "license": "MIT", @@ -3955,6 +4009,36 @@ } } }, + "node_modules/@toruslabs/customauth/node_modules/@toruslabs/metadata-helpers": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@toruslabs/metadata-helpers/-/metadata-helpers-5.0.0.tgz", + "integrity": "sha512-ZUFfOHJVJC53c8wJYHjdF3bIgN2ZvfqehbTZ/zJ7oVFfrrd6O66V3gQ1i1zxBjH3yhOvZKQwc0DaMmh3G0NUXQ==", + "dependencies": { + "@toruslabs/eccrypto": "^4.0.0", + "@toruslabs/http-helpers": "^5.0.0", + "elliptic": "^6.5.4", + "ethereum-cryptography": "^2.1.2", + "json-stable-stringify": "^1.0.2" + }, + "engines": { + "node": ">=18.x", + "npm": ">=9.x" + }, + "peerDependencies": { + "@babel/runtime": "7.x" + } + }, + "node_modules/@toruslabs/customauth/node_modules/ethereum-cryptography": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz", + "integrity": "sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==", + "dependencies": { + "@noble/curves": "1.1.0", + "@noble/hashes": "1.3.1", + "@scure/bip32": "1.3.1", + "@scure/bip39": "1.2.1" + } + }, "node_modules/@toruslabs/eccrypto": { "version": "4.0.0", "license": "CC0-1.0", @@ -4071,18 +4155,19 @@ } }, "node_modules/@toruslabs/metadata-helpers": { - "version": "5.0.0", - "license": "MIT", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@toruslabs/metadata-helpers/-/metadata-helpers-4.0.1.tgz", + "integrity": "sha512-0DFPxaNqmuVwFaEddl94dR/rpin5X+Odl1HR8cnzcrbzjLrOuKkGOdWtB6gnIqCUD6onMFO3156crgbHvagrLg==", "dependencies": { - "@toruslabs/eccrypto": "^4.0.0", - "@toruslabs/http-helpers": "^5.0.0", + "@toruslabs/eccrypto": "^3.0.0", + "@toruslabs/http-helpers": "^4.0.0", "elliptic": "^6.5.4", "ethereum-cryptography": "^2.1.2", "json-stable-stringify": "^1.0.2" }, "engines": { - "node": ">=18.x", - "npm": ">=9.x" + "node": ">=16.18.1", + "npm": ">=8.x" }, "peerDependencies": { "@babel/runtime": "7.x" @@ -4131,16 +4216,29 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@toruslabs/metadata-helpers/node_modules/@toruslabs/eccrypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@toruslabs/eccrypto/-/eccrypto-3.0.0.tgz", + "integrity": "sha512-+lFjV+0FZ3S4zH5T/Gnc795HoqpzLLDW28fSkibZRlx1Nx8uwbl3pyJSfya0C0bRHH1/+NTeBogUDijaRJ1NCw==", + "dependencies": { + "elliptic": "^6.5.4" + }, + "engines": { + "node": ">=16.18.1", + "npm": ">=8.x" + } + }, "node_modules/@toruslabs/metadata-helpers/node_modules/@toruslabs/http-helpers": { - "version": "5.0.0", - "license": "MIT", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@toruslabs/http-helpers/-/http-helpers-4.0.0.tgz", + "integrity": "sha512-ef/Svevk54JANOn3Kf6UPf8X/vZlYHrusNFt8VV/LLahhVNXCXEcO8goC1bHkecu/u20CUyo9HJa0pn8fHh1sg==", "dependencies": { "lodash.merge": "^4.6.2", "loglevel": "^1.8.1" }, "engines": { - "node": ">=18.x", - "npm": ">=9.x" + "node": ">=16.18.1", + "npm": ">=8.x" }, "peerDependencies": { "@babel/runtime": "^7.x", @@ -4217,6 +4315,105 @@ "@babel/runtime": "7.x" } }, + "node_modules/@toruslabs/openlogin-session-manager/node_modules/@noble/curves": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "dependencies": { + "@noble/hashes": "1.3.1" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@toruslabs/openlogin-session-manager/node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@toruslabs/openlogin-session-manager/node_modules/@scure/bip32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", + "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", + "dependencies": { + "@noble/curves": "~1.1.0", + "@noble/hashes": "~1.3.1", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@toruslabs/openlogin-session-manager/node_modules/@scure/bip39": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", + "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "dependencies": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@toruslabs/openlogin-session-manager/node_modules/@toruslabs/http-helpers": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@toruslabs/http-helpers/-/http-helpers-5.0.0.tgz", + "integrity": "sha512-GmezWz9JeF6YyhjLSm+9XDF4YaeICEckY0Jbo43i86SjhfJYgRWqEi63VSiNsaqc/z810Q0FQvEk1TnBRX2tgA==", + "dependencies": { + "lodash.merge": "^4.6.2", + "loglevel": "^1.8.1" + }, + "engines": { + "node": ">=18.x", + "npm": ">=9.x" + }, + "peerDependencies": { + "@babel/runtime": "^7.x", + "@sentry/types": "^7.x" + }, + "peerDependenciesMeta": { + "@sentry/types": { + "optional": true + } + } + }, + "node_modules/@toruslabs/openlogin-session-manager/node_modules/@toruslabs/metadata-helpers": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@toruslabs/metadata-helpers/-/metadata-helpers-5.0.0.tgz", + "integrity": "sha512-ZUFfOHJVJC53c8wJYHjdF3bIgN2ZvfqehbTZ/zJ7oVFfrrd6O66V3gQ1i1zxBjH3yhOvZKQwc0DaMmh3G0NUXQ==", + "dependencies": { + "@toruslabs/eccrypto": "^4.0.0", + "@toruslabs/http-helpers": "^5.0.0", + "elliptic": "^6.5.4", + "ethereum-cryptography": "^2.1.2", + "json-stable-stringify": "^1.0.2" + }, + "engines": { + "node": ">=18.x", + "npm": ">=9.x" + }, + "peerDependencies": { + "@babel/runtime": "7.x" + } + }, + "node_modules/@toruslabs/openlogin-session-manager/node_modules/ethereum-cryptography": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz", + "integrity": "sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==", + "dependencies": { + "@noble/curves": "1.1.0", + "@noble/hashes": "1.3.1", + "@scure/bip32": "1.3.1", + "@scure/bip39": "1.2.1" + } + }, "node_modules/@toruslabs/openlogin-utils": { "version": "2.13.0", "license": "ISC", @@ -4229,6 +4426,53 @@ "@babel/runtime": "7.x" } }, + "node_modules/@toruslabs/openlogin/node_modules/@noble/curves": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "dependencies": { + "@noble/hashes": "1.3.1" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@toruslabs/openlogin/node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@toruslabs/openlogin/node_modules/@scure/bip32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", + "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", + "dependencies": { + "@noble/curves": "~1.1.0", + "@noble/hashes": "~1.3.1", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@toruslabs/openlogin/node_modules/@scure/bip39": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", + "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "dependencies": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@toruslabs/openlogin/node_modules/@toruslabs/broadcast-channel": { "version": "8.0.0", "license": "MIT", @@ -4247,6 +4491,47 @@ "npm": ">=9.x" } }, + "node_modules/@toruslabs/openlogin/node_modules/@toruslabs/http-helpers": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@toruslabs/http-helpers/-/http-helpers-5.0.0.tgz", + "integrity": "sha512-GmezWz9JeF6YyhjLSm+9XDF4YaeICEckY0Jbo43i86SjhfJYgRWqEi63VSiNsaqc/z810Q0FQvEk1TnBRX2tgA==", + "dependencies": { + "lodash.merge": "^4.6.2", + "loglevel": "^1.8.1" + }, + "engines": { + "node": ">=18.x", + "npm": ">=9.x" + }, + "peerDependencies": { + "@babel/runtime": "^7.x", + "@sentry/types": "^7.x" + }, + "peerDependenciesMeta": { + "@sentry/types": { + "optional": true + } + } + }, + "node_modules/@toruslabs/openlogin/node_modules/@toruslabs/metadata-helpers": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@toruslabs/metadata-helpers/-/metadata-helpers-5.0.0.tgz", + "integrity": "sha512-ZUFfOHJVJC53c8wJYHjdF3bIgN2ZvfqehbTZ/zJ7oVFfrrd6O66V3gQ1i1zxBjH3yhOvZKQwc0DaMmh3G0NUXQ==", + "dependencies": { + "@toruslabs/eccrypto": "^4.0.0", + "@toruslabs/http-helpers": "^5.0.0", + "elliptic": "^6.5.4", + "ethereum-cryptography": "^2.1.2", + "json-stable-stringify": "^1.0.2" + }, + "engines": { + "node": ">=18.x", + "npm": ">=9.x" + }, + "peerDependencies": { + "@babel/runtime": "7.x" + } + }, "node_modules/@toruslabs/openlogin/node_modules/@toruslabs/openlogin-utils": { "version": "5.0.2", "license": "ISC", @@ -4262,6 +4547,17 @@ "@babel/runtime": "7.x" } }, + "node_modules/@toruslabs/openlogin/node_modules/ethereum-cryptography": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz", + "integrity": "sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==", + "dependencies": { + "@noble/curves": "1.1.0", + "@noble/hashes": "1.3.1", + "@scure/bip32": "1.3.1", + "@scure/bip39": "1.2.1" + } + }, "node_modules/@toruslabs/rss-client": { "version": "1.5.0", "license": "MIT", @@ -4370,7 +4666,8 @@ }, "node_modules/@toruslabs/torus.js": { "version": "11.0.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@toruslabs/torus.js/-/torus.js-11.0.6.tgz", + "integrity": "sha512-l+Ba/DX1L2cLngiL08r8zZmRQ/A3MJ4pl20MaTzQuwxS2OfOXSReKld4YOWHwo5NEd36PHZdZ43qbh0NrzrwVQ==", "dependencies": { "@toruslabs/constants": "^13.0.1", "@toruslabs/eccrypto": "^4.0.0", @@ -4478,6 +4775,10 @@ "node_modules/@toruslabs/tss-lib": { "version": "1.7.1" }, + "node_modules/@toruslabs/tss-lib-node": { + "resolved": "../tss-server/packages/tss-lib", + "link": true + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "dev": true, @@ -5127,6 +5428,25 @@ } } }, + "node_modules/@web3auth/base-provider/node_modules/@toruslabs/metadata-helpers": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@toruslabs/metadata-helpers/-/metadata-helpers-5.0.0.tgz", + "integrity": "sha512-ZUFfOHJVJC53c8wJYHjdF3bIgN2ZvfqehbTZ/zJ7oVFfrrd6O66V3gQ1i1zxBjH3yhOvZKQwc0DaMmh3G0NUXQ==", + "dependencies": { + "@toruslabs/eccrypto": "^4.0.0", + "@toruslabs/http-helpers": "^5.0.0", + "elliptic": "^6.5.4", + "ethereum-cryptography": "^2.1.2", + "json-stable-stringify": "^1.0.2" + }, + "engines": { + "node": ">=18.x", + "npm": ">=9.x" + }, + "peerDependencies": { + "@babel/runtime": "7.x" + } + }, "node_modules/@web3auth/base-provider/node_modules/@toruslabs/openlogin-jrpc": { "version": "5.0.2", "license": "ISC", @@ -6353,6 +6673,12 @@ "ieee754": "^1.2.1" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true + }, "node_modules/buffer-from": { "version": "1.1.2", "dev": true, @@ -7300,6 +7626,15 @@ "dev": true, "license": "MIT" }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.515", "dev": true, @@ -10657,6 +10992,82 @@ "node": "*" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dev": true, + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsonwebtoken/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dev": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dev": true, + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/jwt-decode": { "version": "3.1.2", "license": "MIT" @@ -10909,11 +11320,35 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true + }, "node_modules/lodash.invokemap": { "version": "4.6.0", "dev": true, "license": "MIT" }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true + }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "dev": true, @@ -10933,6 +11368,12 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, "node_modules/lodash.pullall": { "version": "4.2.0", "dev": true, diff --git a/package.json b/package.json index 5b81c413..54e0b80a 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "homepage": "https://github.com/Web3Auth/mpc-core-kit/tree/master#readme", "license": "ISC", "scripts": { - "test": "echo no tests available", + "test": "node --test -r esbuild-register tests/*.spec.ts ", "dev": "torus-scripts start", "build": "torus-scripts build", "release": "torus-scripts release", @@ -68,12 +68,14 @@ "@types/elliptic": "^6.4.14", "@types/node": "^20.6.3", "@typescript-eslint/eslint-plugin": "^6.7.0", + "@toruslabs/tss-lib-node" : "^1.1.3", "chai": "^4.3.8", "cross-env": "^7.0.3", "dotenv": "^16.3.1", "esbuild-register": "^3.5.0", "eslint": "^8.49.0", "husky": "^8.0.3", + "jsonwebtoken": "^9.0.2", "lint-staged": "^14.0.1", "mocha": "^10.2.0", "node-fetch": "^3.3.2", diff --git a/src/helper/browserStorage.ts b/src/helper/browserStorage.ts index 9e130f38..2970c1dd 100644 --- a/src/helper/browserStorage.ts +++ b/src/helper/browserStorage.ts @@ -4,6 +4,28 @@ import { FIELD_ELEMENT_HEX_LEN } from "../constants"; import { ICoreKit, IStorage, TkeyLocalStoreData } from "../interfaces"; import { storageAvailable } from "../utils"; +export type SupportedStorageType = "local" | "session" | "memory" | IStorage; + +export class MemoryStorage implements IStorage { + private _store: Record = {}; + + getItem(key: string): string | null { + return this._store[key] || null; + } + + setItem(key: string, value: string): void { + this._store[key] = value; + } + + removeItem(key: string): void { + delete this._store[key]; + } + + clear(): void { + this._store = {}; + } +} + export class BrowserStorage { // eslint-disable-next-line no-use-before-define private static instance: BrowserStorage; @@ -24,14 +46,17 @@ export class BrowserStorage { } } - static getInstance(key: string, storageKey: "session" | "local" = "local"): BrowserStorage { + static getInstance(key: string, storageKey: SupportedStorageType = "local"): BrowserStorage { if (!this.instance) { - let storage: Storage | undefined; + let storage: IStorage | undefined; if (storageKey === "local" && storageAvailable("localStorage")) { storage = localStorage; - } - if (storageKey === "session" && storageAvailable("sessionStorage")) { + } else if (storageKey === "session" && storageAvailable("sessionStorage")) { storage = sessionStorage; + } else if (storageKey === "memory") { + storage = new MemoryStorage(); + } else if (typeof storageKey === "object") { + storage = storageKey; } if (!storage) { @@ -76,7 +101,7 @@ export class BrowserStorage { } } -export async function storeWebBrowserFactor(factorKey: BN, mpcCoreKit: ICoreKit, storageKey: "local" | "session" = "local"): Promise { +export async function storeWebBrowserFactor(factorKey: BN, mpcCoreKit: ICoreKit, storageKey: SupportedStorageType = "local"): Promise { const metadata = mpcCoreKit.tKey.getMetadata(); const currentStorage = BrowserStorage.getInstance("mpc_corekit_store", storageKey); @@ -89,7 +114,7 @@ export async function storeWebBrowserFactor(factorKey: BN, mpcCoreKit: ICoreKit, ); } -export async function getWebBrowserFactor(mpcCoreKit: ICoreKit, storageKey: "local" | "session" = "local"): Promise { +export async function getWebBrowserFactor(mpcCoreKit: ICoreKit, storageKey: SupportedStorageType = "local"): Promise { const metadata = mpcCoreKit.tKey.getMetadata(); const currentStorage = BrowserStorage.getInstance("mpc_corekit_store", storageKey); diff --git a/src/interfaces.ts b/src/interfaces.ts index 25c8f9d1..ab424705 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -13,6 +13,8 @@ import { CustomChainConfig, SafeEventEmitterProvider } from "@web3auth/base"; import BN from "bn.js"; import { FactorKeyTypeShareDescription, TssShareType, USER_PATH, WEB3AUTH_NETWORK } from "./constants"; + +export type CoreKitMode = UX_MODE_TYPE | "nodejs"; export interface IStorage { getItem(key: string): string | null; setItem(key: string, value: string): void; @@ -277,7 +279,7 @@ export interface Web3AuthOptions { * * @defaultValue `'local'` */ - storageKey?: "session" | "local"; + storageKey?: "session" | "local" | "memory" | IStorage; /** * @defaultValue 86400 @@ -287,7 +289,7 @@ export interface Web3AuthOptions { /** * @defaultValue `'POPUP'` */ - uxMode?: UX_MODE_TYPE; + uxMode?: CoreKitMode; /** * @defaultValue `false` @@ -338,6 +340,14 @@ export interface Web3AuthOptions { * Recommended for Non Custodial Flow. */ disableHashedFactorKey?: boolean; + + /** + * @defaultValue `null` + * Overwrite tss-lib for nodejs. + * Required for nodejs mode. + * Do not use this option for non nodejs mode. + */ + tssLib?: unknown; } export type Web3AuthOptionsWithDefaults = Required; diff --git a/src/mpcCoreKit.ts b/src/mpcCoreKit.ts index c1b10331..1e0b9e40 100644 --- a/src/mpcCoreKit.ts +++ b/src/mpcCoreKit.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/member-ordering */ import { BNString, encrypt, getPubKeyPoint, Point as TkeyPoint, SHARE_DELETED, ShareStore, StringifiedType } from "@tkey-mpc/common-types"; -import ThresholdKey, { CoreError } from "@tkey-mpc/core"; +import ThresholdKey, { CoreError, lagrangeInterpolation } from "@tkey-mpc/core"; import { TorusServiceProvider } from "@tkey-mpc/service-provider-torus"; import { ShareSerializationModule } from "@tkey-mpc/share-serialization"; import { TorusStorageLayer } from "@tkey-mpc/storage-layer-torus"; @@ -11,11 +11,13 @@ import { keccak256 } from "@toruslabs/metadata-helpers"; import { OpenloginSessionManager } from "@toruslabs/openlogin-session-manager"; import TorusUtils, { TorusKey } from "@toruslabs/torus.js"; import { Client, utils as tssUtils } from "@toruslabs/tss-client"; +import type * as TssLib from "@toruslabs/tss-lib/dkls"; import { CHAIN_NAMESPACES, log, SafeEventEmitterProvider } from "@web3auth/base"; import { EthereumSigningProvider } from "@web3auth-mpc/ethereum-provider"; import BN from "bn.js"; import bowser from "bowser"; +// import { name, version } from "../package.json"; import { CURVE, DEFAULT_CHAIN_CONFIG, @@ -85,6 +87,11 @@ export class Web3AuthMPCCoreKit implements ICoreKit { private ready = false; constructor(options: Web3AuthOptions) { + // log.info("======================================================"); + // log.info(`WEB3AUTH SDK : ${name}:${version}`); + + // log.info("======================================================"); + if (!options.chainConfig) options.chainConfig = DEFAULT_CHAIN_CONFIG; if (options.chainConfig.chainNamespace !== CHAIN_NAMESPACES.EIP155) { throw new Error("You must specify a eip155 chain config."); @@ -92,6 +99,13 @@ export class Web3AuthMPCCoreKit implements ICoreKit { if (!options.web3AuthClientId) { throw new Error("You must specify a web3auth clientId."); } + if (options.uxMode === "nodejs" && ["local", "session"].includes(options.storageKey.toString())) { + throw new Error(`nodejs mode do not storage of type : ${options.storageKey}`); + } + + if (options.uxMode === "nodejs" && !options.tssLib) { + throw new Error(`nodejs mode requires tssLib`); + } if (options.enableLogging) { log.enableAll(); @@ -183,7 +197,38 @@ export class Web3AuthMPCCoreKit implements ICoreKit { return this.options.uxMode === UX_MODE.REDIRECT; } + public async _UNSAFE_recoverTssKey(factorKey: string[]) { + this.checkReady(); + const factorKeyBN = new BN(factorKey[0], "hex"); + + const shareStore0 = await this.getFactorKeyMetadata(factorKeyBN); + await this.tKey.initialize({ withShare: shareStore0 }); + + this.tkey.privKey = new BN(factorKey[1], "hex"); + + const tssShares: BN[] = []; + const tssIndexes: number[] = []; + const tssIndexesBN: BN[] = []; + for (let i = 0; i < factorKey.length; i++) { + const factorKeyBNInput = new BN(factorKey[i], "hex"); + const { tssIndex, tssShare } = await this.tKey.getTSSShare(factorKeyBNInput); + if (tssIndexes.includes(tssIndex)) { + await this.init(); + throw new Error("Duplicate TSS Index"); + } + tssIndexes.push(tssIndex); + tssIndexesBN.push(new BN(tssIndex)); + tssShares.push(tssShare); + } + + const finalKey = lagrangeInterpolation(tssShares, tssIndexesBN); + await this.init(); + return finalKey.toString("hex"); + } + public async init(params: InitParams = { handleRedirectResult: true }): Promise { + this.resetState(); + const nodeDetails = await this.nodeDetailManager.getNodeDetails({ verifier: "test-verifier", verifierId: "test@example.com" }); if (!nodeDetails) { @@ -195,7 +240,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit { customAuthArgs: { web3AuthClientId: this.options.web3AuthClientId, baseUrl: this.options.baseUrl ? this.options.baseUrl : `${window.location.origin}/serviceworker`, - uxMode: this.options.uxMode, + uxMode: this.options.uxMode === "nodejs" ? UX_MODE.REDIRECT : this.options.uxMode, network: this.options.web3AuthNetwork, redirectPathName: this.options.redirectPathName, locationReplaceOnRedirect: true, @@ -223,13 +268,17 @@ export class Web3AuthMPCCoreKit implements ICoreKit { if (this.isRedirectMode) { await (this.tKey.serviceProvider as TorusServiceProvider).init({ skipSw: true, skipPrefetch: true }); - } else { + } else if (this.options.uxMode === UX_MODE.POPUP) { await (this.tKey.serviceProvider as TorusServiceProvider).init({}); } this.ready = true; // try handle redirect flow if enabled and return(redirect) from oauth login - if (params.handleRedirectResult && (window?.location.hash.includes("#state") || window?.location.hash.includes("#access_token"))) { + if ( + params.handleRedirectResult && + this.options.uxMode === UX_MODE.REDIRECT && + (window?.location.hash.includes("#state") || window?.location.hash.includes("#access_token")) + ) { await this.handleRedirectResult(); // if not redirect flow try to rehydrate session if available @@ -240,7 +289,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit { // if not redirect flow or session rehydration, ask for factor key to login } - public async loginWithOauth(params: OauthLoginParams): Promise { + public async loginWithOauth(params: OauthLoginParams, importTssKey?: string): Promise { this.checkReady(); const tkeyServiceProvider = this.tKey.serviceProvider as TorusServiceProvider; @@ -275,7 +324,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit { }); } - await this.setupTkey(); + await this.setupTkey(importTssKey); } catch (err: unknown) { log.error("login error", err); if (err instanceof CoreError) { @@ -285,7 +334,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit { } } - public async loginWithJWT(idTokenLoginParams: IdTokenLoginParams): Promise { + public async loginWithJWT(idTokenLoginParams: IdTokenLoginParams, importTssKey?: string): Promise { this.checkReady(); const { verifier, verifierId, idToken } = idTokenLoginParams; @@ -325,7 +374,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit { signatures: this._getSignatures(loginResponse.sessionData.sessionTokenData), }); - await this.setupTkey(); + await this.setupTkey(importTssKey); } catch (err: unknown) { log.error("login error", err); if (err instanceof CoreError) { @@ -429,33 +478,43 @@ export class Web3AuthMPCCoreKit implements ICoreKit { throw new Error("MFA already enabled"); } - try { + let browserData; + + if (this.options.uxMode === "nodejs") { + browserData = { + browserName: "Node Env", + browserVersion: "", + deviceName: "nodejs", + }; + } else { const browserInfo = bowser.parse(navigator.userAgent); const browserName = `${browserInfo.browser.name}`; - const browserData = { + browserData = { browserName, browserVersion: browserInfo.browser.version, deviceName: browserInfo.os.name, }; - const deviceFactorKey = new BN(await this.createFactor({ shareType: TssShareType.DEVICE, additionalMetadata: browserData }), "hex"); - storeWebBrowserFactor(deviceFactorKey, this); - await this.inputFactorKey(new BN(deviceFactorKey, "hex")); - - const hashedFactorPub = getPubKeyPoint(hashedFactorKey); - await this.deleteFactor(hashedFactorPub, hashedFactorKey); - await this.deleteMetadataShareBackup(hashedFactorKey); - - // only recovery factor = true - if (recoveryFactor) { - const backupFactorKey = await this.createFactor({ shareType: TssShareType.RECOVERY, ...enableMFAParams }); - return backupFactorKey; - } - // update to undefined for next major release - return ""; - } catch (err: unknown) { - log.error("error enabling MFA", err); - throw new Error((err as Error).message); } + + const deviceFactorKey = new BN(await this.createFactor({ shareType: TssShareType.DEVICE, additionalMetadata: browserData }), "hex"); + storeWebBrowserFactor(deviceFactorKey, this); + await this.inputFactorKey(new BN(deviceFactorKey, "hex")); + + const hashedFactorPub = getPubKeyPoint(hashedFactorKey); + await this.deleteFactor(hashedFactorPub, hashedFactorKey); + await this.deleteMetadataShareBackup(hashedFactorKey); + + // only recovery factor = true + if (recoveryFactor) { + const backupFactorKey = await this.createFactor({ shareType: TssShareType.RECOVERY, ...enableMFAParams }); + return backupFactorKey; + } + // update to undefined for next major release + return ""; + // } catch (err: unknown) { + // log.error("error enabling MFA", err); + // throw new Error((err as Error).message); + // } } public getTssFactorPub = (): string[] => { @@ -501,6 +560,95 @@ export class Web3AuthMPCCoreKit implements ICoreKit { } } + // function for setting up provider + public getPublic: () => Promise = async () => { + let { tssPubKey } = this.state; + if (tssPubKey.length === FIELD_ELEMENT_HEX_LEN + 1) { + tssPubKey = tssPubKey.subarray(1); + } + return tssPubKey; + }; + + public sign = async (msgHash: Buffer) => { + // PreSetup + let { tssShareIndex, tssPubKey } = this.state; + const { torusNodeTSSEndpoints } = await this.nodeDetailManager.getNodeDetails({ + verifier: "test-verifier", + verifierId: "test@example.com", + }); + + if (!this.state.factorKey) throw new Error("factorKey not present"); + const { tssShare } = await this.tKey.getTSSShare(this.state.factorKey); + const tssNonce = this.getTssNonce(); + + if (!tssPubKey || !torusNodeTSSEndpoints) { + throw new Error("tssPubKey or torusNodeTSSEndpoints not available"); + } + + if (tssPubKey.length === FIELD_ELEMENT_HEX_LEN + 1) { + tssPubKey = tssPubKey.subarray(1); + } + + const vid = `${this.verifier}${DELIMITERS.Delimiter1}${this.verifierId}`; + const sessionId = `${vid}${DELIMITERS.Delimiter2}default${DELIMITERS.Delimiter3}${tssNonce}${DELIMITERS.Delimiter4}`; + + const parties = 4; + const clientIndex = parties - 1; + // 1. setup + // generate endpoints for servers + const { nodeIndexes } = await (this.tKey.serviceProvider as TorusServiceProvider).getTSSPubKey( + this.tKey.tssTag, + this.tKey.metadata.tssNonces[this.tKey.tssTag] + ); + const { endpoints, tssWSEndpoints, partyIndexes } = generateTSSEndpoints(torusNodeTSSEndpoints, parties, clientIndex, nodeIndexes); + const randomSessionNonce = keccak256(Buffer.from(generatePrivate().toString("hex") + Date.now(), "utf8")).toString("hex"); + const tssImportUrl = `${torusNodeTSSEndpoints[0]}/v1/clientWasm`; + // session is needed for authentication to the web3auth infrastructure holding the factor 1 + const currentSession = `${sessionId}${randomSessionNonce}`; + + let tss: typeof TssLib; + if (this.options.uxMode === "nodejs") { + tss = this.options.tssLib as typeof TssLib; + } else { + tss = await import("@toruslabs/tss-lib"); + await tss.default(tssImportUrl); + } + // setup mock shares, sockets and tss wasm files. + const [sockets] = await Promise.all([tssUtils.setupSockets(tssWSEndpoints, randomSessionNonce)]); + + const participatingServerDKGIndexes = nodeIndexes; + const dklsCoeff = tssUtils.getDKLSCoeff(true, participatingServerDKGIndexes, tssShareIndex as number); + const denormalisedShare = dklsCoeff.mul(tssShare).umod(CURVE.curve.n); + const share = scalarBNToBufferSEC1(denormalisedShare).toString("base64"); + + if (!currentSession) { + throw new Error(`sessionAuth does not exist ${currentSession}`); + } + + if (!this.signatures) { + throw new Error(`Signature does not exist ${this.signatures}`); + } + + const client = new Client(currentSession, clientIndex, partyIndexes, endpoints, sockets, share, tssPubKey.toString("base64"), true, tssImportUrl); + const serverCoeffs: Record = {}; + for (let i = 0; i < participatingServerDKGIndexes.length; i++) { + const serverIndex = participatingServerDKGIndexes[i]; + serverCoeffs[serverIndex] = tssUtils.getDKLSCoeff(false, participatingServerDKGIndexes, tssShareIndex as number, serverIndex).toString("hex"); + } + client.precompute(tss, { signatures: this.signatures, server_coeffs: serverCoeffs }); + await client.ready(); + + let { r, s, recoveryParam } = await client.sign(tss, Buffer.from(msgHash).toString("base64"), true, "", "keccak256", { + signatures: this.signatures, + }); + + if (recoveryParam < 27) { + recoveryParam += 27; + } + await client.cleanup(tss, { signatures: this.signatures, server_coeffs: serverCoeffs }); + return { v: recoveryParam, r: scalarBNToBufferSEC1(r), s: scalarBNToBufferSEC1(s) }; + }; + async deleteFactor(factorPub: TkeyPoint, factorKey?: BNString): Promise { if (!this.state.factorKey) throw new Error("Factor key not present"); if (!this.tKey.metadata.factorPubs) throw new Error("Factor pubs not present"); @@ -536,13 +684,13 @@ export class Web3AuthMPCCoreKit implements ICoreKit { } public async logout(): Promise { - if (!this.sessionManager.sessionId) { - throw new Error("User is not logged in."); + if (this.sessionManager.sessionId) { + // throw new Error("User is not logged in."); + await this.sessionManager.invalidateSession(); } - await this.sessionManager.invalidateSession(); this.currentStorage.set("sessionId", ""); this.resetState(); - await this.init(); + await this.init({ handleRedirectResult: false }); } public getUserInfo(): UserInfo { @@ -600,7 +748,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit { if (!this.state.signatures) throw new Error("signatures not present"); const tssKeyBN = new BN(tssKey, "hex"); - this.tKey.importTssKey({ tag: this.tKey.tssTag, importKey: tssKeyBN, factorPub, newTSSIndex }, { authSignatures: this.state.signatures }); + await this.tKey.importTssKey({ tag: this.tKey.tssTag, importKey: tssKeyBN, factorPub, newTSSIndex }, { authSignatures: this.state.signatures }); } public async _UNSAFE_exportTssKey(): Promise { @@ -622,12 +770,11 @@ export class Web3AuthMPCCoreKit implements ICoreKit { return tssNonce; } - private async setupTkey(): Promise { + private async setupTkey(importTssKey?: string): Promise { if (!this.state.oAuthKey) { throw new Error("user not logged in"); } const existingUser = await this.isMetadataPresent(this.state.oAuthKey); - if (!existingUser) { // Generate or use hash factor and initialize tkey with it. let factorKey: BN; @@ -639,10 +786,15 @@ export class Web3AuthMPCCoreKit implements ICoreKit { } else { factorKey = getHashedPrivateKey(this.state.oAuthKey, this.options.web3AuthClientId); } - const deviceTSSShare = new BN(generatePrivate()); const deviceTSSIndex = TssShareType.DEVICE; const factorPub = getPubKeyPoint(factorKey); - await this.tKey.initialize({ useTSS: true, factorPub, deviceTSSShare, deviceTSSIndex }); + if (!importTssKey) { + const deviceTSSShare = new BN(generatePrivate()); + await this.tKey.initialize({ useTSS: true, factorPub, deviceTSSShare, deviceTSSIndex }); + } else { + await this.tKey.initialize(); + await this.importTssKey(importTssKey, factorPub, deviceTSSIndex); + } // Finalize initialization. await this.tKey.reconstructKey(); @@ -656,6 +808,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit { await this.addFactorDescription(factorKey, FactorKeyTypeShareDescription.HashedShare); } } else { + if (importTssKey) throw new Error("Cannot import tss key for existing user"); await this.tKey.initialize({ neverInitializeNewKey: true }); const hashedFactorKey = getHashedPrivateKey(this.state.oAuthKey, this.options.web3AuthClientId); if ((await this.checkIfFactorKeyValid(hashedFactorKey)) && !this.options.disableHashedFactorKey) { @@ -885,94 +1038,7 @@ export class Web3AuthMPCCoreKit implements ICoreKit { private async setupProvider(): Promise { const signingProvider = new EthereumSigningProvider({ config: { chainConfig: this.options.chainConfig } }); - let { tssShareIndex, tssPubKey } = this.state; - const { torusNodeTSSEndpoints } = await this.nodeDetailManager.getNodeDetails({ - verifier: "test-verifier", - verifierId: "test@example.com", - }); - - if (!this.state.factorKey) throw new Error("factorKey not present"); - const { tssShare } = await this.tKey.getTSSShare(this.state.factorKey); - const tssNonce = this.getTssNonce(); - - if (!tssPubKey || !torusNodeTSSEndpoints) { - throw new Error("tssPubKey or torusNodeTSSEndpoints not available"); - } - - if (tssPubKey.length === FIELD_ELEMENT_HEX_LEN + 1) { - tssPubKey = tssPubKey.subarray(1); - } - - const vid = `${this.verifier}${DELIMITERS.Delimiter1}${this.verifierId}`; - const sessionId = `${vid}${DELIMITERS.Delimiter2}default${DELIMITERS.Delimiter3}${tssNonce}${DELIMITERS.Delimiter4}`; - - const sign = async (msgHash: Buffer) => { - const parties = 4; - const clientIndex = parties - 1; - const tss = await import("@toruslabs/tss-lib"); - // 1. setup - // generate endpoints for servers - const { nodeIndexes } = await (this.tKey.serviceProvider as TorusServiceProvider).getTSSPubKey( - this.tKey.tssTag, - this.tKey.metadata.tssNonces[this.tKey.tssTag] - ); - const { endpoints, tssWSEndpoints, partyIndexes } = generateTSSEndpoints(torusNodeTSSEndpoints, parties, clientIndex, nodeIndexes); - const randomSessionNonce = keccak256(Buffer.from(generatePrivate().toString("hex") + Date.now(), "utf8")).toString("hex"); - const tssImportUrl = `${torusNodeTSSEndpoints[0]}/v1/clientWasm`; - // session is needed for authentication to the web3auth infrastructure holding the factor 1 - const currentSession = `${sessionId}${randomSessionNonce}`; - - // setup mock shares, sockets and tss wasm files. - const [sockets] = await Promise.all([tssUtils.setupSockets(tssWSEndpoints, randomSessionNonce), tss.default(tssImportUrl)]); - - const participatingServerDKGIndexes = nodeIndexes; - const dklsCoeff = tssUtils.getDKLSCoeff(true, participatingServerDKGIndexes, tssShareIndex as number); - const denormalisedShare = dklsCoeff.mul(tssShare).umod(CURVE.curve.n); - const share = scalarBNToBufferSEC1(denormalisedShare).toString("base64"); - - if (!currentSession) { - throw new Error(`sessionAuth does not exist ${currentSession}`); - } - - if (!this.signatures) { - throw new Error(`Signature does not exist ${this.signatures}`); - } - - const client = new Client( - currentSession, - clientIndex, - partyIndexes, - endpoints, - sockets, - share, - tssPubKey.toString("base64"), - true, - tssImportUrl - ); - const serverCoeffs: Record = {}; - for (let i = 0; i < participatingServerDKGIndexes.length; i++) { - const serverIndex = participatingServerDKGIndexes[i]; - serverCoeffs[serverIndex] = tssUtils.getDKLSCoeff(false, participatingServerDKGIndexes, tssShareIndex as number, serverIndex).toString("hex"); - } - client.precompute(tss, { signatures: this.signatures, server_coeffs: serverCoeffs }); - await client.ready(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let { r, s, recoveryParam } = await client.sign(tss as any, Buffer.from(msgHash).toString("base64"), true, "", "keccak256", { - signatures: this.signatures, - }); - - if (recoveryParam < 27) { - recoveryParam += 27; - } - await client.cleanup(tss, { signatures: this.signatures, server_coeffs: serverCoeffs }); - return { v: recoveryParam, r: scalarBNToBufferSEC1(r), s: scalarBNToBufferSEC1(s) }; - }; - - const getPublic: () => Promise = async () => { - return tssPubKey; - }; - - await signingProvider.setupProvider({ sign, getPublic }); + await signingProvider.setupProvider({ sign: this.sign, getPublic: this.getPublic }); this.privKeyProvider = signingProvider; } diff --git a/src/point.ts b/src/point.ts index 6c1689c0..b25af064 100644 --- a/src/point.ts +++ b/src/point.ts @@ -1,4 +1,5 @@ import { Point as TkeyPoint } from "@tkey-mpc/common-types"; +import { BNString } from "@toruslabs/torus.js"; import BN from "bn.js"; import { curve } from "elliptic"; @@ -21,6 +22,11 @@ export class Point { this.p = p; } + public static fromPrivateKey(privateKey: BNString): Point { + const ep = CURVE.keyFromPrivate(privateKey.toString("hex")).getPublic(); + return new Point(ep); + } + /** * Creates a new Point from a TKey Point. * @param p - The TKey Point. diff --git a/src/utils.ts b/src/utils.ts index 5f6228b0..f59e862d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -59,7 +59,7 @@ export function storageAvailable(type: string): boolean { export function parseToken(token: string) { const base64Url = token.split(".")[1]; const base64 = base64Url.replace("-", "+").replace("_", "/"); - return JSON.parse(window.atob(base64 || "")); + return JSON.parse(atob(base64 || "")); } /** diff --git a/tests/factors.spec.ts b/tests/factors.spec.ts new file mode 100644 index 00000000..07fd691f --- /dev/null +++ b/tests/factors.spec.ts @@ -0,0 +1,151 @@ +/* eslint-disable mocha/handle-done-callback */ +import assert from "node:assert"; +import test from "node:test"; + +import * as TssLib from "@toruslabs/tss-lib-node"; +import BN from "bn.js"; + +import { + COREKIT_STATUS, + getWebBrowserFactor, + MemoryStorage, + Point, + SupportedStorageType, + TssShareType, + WEB3AUTH_NETWORK, + Web3AuthMPCCoreKit, +} from "../src"; +import { criticalResetAccount, mockLogin } from "./setup"; + +type FactorTestVariable = { + types: TssShareType; + manualSync?: boolean; + storage: SupportedStorageType; +}; + +// const { types } = factor; +export const FactorManipulationTest = async (newInstance: () => Promise, testVariable: FactorTestVariable) => { + test(`#Factor manipulation - ${testVariable.types} `, async function (t) { + await t.before(async function () { + const coreKitInstance = await newInstance(); + await criticalResetAccount(coreKitInstance); + await coreKitInstance.logout(); + }); + + await t.test("should able to create factor", async function () { + const coreKitInstance = await newInstance(); + const firstFactor = coreKitInstance.getCurrentFactorKey(); + // try delete hash factor factor + try { + const pt = Point.fromPrivateKey(firstFactor.factorKey); + await coreKitInstance.deleteFactor(pt.toTkeyPoint()); + throw new Error("should not reach here"); + } catch {} + + // create factor + const factorKey1 = await coreKitInstance.createFactor({ + shareType: TssShareType.DEVICE, + }); + + const factorKey2 = await coreKitInstance.createFactor({ + shareType: TssShareType.RECOVERY, + }); + + // sync + if (testVariable.manualSync) { + await coreKitInstance.commitChanges(); + } + // clear session prevent rehydration + await coreKitInstance.logout(); + + // new instance + const instance2 = await newInstance(); + assert.strictEqual(instance2.getTssFactorPub().length, 3); + + // try inputFactor ( set as active factor ) + + // delete factor + const pt = Point.fromPrivateKey(factorKey1); + await instance2.deleteFactor(pt.toTkeyPoint()); + + // delete factor + const pt2 = Point.fromPrivateKey(factorKey2); + await instance2.deleteFactor(pt2.toTkeyPoint()); + + if (testVariable.manualSync) { + await instance2.commitChanges(); + } + + // new instance + const instance3 = await newInstance(); + assert.strictEqual(instance3.getTssFactorPub().length, 1); + }); + + // enable mfa + + await t.test("enable MFA", async function () { + const instance = await newInstance(); + const recoverFactor = await instance.enableMFA({}); + + if (testVariable.manualSync) { + await instance.commitChanges(); + } + + // to prevent rehydration ( rehydrate session id store in BrowserStorage) + await instance.logout(); + + // new instance + const instance2 = await newInstance(); + const browserFactor = await getWebBrowserFactor(instance2, testVariable.storage); + // try { + // checkLogin(instance2); + // } + + // login with mfa factor + await instance2.inputFactorKey(new BN(recoverFactor, "hex")); + assert.strictEqual(instance2.status, COREKIT_STATUS.LOGGED_IN); + await instance2.logout(); + + // new instance + const instance3 = await newInstance(); + assert.strictEqual(instance3.status, COREKIT_STATUS.REQUIRED_SHARE); + + await instance3.inputFactorKey(new BN(browserFactor, "hex")); + assert.strictEqual(instance3.status, COREKIT_STATUS.LOGGED_IN); + }); + }); +}; + +const variable: FactorTestVariable[] = [ + { types: TssShareType.DEVICE, manualSync: true, storage: new MemoryStorage() }, + { types: TssShareType.RECOVERY, manualSync: true, storage: "memory" }, +]; + +const email = "testmail99"; +variable.forEach(async (testVariable) => { + const newCoreKitLogInInstance = async () => { + const instance = new Web3AuthMPCCoreKit({ + web3AuthClientId: "torus-key-test", + web3AuthNetwork: WEB3AUTH_NETWORK.DEVNET, + baseUrl: "http://localhost:3000", + uxMode: "nodejs", + tssLib: TssLib, + storageKey: testVariable.storage, + manualSync: testVariable.manualSync, + }); + + const { idToken, parsedToken } = await mockLogin(email); + await instance.init({ handleRedirectResult: false }); + try { + await instance.loginWithJWT({ + verifier: "torus-test-health", + verifierId: parsedToken.email, + idToken, + }); + } catch (error) {} + + return instance; + }; + + await FactorManipulationTest(newCoreKitLogInInstance, testVariable); +}); diff --git a/tests/importRecovery.spec.ts b/tests/importRecovery.spec.ts new file mode 100644 index 00000000..1bcc42ef --- /dev/null +++ b/tests/importRecovery.spec.ts @@ -0,0 +1,105 @@ +/* eslint-disable mocha/handle-done-callback */ +import assert from "node:assert"; +import test from "node:test"; + +import * as TssLib from "@toruslabs/tss-lib-node"; +import { log } from "@web3auth/base"; + +import { IdTokenLoginParams, TssShareType, WEB3AUTH_NETWORK, Web3AuthMPCCoreKit } from "../src"; +import { criticalResetAccount, mockLogin, newCoreKitLogInInstance } from "./setup"; + +type ImportKeyTestVariable = { + manualSync?: boolean; + email: string; + importKeyEmail: string; +}; +export const ImportTest = async (testVariable: ImportKeyTestVariable) => { + test(`import recover tss key : ${testVariable.manualSync}`, async function (t) { + t.before(async () => { + const instance = await newCoreKitLogInInstance({ + network: WEB3AUTH_NETWORK.DEVNET, + manualSync: testVariable.manualSync, + email: testVariable.email, + }); + await criticalResetAccount(instance); + await instance.logout(); + }); + + await t.test("#recover Tss key using 2 factors key, import tss key to new oauth login", async function () { + const { idToken, parsedToken } = await mockLogin(testVariable.email); + + const idTokenLoginParams = { + verifier: "torus-test-health", + verifierId: parsedToken.email, + idToken, + } as IdTokenLoginParams; + + const coreKitInstance = new Web3AuthMPCCoreKit({ + web3AuthClientId: "torus-key-test", + web3AuthNetwork: WEB3AUTH_NETWORK.DEVNET, + baseUrl: "http://localhost:3000", + uxMode: "nodejs", + tssLib: TssLib, + storageKey: "memory", + manualSync: testVariable.manualSync, + }); + + await coreKitInstance.init(); + await coreKitInstance.loginWithJWT(idTokenLoginParams); + + const factorKeyDevice = await coreKitInstance.createFactor({ + shareType: TssShareType.DEVICE, + }); + + const factorKeyRecovery = await coreKitInstance.createFactor({ + shareType: TssShareType.RECOVERY, + }); + + // recover key + // reinitalize corekit + await coreKitInstance.logout(); + const recoveredTssKey = await coreKitInstance._UNSAFE_recoverTssKey([factorKeyDevice, factorKeyRecovery]); + + await criticalResetAccount(coreKitInstance); + // reinitialize corekit + const newEmail = testVariable.importKeyEmail; + const newLogin = await mockLogin(newEmail); + + const newIdTokenLoginParams = { + verifier: "torus-test-health", + verifierId: newLogin.parsedToken.email, + idToken: newLogin.idToken, + } as IdTokenLoginParams; + + const coreKitInstance2 = new Web3AuthMPCCoreKit({ + web3AuthClientId: "torus-key-test", + web3AuthNetwork: WEB3AUTH_NETWORK.DEVNET, + baseUrl: "http://localhost:3000", + uxMode: "nodejs", + tssLib: TssLib, + storageKey: "memory", + }); + + await coreKitInstance2.init(); + await coreKitInstance2.loginWithJWT(newIdTokenLoginParams, recoveredTssKey); + + const exportedTssKey = await coreKitInstance2._UNSAFE_exportTssKey(); + criticalResetAccount(coreKitInstance2); + + assert.strictEqual(exportedTssKey, recoveredTssKey); + }); + + t.afterEach(function () { + return log.info("finished running recovery test"); + }); + t.after(function () { + return log.info("finished running recovery tests"); + }); + }); +}; + +const variable: ImportKeyTestVariable[] = [{ manualSync: false, email: "emailexport", importKeyEmail: "emailimport" }]; + +variable.forEach(async (testVariable) => { + await ImportTest(testVariable); +}); diff --git a/tests/login.spec.ts b/tests/login.spec.ts new file mode 100644 index 00000000..c6bc03e8 --- /dev/null +++ b/tests/login.spec.ts @@ -0,0 +1,124 @@ +/* eslint-disable mocha/handle-done-callback */ +import assert from "node:assert"; +import test from "node:test"; + +import { UX_MODE_TYPE } from "@toruslabs/customauth"; +import { keccak256 } from "@toruslabs/metadata-helpers"; +import * as TssLib from "@toruslabs/tss-lib-node"; +import BN from "bn.js"; +import { ec as EC } from "elliptic"; + +import { COREKIT_STATUS, WEB3AUTH_NETWORK, WEB3AUTH_NETWORK_TYPE, Web3AuthMPCCoreKit } from "../src"; +import { criticalResetAccount, mockLogin } from "./setup"; + +type TestVariable = { + web3AuthNetwork: WEB3AUTH_NETWORK_TYPE; + uxMode: UX_MODE_TYPE | "nodejs"; + manualSync?: boolean; + + email: string; +}; + +const defaultTestEmail = "testEmail1"; +const variable: TestVariable[] = [ + { web3AuthNetwork: WEB3AUTH_NETWORK.DEVNET, uxMode: "nodejs", email: defaultTestEmail }, + // { web3AuthNetwork: WEB3AUTH_NETWORK.MAINNET, uxMode: UX_MODE.REDIRECT, email: defaultTestEmail }, + + { web3AuthNetwork: WEB3AUTH_NETWORK.DEVNET, uxMode: "nodejs", manualSync: true, email: defaultTestEmail }, + // { web3AuthNetwork: WEB3AUTH_NETWORK.MAINNET, uxMode: UX_MODE.REDIRECT, manualSync: true, email: defaultTestEmail }, +]; + +const checkLogin = async (coreKitInstance: Web3AuthMPCCoreKit) => { + const keyDetails = coreKitInstance.getKeyDetails(); + assert.strictEqual(coreKitInstance.status, COREKIT_STATUS.LOGGED_IN); + assert.strictEqual(keyDetails.requiredFactors, 0); + const factorkey = coreKitInstance.getCurrentFactorKey(); + await coreKitInstance.tKey.getTSSShare(new BN(factorkey.factorKey, "hex")); +}; + +variable.forEach((testVariable) => { + const { web3AuthNetwork, uxMode, manualSync, email } = testVariable; + const coreKitInstance = new Web3AuthMPCCoreKit({ + web3AuthClientId: "torus-key-test", + web3AuthNetwork, + baseUrl: "http://localhost:3000", + uxMode, + tssLib: TssLib, + storageKey: "memory", + manualSync, + }); + + const testNameSuffix = JSON.stringify(testVariable); + test(`#Login Test with JWT + logout : ${testNameSuffix}`, async (t) => { + t.before(async function () { + if (coreKitInstance.status === COREKIT_STATUS.INITIALIZED) await criticalResetAccount(coreKitInstance); + }); + + t.after(async function () { + // after all test tear down + }); + + // t.skip("#Login with Oauth", async function () { + // // popup + // // redirect flow + // // not testable + // }); + await t.test("#Login ", async function () { + // mocklogin + const { idToken, parsedToken } = await mockLogin(email); + await coreKitInstance.init({ handleRedirectResult: false }); + await coreKitInstance.loginWithJWT({ + verifier: "torus-test-health", + verifierId: parsedToken.email, + idToken, + }); + + // get key details + await checkLogin(coreKitInstance); + }); + + await t.test("#relogin ", async function () { + // reload without rehydrate + // await coreKitInstance.init({ rehydrate: false }); + + // rehydrate + await coreKitInstance.init({ handleRedirectResult: false }); + await checkLogin(coreKitInstance); + + // logout + await coreKitInstance.logout(); + + // rehydrate should fail + await coreKitInstance.init(); + assert.strictEqual(coreKitInstance.status, COREKIT_STATUS.INITIALIZED); + try { + coreKitInstance.getCurrentFactorKey(); + throw new Error("should not reach here"); + } catch (error) {} + + // relogin + const { idToken, parsedToken } = await mockLogin(email); + await coreKitInstance.loginWithJWT({ + verifier: "torus-test-health", + verifierId: parsedToken.email, + idToken, + }); + + // get key details + await checkLogin(coreKitInstance); + }); + + await t.test("#able to sign", async function () { + const msg = "hello world"; + const msgBuffer = Buffer.from(msg); + const msgHash = keccak256(msgBuffer); + const signature = await coreKitInstance.sign(msgHash); + + const secp256k1 = new EC("secp256k1"); + const pubkey = secp256k1.recoverPubKey(msgHash, signature, signature.v - 27); + const publicKeyPoint = coreKitInstance.getTssPublicKey(); + assert.strictEqual(pubkey.x.toString("hex"), publicKeyPoint.x.toString("hex")); + assert.strictEqual(pubkey.y.toString("hex"), publicKeyPoint.y.toString("hex")); + }); + }); +}); diff --git a/tests/securityQuestion.spec.ts b/tests/securityQuestion.spec.ts new file mode 100644 index 00000000..a068aa09 --- /dev/null +++ b/tests/securityQuestion.spec.ts @@ -0,0 +1,135 @@ +/* eslint-disable mocha/handle-done-callback */ +/* eslint-disable no-console */ +import assert from "node:assert"; +import test from "node:test"; + +// import { getPubKeyPoint } from "@tkey-mpc/common-types"; +import { UX_MODE_TYPE } from "@toruslabs/customauth"; +import * as TssLib from "@toruslabs/tss-lib-node"; +import BN from "bn.js"; + +import { COREKIT_STATUS, TssSecurityQuestion, WEB3AUTH_NETWORK, WEB3AUTH_NETWORK_TYPE, Web3AuthMPCCoreKit } from "../src"; +import { criticalResetAccount, mockLogin } from "./setup"; + +type TestVariable = { + web3AuthNetwork: WEB3AUTH_NETWORK_TYPE; + uxMode: UX_MODE_TYPE | "nodejs"; + manualSync?: boolean; +}; + +export const TssSecurityQuestionsTest = async (newInstance: () => Promise, testVariable: TestVariable) => { + test(`#Tss Security Question - ${testVariable.manualSync} `, async function (t) { + await t.before(async function () { + const coreKitInstance = await newInstance(); + if (coreKitInstance.status === COREKIT_STATUS.REQUIRED_SHARE) await criticalResetAccount(coreKitInstance); + await coreKitInstance.logout(); + }); + t.afterEach(function () { + return console.log("finished running test"); + }); + t.after(function () { + return console.log("finished running tests"); + }); + + await t.test("should work", async function () { + // set security question + const instance = await newInstance(); + const question = "test question"; + const answer = "test answer"; + const newQuestion = "new question"; + const newAnswer = "new answer"; + // const shareType = TssShareType.DEVICE; + + const securityQuestion = new TssSecurityQuestion(); + await securityQuestion.setSecurityQuestion({ + mpcCoreKit: instance, + question, + answer, + // shareType, + }); + + // recover factor + const factor = await securityQuestion.recoverFactor(instance, answer); + // check factor + await instance.tKey.getTSSShare(new BN(factor, "hex")); + // check wrong answer + try { + await securityQuestion.recoverFactor(instance, "wrong answer"); + throw new Error("should not reach here"); + } catch {} + + // change factor + await securityQuestion.changeSecurityQuestion({ + mpcCoreKit: instance, + newQuestion, + newAnswer, + answer, + }); + // recover factor + // check factor + const newFactor = await securityQuestion.recoverFactor(instance, newAnswer); + await instance.tKey.getTSSShare(new BN(newFactor, "hex")); + + try { + await instance.tKey.getTSSShare(new BN(factor, "hex")); + throw new Error("should not reach here"); + } catch {} + + // recover factor + // check wrong answer + try { + await securityQuestion.recoverFactor(instance, answer); + throw new Error("should not reach here"); + } catch {} + + // delete factor + await securityQuestion.deleteSecurityQuestion(instance); + // recover factor + try { + await securityQuestion.recoverFactor(instance, answer); + throw new Error("should not reach here"); + } catch {} + + // input factor + assert.strictEqual(true, true); + }); + }); +}; + +const variable: TestVariable[] = [ + // { web3AuthNetwork: WEB3AUTH_NETWORK.DEVNET, uxMode: UX_MODE.REDIRECT }, + // { web3AuthNetwork: WEB3AUTH_NETWORK.MAINNET, uxMode: UX_MODE.REDIRECT }, + + { web3AuthNetwork: WEB3AUTH_NETWORK.DEVNET, uxMode: "nodejs", manualSync: true }, + // { web3AuthNetwork: WEB3AUTH_NETWORK.MAINNET, uxMode: UX_MODE.REDIRECT, manualSync: true }, +]; + +const email = "testmail99"; + +variable.forEach(async (testVariable) => { + const newCoreKitLogInInstance = async () => { + const instance = new Web3AuthMPCCoreKit({ + web3AuthClientId: "torus-key-test", + web3AuthNetwork: WEB3AUTH_NETWORK.DEVNET, + baseUrl: "http://localhost:3000", + uxMode: "nodejs", + tssLib: TssLib, + storageKey: "memory", + manualSync: testVariable.manualSync, + }); + + const { idToken, parsedToken } = await mockLogin(email); + await instance.init({ handleRedirectResult: false }); + try { + await instance.loginWithJWT({ + verifier: "torus-test-health", + verifierId: parsedToken.email, + idToken, + }); + } catch (error) {} + + return instance; + }; + + await TssSecurityQuestionsTest(newCoreKitLogInInstance, testVariable); +}); diff --git a/tests/setup.ts b/tests/setup.ts new file mode 100644 index 00000000..c9464030 --- /dev/null +++ b/tests/setup.ts @@ -0,0 +1,94 @@ +import * as TssLib from "@toruslabs/tss-lib-node"; +import BN from "bn.js"; +import jwt, { Algorithm } from "jsonwebtoken"; + +import { parseToken, WEB3AUTH_NETWORK_TYPE, Web3AuthMPCCoreKit } from "../src"; + +export const mockLogin2 = async (email: string) => { + const req = new Request("https://li6lnimoyrwgn2iuqtgdwlrwvq0upwtr.lambda-url.eu-west-1.on.aws/", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ verifier: "torus-key-test", scope: "email", extraPayload: { email }, alg: "ES256" }), + }); + + const resp = await fetch(req); + const bodyJson = (await resp.json()) as { token: string }; + const idToken = bodyJson.token; + const parsedToken = parseToken(idToken); + return { idToken, parsedToken }; +}; + +export const criticalResetAccount = async (coreKitInstance: Web3AuthMPCCoreKit): Promise => { + // This is a critical function that should only be used for testing purposes + // Resetting your account means clearing all the metadata associated with it from the metadata server + // The key details will be deleted from our server and you will not be able to recover your account + if (!coreKitInstance) { + throw new Error("coreKitInstance is not set"); + } + + await coreKitInstance.tKey.storageLayer.setMetadata({ + privKey: new BN(coreKitInstance.metadataKey!, "hex"), + input: { message: "KEY_NOT_FOUND" }, + }); +}; + +const privateKey = "MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCD7oLrcKae+jVZPGx52Cb/lKhdKxpXjl9eGNa1MlY57A=="; +const jwtPrivateKey = `-----BEGIN PRIVATE KEY-----\n${privateKey}\n-----END PRIVATE KEY-----`; +const alg: Algorithm = "ES256"; + +export const mockLogin = async (email: string) => { + const iat = Math.floor(Date.now() / 1000); + const payload = { + iss: "torus-key-test", + aud: "torus-key-test", + name: email, + email, + scope: "email", + iat, + eat: iat + 120, + }; + + const algo = { + expiresIn: 120, + algorithm: alg, + }; + + const token = jwt.sign(payload, jwtPrivateKey, algo); + const idToken = token; + const parsedToken = parseToken(idToken); + return { idToken, parsedToken }; +}; + +export const newCoreKitLogInInstance = async ({ + network, + manualSync, + email, +}: { + network: WEB3AUTH_NETWORK_TYPE; + manualSync: boolean; + email: string; +}) => { + const instance = new Web3AuthMPCCoreKit({ + web3AuthClientId: "torus-key-test", + web3AuthNetwork: network, + baseUrl: "http://localhost:3000", + uxMode: "nodejs", + tssLib: TssLib, + storageKey: "memory", + manualSync, + }); + + const { idToken, parsedToken } = await mockLogin(email); + await instance.init(); + try { + await instance.loginWithJWT({ + verifier: "torus-test-health", + verifierId: parsedToken.email, + idToken, + }); + } catch (error) {} + + return instance; +}; diff --git a/tests/signing.spec.ts b/tests/signing.spec.ts new file mode 100644 index 00000000..e69de29b