From ec899c231c2418959f2ec929c0b94992455b10da Mon Sep 17 00:00:00 2001 From: Adarsh-Kumar28 Date: Tue, 10 Dec 2024 15:50:11 +0530 Subject: [PATCH 1/4] test: EIP1271 AuthSig with EthSign --- local-tests/test.ts | 6 + ...estEip1271AuthSigToEncryptDecryptString.ts | 125 ++++++++++++++++++ tsconfig.json | 17 ++- yarn.lock | 15 ++- 4 files changed, 155 insertions(+), 8 deletions(-) create mode 100644 local-tests/tests/testEip1271AuthSigToEncryptDecryptString.ts diff --git a/local-tests/test.ts b/local-tests/test.ts index e140a2d913..11fdc4ceea 100644 --- a/local-tests/test.ts +++ b/local-tests/test.ts @@ -44,6 +44,7 @@ import { testUseInvalidLitActionIpfsCodeToGenerateSessionSigs } from './tests/te import { testSolAuthSigToEncryptDecryptString } from './tests/testSolAuthSigToEncryptDecryptString'; import { testEthAuthSigToEncryptDecryptString } from './tests/testEthAuthSigToEncryptDecryptString'; import { testCosmosAuthSigToEncryptDecryptString } from './tests/testCosmosAuthSigToEncryptDecryptString'; +import { testEip1271AuthSigToEncryptDecryptString } from './tests/testEip1271AuthSigToEncryptDecryptString'; import { testPkpEthersWithEoaSessionSigsToSignMessage } from './tests/testPkpEthersWithEoaSessionSigsToSignMessage'; import { testPkpEthersWithEoaSessionSigsToSignWithAuthContext } from './tests/testPkpEthersWithEoaSessionSigsToSignWithAuthContext'; import { testPkpEthersWithEoaSessionSigsToEthSign } from './tests/testPkpEthersWithEoaSessionSigsToEthSign'; @@ -232,6 +233,10 @@ setLitActionsCodeToLocal(); testCosmosAuthSigToEncryptDecryptString, }; + const eip1271AuthSigTests = { + testEip1271AuthSigToEncryptDecryptString, + }; + const pkpEthersTest = { eoaSessionSigs: { testPkpEthersWithEoaSessionSigsToSignWithAuthContext, @@ -294,6 +299,7 @@ setLitActionsCodeToLocal(); ...litActionIpfsIdSessionSigsTests, ...capacityDelegationTests, ...bareAuthSigTests, + ...eip1271AuthSigTests, ...pkpEthersTest.eoaSessionSigs, ...pkpEthersTest.pkpSessionSigs, diff --git a/local-tests/tests/testEip1271AuthSigToEncryptDecryptString.ts b/local-tests/tests/testEip1271AuthSigToEncryptDecryptString.ts new file mode 100644 index 0000000000..252b2bc485 --- /dev/null +++ b/local-tests/tests/testEip1271AuthSigToEncryptDecryptString.ts @@ -0,0 +1,125 @@ +import { AuthSig, BaseSiweMessage, ILitNodeClient } from '@lit-protocol/types'; +import { AccessControlConditions } from 'local-tests/setup/accs/accs'; +import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; +import { log } from '@lit-protocol/misc'; +import { encryptString, decryptToString } from '@lit-protocol/encryption'; +import { CENTRALISATION_BY_NETWORK } from '@lit-protocol/constants'; +import { createSiweMessage, generateAuthSig } from '@lit-protocol/auth-helpers'; +import { hashMessage } from 'ethers/lib/utils'; +import { ethers } from 'ethers'; + +/** + * Test Commands: + * ✅ NETWORK=datil-dev yarn test:local --filter=testEip1271AuthSigToEncryptDecryptString + * ✅ NETWORK=datil-test yarn test:local --filter=testEip1271AuthSigToEncryptDecryptString + * ✅ NETWORK=custom yarn test:local --filter=testEip1271AuthSigToEncryptDecryptString + */ +export const testEip1271AuthSigToEncryptDecryptString = async ( + devEnv: TinnyEnvironment +) => { + const dataToEncrypt = 'Decrypted from EIP1271 AuthSig'; + const contractAddress = '0x88105De2349f59767278Fd15c0858f806c08d615'; + const abi = [ + "function setTempOwner(address _tempOwner) external", + "function getTempOwner() external view returns (address)", + "function isValidSignature(bytes32 _hash, bytes calldata _signature) external view returns (bytes4)" + ]; + + const alice = await devEnv.createRandomPerson(); + if (CENTRALISATION_BY_NETWORK[devEnv.network] === 'decentralised') { + // The capacity credits NFT owner automatically uses the capacity credits + // to pay for the encryption + await alice.mintCapacityCreditsNFT(); + } + + let accs = AccessControlConditions.getEmvBasicAccessControlConditions({ + userAddress: contractAddress, + }); + accs[0].chain = 'yellowstone'; // Contract deployed on Yellowstone + + const encryptRes = await encryptString( + { + accessControlConditions: accs, + dataToEncrypt, + }, + devEnv.litNodeClient as unknown as ILitNodeClient + ); + + log('encryptRes:', encryptRes); + + if (!encryptRes.ciphertext) { + throw new Error(`Expected "ciphertext" in encryptRes`); + } + + if (!encryptRes.dataToEncryptHash) { + throw new Error(`Expected "dataToEncryptHash" to in encryptRes`); + } + + // Craft the SiweMessage to be hashed & signed + const siweMessage = await createSiweMessage({ + nonce: await devEnv.litNodeClient.getLatestBlockhash(), + walletAddress: alice.wallet.address, + }); + + const siweSignature = await alice.wallet.signMessage(siweMessage); + console.log('siweSignature: ', siweSignature); + + // Internally generate from wallet.signMessage + const hash = hashMessage(siweMessage); + const hashUint8Array = ethers.utils.arrayify(hash); + console.log('hash:', hash); + console.log('hashUint8Array: ', hashUint8Array); // Match it against the hash done on the nodes before calling verifySignature() + + // Test from the contract + const contract = new ethers.Contract(contractAddress, abi, alice.wallet); + + console.log("1. Setting temp owner..."); + const setTempOwnerTx = await contract.setTempOwner(alice.wallet.address); + await setTempOwnerTx.wait(); + console.log("Set temp owner transaction hash: ", setTempOwnerTx.hash); + + const tempOwner = await contract.getTempOwner(); + if (tempOwner.toLowerCase() !== alice.wallet.address.toLowerCase()) { + throw new Error(`Expected temp owner to be ${alice.wallet.address} but got ${tempOwner}`); + } + + console.log("2. Checking isValidSignature..."); + try { + const isValid = await contract.isValidSignature(hash, siweSignature); + if (isValid !== "0x1626ba7e") { + throw new Error(`Expected isValidSignature to be 0x1626ba7e but got ${isValid}`); + } + } catch (error) { + console.error("Error calling isValidSignature:", error); + throw error; + } + + const eip1271AuthSig: AuthSig = { + address: contractAddress, + sig: siweSignature, + derivedVia: "EIP1271", + signedMessage: siweMessage, + }; + + // log(eip1271AuthSig); + + // -- Decrypt the encrypted string + const decryptRes = await decryptToString( + { + accessControlConditions: accs, + ciphertext: encryptRes.ciphertext, + dataToEncryptHash: encryptRes.dataToEncryptHash, + authSig: eip1271AuthSig, + chain: 'yellowstone', // Deployed chain + }, + devEnv.litNodeClient as unknown as ILitNodeClient + ); + + if (decryptRes !== dataToEncrypt) { + throw new Error( + `Expected decryptRes to be ${dataToEncrypt} but got ${decryptRes}` + ); + } + + console.log('✅ decryptRes:', decryptRes); +}; diff --git a/tsconfig.json b/tsconfig.json index d79d1c4238..e8f4e19b50 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,15 +10,24 @@ "importHelpers": true, "target": "ES2020", "module": "ES2020", - "lib": ["ES2020", "dom", "ES2021.String"], + "lib": [ + "ES2020", + "dom", + "ES2021.String" + ], "skipLibCheck": true, "skipDefaultLibCheck": true, "baseUrl": ".", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "paths": { - "@lit-protocol/*": ["packages/*/src"] + "@lit-protocol/*": [ + "packages/*/src" + ] } }, - "exclude": ["node_modules", "tmp"] -} + "exclude": [ + "node_modules", + "tmp" + ] +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 452aa24cc1..74597f3c24 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6866,7 +6866,7 @@ argv-formatter@~1.0.0: resolved "https://registry.yarnpkg.com/argv-formatter/-/argv-formatter-1.0.0.tgz#a0ca0cbc29a5b73e836eebe1cbf6c5e0e4eb82f9" integrity sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw== -aria-query@5.1.3: +aria-query@5.1.3, aria-query@~5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e" integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ== @@ -7176,7 +7176,7 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== -axe-core@^4.10.0: +axe-core@^4.10.0, axe-core@^4.9.1: version "4.10.2" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.2.tgz#85228e3e1d8b8532a27659b332e39b7fa0e022df" integrity sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w== @@ -7218,6 +7218,13 @@ axobject-query@^4.1.0: resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee" integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== +axobject-query@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.1.1.tgz#3b6e5c6d4e43ca7ba51c5babf99d22a9c68485e1" + integrity sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg== + dependencies: + deep-equal "^2.0.5" + babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -11085,7 +11092,7 @@ es-get-iterator@^1.1.3: isarray "^2.0.5" stop-iteration-iterator "^1.0.0" -es-iterator-helpers@^1.1.0: +es-iterator-helpers@^1.0.19, es-iterator-helpers@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz#2f1a3ab998b30cb2d10b195b587c6d9ebdebf152" integrity sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q== @@ -21986,7 +21993,7 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string.prototype.includes@^2.0.1: +string.prototype.includes@^2.0.0, string.prototype.includes@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz#eceef21283640761a81dbe16d6c7171a4edf7d92" integrity sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg== From 253f386abfcda2988ce48d7d5abffe7c6e93e6e6 Mon Sep 17 00:00:00 2001 From: Adarsh-Kumar28 Date: Tue, 10 Dec 2024 16:28:29 +0530 Subject: [PATCH 2/4] test: Add failure case when EIP1271 contract returns 0xffffffff --- ...estEip1271AuthSigToEncryptDecryptString.ts | 71 ++++++++++++++----- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/local-tests/tests/testEip1271AuthSigToEncryptDecryptString.ts b/local-tests/tests/testEip1271AuthSigToEncryptDecryptString.ts index 252b2bc485..a80f314103 100644 --- a/local-tests/tests/testEip1271AuthSigToEncryptDecryptString.ts +++ b/local-tests/tests/testEip1271AuthSigToEncryptDecryptString.ts @@ -19,6 +19,7 @@ export const testEip1271AuthSigToEncryptDecryptString = async ( ) => { const dataToEncrypt = 'Decrypted from EIP1271 AuthSig'; const contractAddress = '0x88105De2349f59767278Fd15c0858f806c08d615'; + const deployerAddress = '0x0b1C5E9E82393AD5d1d1e9a498BF7bAAC13b31Ee'; // No purpose other than to be a random address const abi = [ "function setTempOwner(address _tempOwner) external", "function getTempOwner() external view returns (address)", @@ -45,7 +46,7 @@ export const testEip1271AuthSigToEncryptDecryptString = async ( devEnv.litNodeClient as unknown as ILitNodeClient ); - log('encryptRes:', encryptRes); + // log('encryptRes:', encryptRes); if (!encryptRes.ciphertext) { throw new Error(`Expected "ciphertext" in encryptRes`); @@ -62,47 +63,81 @@ export const testEip1271AuthSigToEncryptDecryptString = async ( }); const siweSignature = await alice.wallet.signMessage(siweMessage); - console.log('siweSignature: ', siweSignature); + log('siweSignature: ', siweSignature); // Internally generate from wallet.signMessage const hash = hashMessage(siweMessage); const hashUint8Array = ethers.utils.arrayify(hash); - console.log('hash:', hash); - console.log('hashUint8Array: ', hashUint8Array); // Match it against the hash done on the nodes before calling verifySignature() + log('hash:', hash); + log('hashUint8Array: ', hashUint8Array); // Match it against the hash done on the nodes before calling verifySignature() + + const eip1271AuthSig: AuthSig = { + address: contractAddress, + sig: siweSignature, + derivedVia: "EIP1271", + signedMessage: siweMessage, + }; + + // log(eip1271AuthSig); // Test from the contract const contract = new ethers.Contract(contractAddress, abi, alice.wallet); + const setDeployerAsTempOwnerTx = await contract.setTempOwner(deployerAddress); + await setDeployerAsTempOwnerTx.wait(); + + log("0. isValidSignature should FAIL since Alice (AuthSig.sig) is not the tempOwner yet"); + try { + const isValid = await contract.isValidSignature(hash, siweSignature); + if (isValid === "0x1626ba7e") { + throw new Error(`Expected isValidSignature to be 0xffffffff but got ${isValid}`); + } + } catch (error) { + log("Error calling isValidSignature:", error); + throw error; + } - console.log("1. Setting temp owner..."); + try { + const _decryptRes = await decryptToString( + { + accessControlConditions: accs, + ciphertext: encryptRes.ciphertext, + dataToEncryptHash: encryptRes.dataToEncryptHash, + authSig: eip1271AuthSig, + chain: 'yellowstone', // Deployed chain + }, + devEnv.litNodeClient as unknown as ILitNodeClient + ); + } catch (error) { + if (!error.message.includes('NodeContractAuthsigUnauthorized') || + !error.message.includes('Access control failed for Smart contract') || + !error.message.includes('validation error: Authsig failed for contract 0x88105De2349f59767278Fd15c0858f806c08d615. Return value was ffffffff.') + ) { + throw new Error(`Expected error message to contain specific EIP1271 validation failure, but got: ${error}`); + } + } + + // Should PASS now + log("1. Setting temp owner..."); const setTempOwnerTx = await contract.setTempOwner(alice.wallet.address); await setTempOwnerTx.wait(); - console.log("Set temp owner transaction hash: ", setTempOwnerTx.hash); + log("Set tempOwner transaction hash: ", setTempOwnerTx.hash); const tempOwner = await contract.getTempOwner(); if (tempOwner.toLowerCase() !== alice.wallet.address.toLowerCase()) { throw new Error(`Expected temp owner to be ${alice.wallet.address} but got ${tempOwner}`); } - console.log("2. Checking isValidSignature..."); + log("2. Checking isValidSignature..."); try { const isValid = await contract.isValidSignature(hash, siweSignature); if (isValid !== "0x1626ba7e") { throw new Error(`Expected isValidSignature to be 0x1626ba7e but got ${isValid}`); } } catch (error) { - console.error("Error calling isValidSignature:", error); + log("Error calling isValidSignature:", error); throw error; } - const eip1271AuthSig: AuthSig = { - address: contractAddress, - sig: siweSignature, - derivedVia: "EIP1271", - signedMessage: siweMessage, - }; - - // log(eip1271AuthSig); - // -- Decrypt the encrypted string const decryptRes = await decryptToString( { @@ -121,5 +156,5 @@ export const testEip1271AuthSigToEncryptDecryptString = async ( ); } - console.log('✅ decryptRes:', decryptRes); + log('✅ decryptRes:', decryptRes); }; From a401416e857ad17b9c854212b7346e360b2d57f2 Mon Sep 17 00:00:00 2001 From: Adarsh-Kumar28 Date: Tue, 10 Dec 2024 17:05:35 +0530 Subject: [PATCH 3/4] test: EIP1271 SHA256 AuthSig suite --- local-tests/test.ts | 6 +- ...akEip1271AuthSigToEncryptDecryptString.ts} | 11 +- ...ShaEip1271AuthSigToEncryptDecryptString.ts | 162 ++++++++++++++++++ 3 files changed, 172 insertions(+), 7 deletions(-) rename local-tests/tests/{testEip1271AuthSigToEncryptDecryptString.ts => testKeccakEip1271AuthSigToEncryptDecryptString.ts} (92%) create mode 100644 local-tests/tests/testShaEip1271AuthSigToEncryptDecryptString.ts diff --git a/local-tests/test.ts b/local-tests/test.ts index 11fdc4ceea..f4154aa420 100644 --- a/local-tests/test.ts +++ b/local-tests/test.ts @@ -44,7 +44,8 @@ import { testUseInvalidLitActionIpfsCodeToGenerateSessionSigs } from './tests/te import { testSolAuthSigToEncryptDecryptString } from './tests/testSolAuthSigToEncryptDecryptString'; import { testEthAuthSigToEncryptDecryptString } from './tests/testEthAuthSigToEncryptDecryptString'; import { testCosmosAuthSigToEncryptDecryptString } from './tests/testCosmosAuthSigToEncryptDecryptString'; -import { testEip1271AuthSigToEncryptDecryptString } from './tests/testEip1271AuthSigToEncryptDecryptString'; +import { testKeccakEip1271AuthSigToEncryptDecryptString } from './tests/testKeccakEip1271AuthSigToEncryptDecryptString'; +import { testShaEip1271AuthSigToEncryptDecryptString } from './tests/testShaEip1271AuthSigToEncryptDecryptString'; import { testPkpEthersWithEoaSessionSigsToSignMessage } from './tests/testPkpEthersWithEoaSessionSigsToSignMessage'; import { testPkpEthersWithEoaSessionSigsToSignWithAuthContext } from './tests/testPkpEthersWithEoaSessionSigsToSignWithAuthContext'; import { testPkpEthersWithEoaSessionSigsToEthSign } from './tests/testPkpEthersWithEoaSessionSigsToEthSign'; @@ -234,7 +235,8 @@ setLitActionsCodeToLocal(); }; const eip1271AuthSigTests = { - testEip1271AuthSigToEncryptDecryptString, + testKeccakEip1271AuthSigToEncryptDecryptString, + testShaEip1271AuthSigToEncryptDecryptString, }; const pkpEthersTest = { diff --git a/local-tests/tests/testEip1271AuthSigToEncryptDecryptString.ts b/local-tests/tests/testKeccakEip1271AuthSigToEncryptDecryptString.ts similarity index 92% rename from local-tests/tests/testEip1271AuthSigToEncryptDecryptString.ts rename to local-tests/tests/testKeccakEip1271AuthSigToEncryptDecryptString.ts index a80f314103..1e27c9062a 100644 --- a/local-tests/tests/testEip1271AuthSigToEncryptDecryptString.ts +++ b/local-tests/tests/testKeccakEip1271AuthSigToEncryptDecryptString.ts @@ -4,17 +4,18 @@ import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; import { log } from '@lit-protocol/misc'; import { encryptString, decryptToString } from '@lit-protocol/encryption'; import { CENTRALISATION_BY_NETWORK } from '@lit-protocol/constants'; -import { createSiweMessage, generateAuthSig } from '@lit-protocol/auth-helpers'; +import { createSiweMessage } from '@lit-protocol/auth-helpers'; import { hashMessage } from 'ethers/lib/utils'; import { ethers } from 'ethers'; +import { createHash } from 'crypto'; /** * Test Commands: - * ✅ NETWORK=datil-dev yarn test:local --filter=testEip1271AuthSigToEncryptDecryptString - * ✅ NETWORK=datil-test yarn test:local --filter=testEip1271AuthSigToEncryptDecryptString - * ✅ NETWORK=custom yarn test:local --filter=testEip1271AuthSigToEncryptDecryptString + * ✅ NETWORK=datil-dev yarn test:local --filter=testKeccakEip1271AuthSigToEncryptDecryptString + * ✅ NETWORK=datil-test yarn test:local --filter=testKeccakEip1271AuthSigToEncryptDecryptString + * ✅ NETWORK=custom yarn test:local --filter=testKeccakEip1271AuthSigToEncryptDecryptString */ -export const testEip1271AuthSigToEncryptDecryptString = async ( +export const testKeccakEip1271AuthSigToEncryptDecryptString = async ( devEnv: TinnyEnvironment ) => { const dataToEncrypt = 'Decrypted from EIP1271 AuthSig'; diff --git a/local-tests/tests/testShaEip1271AuthSigToEncryptDecryptString.ts b/local-tests/tests/testShaEip1271AuthSigToEncryptDecryptString.ts new file mode 100644 index 0000000000..8d899fde51 --- /dev/null +++ b/local-tests/tests/testShaEip1271AuthSigToEncryptDecryptString.ts @@ -0,0 +1,162 @@ +import { AuthSig, BaseSiweMessage, ILitNodeClient } from '@lit-protocol/types'; +import { AccessControlConditions } from 'local-tests/setup/accs/accs'; +import { TinnyEnvironment } from 'local-tests/setup/tinny-environment'; +import { log } from '@lit-protocol/misc'; +import { encryptString, decryptToString } from '@lit-protocol/encryption'; +import { CENTRALISATION_BY_NETWORK } from '@lit-protocol/constants'; +import { createSiweMessage } from '@lit-protocol/auth-helpers'; +import { joinSignature } from 'ethers/lib/utils'; +import { ethers } from 'ethers'; +import { createHash } from 'crypto'; + +/** + * Test Commands: + * ✅ NETWORK=datil-dev yarn test:local --filter=testShaEip1271AuthSigToEncryptDecryptString + * ✅ NETWORK=datil-test yarn test:local --filter=testShaEip1271AuthSigToEncryptDecryptString + * ✅ NETWORK=custom yarn test:local --filter=testShaEip1271AuthSigToEncryptDecryptString + */ +export const testShaEip1271AuthSigToEncryptDecryptString = async ( + devEnv: TinnyEnvironment +) => { + const dataToEncrypt = 'Decrypted from EIP1271 AuthSig'; + const contractAddress = '0x88105De2349f59767278Fd15c0858f806c08d615'; + const deployerAddress = '0x0b1C5E9E82393AD5d1d1e9a498BF7bAAC13b31Ee'; // No purpose other than to be a random address + const abi = [ + "function setTempOwner(address _tempOwner) external", + "function getTempOwner() external view returns (address)", + "function isValidSignature(bytes32 _hash, bytes calldata _signature) external view returns (bytes4)" + ]; + + const alice = await devEnv.createRandomPerson(); + if (CENTRALISATION_BY_NETWORK[devEnv.network] === 'decentralised') { + // The capacity credits NFT owner automatically uses the capacity credits + // to pay for the encryption + await alice.mintCapacityCreditsNFT(); + } + + let accs = AccessControlConditions.getEmvBasicAccessControlConditions({ + userAddress: contractAddress, + }); + accs[0].chain = 'yellowstone'; // Contract deployed on Yellowstone + + const encryptRes = await encryptString( + { + accessControlConditions: accs, + dataToEncrypt, + }, + devEnv.litNodeClient as unknown as ILitNodeClient + ); + + // log('encryptRes:', encryptRes); + + if (!encryptRes.ciphertext) { + throw new Error(`Expected "ciphertext" in encryptRes`); + } + + if (!encryptRes.dataToEncryptHash) { + throw new Error(`Expected "dataToEncryptHash" to in encryptRes`); + } + + // Craft the SiweMessage to be hashed & signed + const siweMessage = await createSiweMessage({ + nonce: await devEnv.litNodeClient.getLatestBlockhash(), + walletAddress: alice.wallet.address, + }); + + // Explicitly SHA256 hash the SIWE message + const hash = createHash('sha256').update(siweMessage).digest(); + const hashHex = '0x' + hash.toString('hex'); + const hashUint8Array = ethers.utils.arrayify(hashHex); + log('hash:', hashHex); + log('hashUint8Array: ', hashUint8Array); // Match it against the hash done on the nodes before calling verifySignature() + + const siweSignature = joinSignature(alice.wallet._signingKey().signDigest(hashHex)); + log('siweSignature: ', siweSignature); + + const eip1271AuthSig: AuthSig = { + address: contractAddress, + sig: siweSignature, + derivedVia: "EIP1271_SHA256", + signedMessage: siweMessage, + }; + + // log(eip1271AuthSig); + + // Test from the contract + const contract = new ethers.Contract(contractAddress, abi, alice.wallet); + const setDeployerAsTempOwnerTx = await contract.setTempOwner(deployerAddress); + await setDeployerAsTempOwnerTx.wait(); + + log("0. isValidSignature should FAIL since Alice (AuthSig.sig) is not the tempOwner yet"); + try { + const isValid = await contract.isValidSignature(hash, siweSignature); + if (isValid === "0x1626ba7e") { + throw new Error(`Expected isValidSignature to be 0xffffffff but got ${isValid}`); + } + } catch (error) { + log("Error calling isValidSignature:", error); + throw error; + } + + try { + const _decryptRes = await decryptToString( + { + accessControlConditions: accs, + ciphertext: encryptRes.ciphertext, + dataToEncryptHash: encryptRes.dataToEncryptHash, + authSig: eip1271AuthSig, + chain: 'yellowstone', // Deployed chain + }, + devEnv.litNodeClient as unknown as ILitNodeClient + ); + } catch (error) { + if (!error.message.includes('NodeContractAuthsigUnauthorized') || + !error.message.includes('Access control failed for Smart contract') || + !error.message.includes('validation error: Authsig failed for contract 0x88105De2349f59767278Fd15c0858f806c08d615. Return value was ffffffff.') + ) { + throw new Error(`Expected error message to contain specific EIP1271 validation failure, but got: ${error}`); + } + } + + // Should PASS now + log("1. Setting temp owner..."); + const setTempOwnerTx = await contract.setTempOwner(alice.wallet.address); + await setTempOwnerTx.wait(); + log("Set tempOwner transaction hash: ", setTempOwnerTx.hash); + + const tempOwner = await contract.getTempOwner(); + if (tempOwner.toLowerCase() !== alice.wallet.address.toLowerCase()) { + throw new Error(`Expected temp owner to be ${alice.wallet.address} but got ${tempOwner}`); + } + + log("2. Checking isValidSignature..."); + try { + const isValid = await contract.isValidSignature(hash, siweSignature); + if (isValid !== "0x1626ba7e") { + throw new Error(`Expected isValidSignature to be 0x1626ba7e but got ${isValid}`); + } + } catch (error) { + log("Error calling isValidSignature:", error); + throw error; + } + + // -- Decrypt the encrypted string + const decryptRes = await decryptToString( + { + accessControlConditions: accs, + ciphertext: encryptRes.ciphertext, + dataToEncryptHash: encryptRes.dataToEncryptHash, + authSig: eip1271AuthSig, + chain: 'yellowstone', // Deployed chain + }, + devEnv.litNodeClient as unknown as ILitNodeClient + ); + + if (decryptRes !== dataToEncrypt) { + throw new Error( + `Expected decryptRes to be ${dataToEncrypt} but got ${decryptRes}` + ); + } + + log('✅ decryptRes:', decryptRes); +}; From 08c4f0e0ac1aa1bbddf266db776a00fac2efba7f Mon Sep 17 00:00:00 2001 From: Adarsh-Kumar28 Date: Tue, 10 Dec 2024 17:34:27 +0530 Subject: [PATCH 4/4] refac: Prettier --- ...cakEip1271AuthSigToEncryptDecryptString.ts | 51 ++++++++++------- ...ShaEip1271AuthSigToEncryptDecryptString.ts | 55 ++++++++++++------- tsconfig.json | 17 ++---- 3 files changed, 71 insertions(+), 52 deletions(-) diff --git a/local-tests/tests/testKeccakEip1271AuthSigToEncryptDecryptString.ts b/local-tests/tests/testKeccakEip1271AuthSigToEncryptDecryptString.ts index 1e27c9062a..ac4d9cf0c2 100644 --- a/local-tests/tests/testKeccakEip1271AuthSigToEncryptDecryptString.ts +++ b/local-tests/tests/testKeccakEip1271AuthSigToEncryptDecryptString.ts @@ -22,9 +22,9 @@ export const testKeccakEip1271AuthSigToEncryptDecryptString = async ( const contractAddress = '0x88105De2349f59767278Fd15c0858f806c08d615'; const deployerAddress = '0x0b1C5E9E82393AD5d1d1e9a498BF7bAAC13b31Ee'; // No purpose other than to be a random address const abi = [ - "function setTempOwner(address _tempOwner) external", - "function getTempOwner() external view returns (address)", - "function isValidSignature(bytes32 _hash, bytes calldata _signature) external view returns (bytes4)" + 'function setTempOwner(address _tempOwner) external', + 'function getTempOwner() external view returns (address)', + 'function isValidSignature(bytes32 _hash, bytes calldata _signature) external view returns (bytes4)', ]; const alice = await devEnv.createRandomPerson(); @@ -75,7 +75,7 @@ export const testKeccakEip1271AuthSigToEncryptDecryptString = async ( const eip1271AuthSig: AuthSig = { address: contractAddress, sig: siweSignature, - derivedVia: "EIP1271", + derivedVia: 'EIP1271', signedMessage: siweMessage, }; @@ -86,14 +86,18 @@ export const testKeccakEip1271AuthSigToEncryptDecryptString = async ( const setDeployerAsTempOwnerTx = await contract.setTempOwner(deployerAddress); await setDeployerAsTempOwnerTx.wait(); - log("0. isValidSignature should FAIL since Alice (AuthSig.sig) is not the tempOwner yet"); + log( + '0. isValidSignature should FAIL since Alice (AuthSig.sig) is not the tempOwner yet' + ); try { const isValid = await contract.isValidSignature(hash, siweSignature); - if (isValid === "0x1626ba7e") { - throw new Error(`Expected isValidSignature to be 0xffffffff but got ${isValid}`); + if (isValid === '0x1626ba7e') { + throw new Error( + `Expected isValidSignature to be 0xffffffff but got ${isValid}` + ); } } catch (error) { - log("Error calling isValidSignature:", error); + log('Error calling isValidSignature:', error); throw error; } @@ -109,33 +113,42 @@ export const testKeccakEip1271AuthSigToEncryptDecryptString = async ( devEnv.litNodeClient as unknown as ILitNodeClient ); } catch (error) { - if (!error.message.includes('NodeContractAuthsigUnauthorized') || + if ( + !error.message.includes('NodeContractAuthsigUnauthorized') || !error.message.includes('Access control failed for Smart contract') || - !error.message.includes('validation error: Authsig failed for contract 0x88105De2349f59767278Fd15c0858f806c08d615. Return value was ffffffff.') - ) { - throw new Error(`Expected error message to contain specific EIP1271 validation failure, but got: ${error}`); + !error.message.includes( + 'validation error: Authsig failed for contract 0x88105De2349f59767278Fd15c0858f806c08d615. Return value was ffffffff.' + ) + ) { + throw new Error( + `Expected error message to contain specific EIP1271 validation failure, but got: ${error}` + ); } } // Should PASS now - log("1. Setting temp owner..."); + log('1. Setting temp owner...'); const setTempOwnerTx = await contract.setTempOwner(alice.wallet.address); await setTempOwnerTx.wait(); - log("Set tempOwner transaction hash: ", setTempOwnerTx.hash); + log('Set tempOwner transaction hash: ', setTempOwnerTx.hash); const tempOwner = await contract.getTempOwner(); if (tempOwner.toLowerCase() !== alice.wallet.address.toLowerCase()) { - throw new Error(`Expected temp owner to be ${alice.wallet.address} but got ${tempOwner}`); + throw new Error( + `Expected temp owner to be ${alice.wallet.address} but got ${tempOwner}` + ); } - log("2. Checking isValidSignature..."); + log('2. Checking isValidSignature...'); try { const isValid = await contract.isValidSignature(hash, siweSignature); - if (isValid !== "0x1626ba7e") { - throw new Error(`Expected isValidSignature to be 0x1626ba7e but got ${isValid}`); + if (isValid !== '0x1626ba7e') { + throw new Error( + `Expected isValidSignature to be 0x1626ba7e but got ${isValid}` + ); } } catch (error) { - log("Error calling isValidSignature:", error); + log('Error calling isValidSignature:', error); throw error; } diff --git a/local-tests/tests/testShaEip1271AuthSigToEncryptDecryptString.ts b/local-tests/tests/testShaEip1271AuthSigToEncryptDecryptString.ts index 8d899fde51..b858f02dec 100644 --- a/local-tests/tests/testShaEip1271AuthSigToEncryptDecryptString.ts +++ b/local-tests/tests/testShaEip1271AuthSigToEncryptDecryptString.ts @@ -22,9 +22,9 @@ export const testShaEip1271AuthSigToEncryptDecryptString = async ( const contractAddress = '0x88105De2349f59767278Fd15c0858f806c08d615'; const deployerAddress = '0x0b1C5E9E82393AD5d1d1e9a498BF7bAAC13b31Ee'; // No purpose other than to be a random address const abi = [ - "function setTempOwner(address _tempOwner) external", - "function getTempOwner() external view returns (address)", - "function isValidSignature(bytes32 _hash, bytes calldata _signature) external view returns (bytes4)" + 'function setTempOwner(address _tempOwner) external', + 'function getTempOwner() external view returns (address)', + 'function isValidSignature(bytes32 _hash, bytes calldata _signature) external view returns (bytes4)', ]; const alice = await devEnv.createRandomPerson(); @@ -70,13 +70,15 @@ export const testShaEip1271AuthSigToEncryptDecryptString = async ( log('hash:', hashHex); log('hashUint8Array: ', hashUint8Array); // Match it against the hash done on the nodes before calling verifySignature() - const siweSignature = joinSignature(alice.wallet._signingKey().signDigest(hashHex)); + const siweSignature = joinSignature( + alice.wallet._signingKey().signDigest(hashHex) + ); log('siweSignature: ', siweSignature); const eip1271AuthSig: AuthSig = { address: contractAddress, sig: siweSignature, - derivedVia: "EIP1271_SHA256", + derivedVia: 'EIP1271_SHA256', signedMessage: siweMessage, }; @@ -87,14 +89,18 @@ export const testShaEip1271AuthSigToEncryptDecryptString = async ( const setDeployerAsTempOwnerTx = await contract.setTempOwner(deployerAddress); await setDeployerAsTempOwnerTx.wait(); - log("0. isValidSignature should FAIL since Alice (AuthSig.sig) is not the tempOwner yet"); + log( + '0. isValidSignature should FAIL since Alice (AuthSig.sig) is not the tempOwner yet' + ); try { const isValid = await contract.isValidSignature(hash, siweSignature); - if (isValid === "0x1626ba7e") { - throw new Error(`Expected isValidSignature to be 0xffffffff but got ${isValid}`); + if (isValid === '0x1626ba7e') { + throw new Error( + `Expected isValidSignature to be 0xffffffff but got ${isValid}` + ); } } catch (error) { - log("Error calling isValidSignature:", error); + log('Error calling isValidSignature:', error); throw error; } @@ -110,33 +116,42 @@ export const testShaEip1271AuthSigToEncryptDecryptString = async ( devEnv.litNodeClient as unknown as ILitNodeClient ); } catch (error) { - if (!error.message.includes('NodeContractAuthsigUnauthorized') || + if ( + !error.message.includes('NodeContractAuthsigUnauthorized') || !error.message.includes('Access control failed for Smart contract') || - !error.message.includes('validation error: Authsig failed for contract 0x88105De2349f59767278Fd15c0858f806c08d615. Return value was ffffffff.') - ) { - throw new Error(`Expected error message to contain specific EIP1271 validation failure, but got: ${error}`); + !error.message.includes( + 'validation error: Authsig failed for contract 0x88105De2349f59767278Fd15c0858f806c08d615. Return value was ffffffff.' + ) + ) { + throw new Error( + `Expected error message to contain specific EIP1271 validation failure, but got: ${error}` + ); } } // Should PASS now - log("1. Setting temp owner..."); + log('1. Setting temp owner...'); const setTempOwnerTx = await contract.setTempOwner(alice.wallet.address); await setTempOwnerTx.wait(); - log("Set tempOwner transaction hash: ", setTempOwnerTx.hash); + log('Set tempOwner transaction hash: ', setTempOwnerTx.hash); const tempOwner = await contract.getTempOwner(); if (tempOwner.toLowerCase() !== alice.wallet.address.toLowerCase()) { - throw new Error(`Expected temp owner to be ${alice.wallet.address} but got ${tempOwner}`); + throw new Error( + `Expected temp owner to be ${alice.wallet.address} but got ${tempOwner}` + ); } - log("2. Checking isValidSignature..."); + log('2. Checking isValidSignature...'); try { const isValid = await contract.isValidSignature(hash, siweSignature); - if (isValid !== "0x1626ba7e") { - throw new Error(`Expected isValidSignature to be 0x1626ba7e but got ${isValid}`); + if (isValid !== '0x1626ba7e') { + throw new Error( + `Expected isValidSignature to be 0x1626ba7e but got ${isValid}` + ); } } catch (error) { - log("Error calling isValidSignature:", error); + log('Error calling isValidSignature:', error); throw error; } diff --git a/tsconfig.json b/tsconfig.json index e8f4e19b50..d79d1c4238 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,24 +10,15 @@ "importHelpers": true, "target": "ES2020", "module": "ES2020", - "lib": [ - "ES2020", - "dom", - "ES2021.String" - ], + "lib": ["ES2020", "dom", "ES2021.String"], "skipLibCheck": true, "skipDefaultLibCheck": true, "baseUrl": ".", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "paths": { - "@lit-protocol/*": [ - "packages/*/src" - ] + "@lit-protocol/*": ["packages/*/src"] } }, - "exclude": [ - "node_modules", - "tmp" - ] -} \ No newline at end of file + "exclude": ["node_modules", "tmp"] +}