From 3849cebc379372f1eb2008b89cd4dbf885ad0763 Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Thu, 19 Oct 2023 16:42:05 +0100 Subject: [PATCH 1/2] fix: session sigs threshold requirement --- packages/crypto/src/lib/crypto.ts | 7 +- .../src/lib/lit-node-client-nodejs.ts | 112 ++++++++++++++++-- 2 files changed, 109 insertions(+), 10 deletions(-) diff --git a/packages/crypto/src/lib/crypto.ts b/packages/crypto/src/lib/crypto.ts index 70d01e6f2..bf0301f85 100644 --- a/packages/crypto/src/lib/crypto.ts +++ b/packages/crypto/src/lib/crypto.ts @@ -182,6 +182,11 @@ export const combineEcdsaShares = ( sigShares: Array ): CombinedECDSASignature => { const type = sigShares[0].sigType; + + if (!type) { + throw new Error("Sig type is not defined! Here's your sigShares:", sigShares); + } + // the public key can come from any node - it obviously will be identical from each node // const publicKey = sigShares[0].publicKey; // const dataSigned = '0x' + sigShares[0].dataSigned; @@ -190,7 +195,7 @@ export const combineEcdsaShares = ( if (val.signatureShare !== '') { const newVal = _remapKeyShareForEcdsa(val); - if(!newVal.sig_name){ + if (!newVal.sig_name) { newVal.sig_name = 'sig-created-by-lit-sdk'; } diff --git a/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts b/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts index add01d0b7..a85d41441 100644 --- a/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts +++ b/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts @@ -996,7 +996,9 @@ export class LitNodeClientNodeJs extends LitCore { shares.sort((a: any, b: any) => a.shareIndex - b.shareIndex); - const sigShares: Array = shares.map((s: any) => { + const sigShares: Array = shares.map((s: any, index: number) => { + + console.log("Original Share Struct:", s); const share = this._getFlattenShare(s); log("share:", share); @@ -1006,9 +1008,15 @@ export class LitNodeClientNodeJs extends LitCore { } if (!share.bigr) { - throw new Error("bigR is missing"); + throw new Error(`bigR is missing in share ${index}. share ${JSON.stringify(share)}`); } + const sanitisedBigR = sanitise(share.bigr); + const sanitisedSigShare = sanitise(share.publicKey); + + log("sanitisedBigR:", sanitisedBigR); + log("sanitisedSigShare:", sanitisedSigShare); + return { sigType: share.sigType, signatureShare: sanitise(share.signatureShare), @@ -1085,15 +1093,50 @@ export class LitNodeClientNodeJs extends LitCore { */ getSignatures = (signedData: Array): any => { log(`getSignatures(): ${JSON.stringify(signedData, null, 2)}`); + + const validatedSignedData = signedData.map((sigObj: any) => { + + // -- detect whatever signature is available + let signature; + for (let key in sigObj) { + if (sigObj[key]) { + signature = sigObj[key]; + break; + } + } + + const requiredFields = ["signatureShare"]; + + for (const field of requiredFields) { + log("Checking signature:", signature); + + if (!signature[field] || signature[field] === '') { + log(`Invalid signed data. ${field} is missing. Not a problem, we only need ${this.config.minNodeCount} nodes to sign the session key.`); + return null; + } + } + + return sigObj + }).filter((sigObj) => sigObj !== null); + + + log("requested length:", signedData.length); + log("validated length:", validatedSignedData.length); + log("minimum required length:", this.config.minNodeCount); + + if (validatedSignedData.length < this.config.minNodeCount) { + throw new Error(`not enough nodes to get the signatures. Expected ${this.config.minNodeCount}, got ${validatedSignedData.length}`); + } + // -- prepare const signatures: any = {}; // TOOD: get keys of signedData - const keys = Object.keys(signedData[0]); + const keys = Object.keys(validatedSignedData[0]); // -- execute keys.forEach((key: any) => { - const shares = signedData.map((r: any) => r[key]); + const shares = validatedSignedData.map((r: any) => r[key]); shares.sort((a: any, b: any) => a.shareIndex - b.shareIndex); @@ -1113,6 +1156,29 @@ export class LitNodeClientNodeJs extends LitCore { log('getSignatures - sigShares', sigShares); + const validatedSigShares = sigShares.filter((s: any) => { + + const requiredFields = ['sigType', 'signatureShare']; + + for (const field of requiredFields) { + if (!s[field] || s[field] === '') { + log(`Invalid signed data. ${field} is missing. Not a problem, we only need ${this.config.minNodeCount} nodes to sign the session key.`); + return null; + } + } + + return s; + + }).filter((s) => s !== null); + + log("requested length:", signedData.length); + log("validated length:", validatedSigShares.length); + log("minimum required length:", this.config.minNodeCount); + + if (validatedSigShares.length < this.config.minNodeCount) { + throw new Error(`not enough nodes to get the signatures. Expected ${this.config.minNodeCount}, got ${validatedSigShares.length}`); + } + const sigType = mostCommonString(sigShares.map((s: any) => s.sigType)); // -- validate if this.networkPubKeySet is null @@ -1431,7 +1497,7 @@ export class LitNodeClientNodeJs extends LitCore { authMethods, }; - log("XXX reqBody:", reqBody) + log("reqBody:", reqBody) return this.getPkpSignExecutionShares(url, reqBody, requestId); }); @@ -2031,7 +2097,7 @@ export class LitNodeClientNodeJs extends LitCore { }; - log('XXX signSessionKey body', body); + log('signSessionKey body', body); const nodePromises = this.getNodePromises((url: string) => { return this.getSignSessionKeyShares( @@ -2052,7 +2118,7 @@ export class LitNodeClientNodeJs extends LitCore { throw new Error(`Error when handling node promises: ${e}`); } - log("XXX res:", res); + log("handleNodePromises res:", res); // -- case: promises rejected if (!this.#isSuccessNodePromises(res)) { @@ -2069,9 +2135,37 @@ export class LitNodeClientNodeJs extends LitCore { (r: any) => (r as SignedData).signedData ); - log('signedDataList', signedDataList) + log('signedDataList', signedDataList); + + // -- checking if we have enough shares + const validatedSignedDataList = signedDataList.map((signedData: any) => { + + const sessionSig = signedData['sessionSig']; + + // each of this field cannot be empty + const requiredFields = ["sigType", 'dataSigned', 'signatureShare', 'bigr', 'publicKey', 'sigName', 'siweMessage']; + + // check if all required fields are present + for (const field of requiredFields) { + + if (!sessionSig[field] || sessionSig[field] === '') { + log(`Invalid signed data. ${field} is missing. Not a problem, we only need ${this.config.minNodeCount} nodes to sign the session key.`); + return null; + } + } + + return signedData; + }).filter(item => item !== null); + + log("requested length:", signedDataList.length); + log("validated length:", validatedSignedDataList.length); + log("minimum required length:", this.config.minNodeCount); + + if (validatedSignedDataList.length < this.config.minNodeCount) { + throw new Error(`not enough nodes signed the session key. Expected ${this.config.minNodeCount}, got ${validatedSignedDataList.length}`); + } - const signatures = this.getSessionSignatures(signedDataList); + const signatures = this.getSessionSignatures(validatedSignedDataList); const { sessionSig } = signatures; From 77881befe7905422413fdbcfe398b480a19de714 Mon Sep 17 00:00:00 2001 From: Ansonhkg Date: Thu, 19 Oct 2023 16:47:59 +0100 Subject: [PATCH 2/2] fix: use log --- .../lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts b/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts index a85d41441..f7ccceb21 100644 --- a/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts +++ b/packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts @@ -998,7 +998,8 @@ export class LitNodeClientNodeJs extends LitCore { const sigShares: Array = shares.map((s: any, index: number) => { - console.log("Original Share Struct:", s); + log("Original Share Struct:", s); + const share = this._getFlattenShare(s); log("share:", share);