-
Notifications
You must be signed in to change notification settings - Fork 12
Decrypt and Combine Rework #336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
0b862af
e7ff668
dd2b13a
579a470
294f2b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,99 +4,75 @@ import FeedbackComponent from "@site/src/pages/feedback.md"; | |
|
||
## Overview | ||
|
||
Decryption with Lit is typically performed client-side by an authorized user at the time of access. This process is documented [here](../access-control/quick-start.md). However, an alternative method of decryption is supported using Lit Actions. Specifically, the `decryptAndCombine` function can be used to decrypt data within a Lit Action. This is useful for performing operations over sensitive data, where the data itself remains private within the confines of each Lit node's Trusted Execution Environment (TEE). You can learn more about Lit's architecture [here](../../resources/how-it-works#sealed-and-confidential-hardware.md). | ||
|
||
When you call `decryptAndCombine`, each Lit node's decryption shares are collected and combined on a single node and used to decrypt the given content. | ||
|
||
The following doc will provide a complete walkthrough of using `decryptAndCombine`. We'll start by encrypting a string client-side before using a Lit Action to decrypt it. At the bottom of the page you'll find a complete example that demonstrates how you can use this functionality to decrypt an API key and perform a remote API call from within an Action. | ||
|
||
# Encrypting content | ||
The first step is to encrypt your data. The encryption operation will be performed client-side *outside* of your Lit Action using the `LitNodeClient`: | ||
|
||
```js | ||
const chain = 'ethereum'; | ||
const accessControlConditions = [ | ||
{ | ||
contractAddress: '', | ||
standardContractType: '', | ||
chain, | ||
method: 'eth_getBalance', | ||
parameters: [':userAddress', 'latest'], | ||
returnValueTest: { | ||
comparator: '>=', | ||
value: '0', | ||
}, | ||
}, | ||
]; | ||
const message = 'Hello world'; | ||
const client = new LitNodeClient({ | ||
litNetwork: "datil-dev" | ||
}); | ||
await client.connect(); | ||
const { ciphertext, dataToEncryptHash } = await LitJsSdk.encryptString( | ||
{ | ||
accessControlConditions, | ||
sessionSigs: {}, // your session | ||
chain, | ||
dataToEncrypt: message, | ||
}, | ||
client | ||
); | ||
|
||
console.log("cipher text:", ciphertext, "hash:", dataToEncryptHash); | ||
``` | ||
Let's break this down. The first step was creating your Access Control Condition (ACC), which is used to specify who or under what conditions your data should be able to be decrypted. | ||
|
||
The second step was actually encrypting the static content (string, file, zip, etc...) using the `encryptString` function. This returns a `ciphertext` and `dataToEncryptHash`. The `ciphertext`, `dataToEncryptHash`, chain data, and any other metadata (such as your `accessControlConditions`) should be stored on your storage provider of choice. A solid choice is IPFS. | ||
|
||
## Using IPFS CID as an Access Control Parameter | ||
For this example, you can set your Access Control parameter as `currentActionIpfsId` which can be accomplished using the snippet below. This will mean that only a specific Lit Action (based on the IPFS CID where it has been deployed) will be able to decrypt your data. No other party will ever have access. This is useful for situations where you want to restrict access to sensitive information, like an API key, so that it can only be decrypted by a specific Lit Action. | ||
|
||
```js | ||
{ | ||
contractAddress: '', | ||
standardContractType: '', | ||
chain: 'ethereum', | ||
method: '', | ||
parameters: [':currentActionIpfsId'], | ||
returnValueTest: { | ||
comparator: '=', | ||
value: '<YOUR_LIT_ACTION_IPFS_CID>', | ||
}, | ||
} | ||
``` | ||
Decryption with Lit can be performed either client-side by an authorized user or within a Lit Action. | ||
|
||
Using decryption within a Lit Action is useful for performing operations over sensitive data, where the data itself remains private within the confines of each Lit node's Trusted Execution Environment (TEE). You can learn more about Lit's architecture [here](../../resources/how-it-works#sealed-and-confidential-hardware.md). | ||
|
||
Lit Actions have two methods for decrypting data: `decryptToSingleNode` and `decryptAndCombine`. The former reduces the execution scope of the Lit Action to a single node and decrypts the data there. The latter collects each Lit node's decryption share, combines them, and then decrypts the data on a single node. The key difference between the two is that `decryptToSingleNode` only uses the decryption share of a single Lit node, while `decryptAndCombine` uses all of the decryption shares of all Lit nodes. | ||
|
||
When `decryptToSingleNode` is used, the execution scope being reduced to a single Lit node means that any behavior that requires multiple nodes (i.e. console logs, `signAndCombineEcdsa`) will encounter a timeout error. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When you say console logs, do you mean There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should add a snippet on how to end execution on all the Lit node that weren't selected for the decryption That looks something like this |
||
|
||
## Using decryptAndCombine | ||
The following example demonstrates how to encrypt an API key client-side, then decrypt and use it within a Lit Action to query the block number on Base. | ||
|
||
We can now use the `ciphertext` and `dataToEncryptHash` that we got earlier during the encryption step and pass it into our Lit Action. | ||
## Prerequsites | ||
- Knowledge of [SessionSigs](../authentication/session-sigs/intro) | ||
- Basic understanding of [Lit Actions](../serverless-signing/quick-start) | ||
- Intermediate understanding of Lit [Encryption and Decryption](../access-control/quick-start) | ||
|
||
In the below example we set the `authSig` to `null` as a way to tell the Lit Action runtime to use the `authSig` which was provided to the node when you call `executeJs` which returns `sessionSigs`. If you wish you may provide a different Auth Signature if the one provided from the session is not relevant to your use case. You can learn more about authentication and creating session signatures using these [docs](../authentication/session-sigs/intro.md). | ||
## Complete Code Example | ||
The complete code example is available in the [Lit Developer Guides Code Repository](https://github.com/LIT-Protocol/developer-guides-code/tree/master/decrypt-api-key-in-action/nodejs). | ||
|
||
```js | ||
const code = `(async () => { | ||
const resp = await Lit.Actions.decryptAndCombine({ | ||
accessControlConditions, | ||
ciphertext, | ||
dataToEncryptHash, | ||
authSig: null, | ||
chain: 'ethereum', | ||
}); | ||
### Example Lit Action | ||
|
||
Lit.Actions.setResponse({ response: resp }); | ||
})();` | ||
The `decryptAndCombine` function uses the `accessControlConditions` to specify who and under what conditions the data can be decrypted. The `ciphertext` and `dataToEncryptHash` are the encrypted data and the hash of the data that was encrypted. | ||
|
||
const res = await client.executeJs({ | ||
code, | ||
sessionSigs: {} // your session | ||
jsParams: { | ||
accessControlConditions, | ||
ciphertext, | ||
dataToEncryptHash | ||
We set the `authSig` to null as a way to tell the Lit Action runtime to use the `authSig` which was provided to the node when you call `executeJs`. It will use the AuthSig within the session signatures. | ||
spacesailor24 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Then our decrypted API key is used to query the blocknumber on Base. | ||
|
||
```tsx | ||
const _litActionCode = async () => { | ||
try { | ||
const apiKey = await Lit.Actions.decryptAndCombine({ | ||
accessControlConditions, | ||
ciphertext, | ||
dataToEncryptHash, | ||
authSig: null, | ||
chain: "ethereum", | ||
}); | ||
|
||
const fullUrl = url + apiKey; | ||
|
||
const resp = await fetch(fullUrl, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
jsonrpc: "2.0", | ||
id: 1, | ||
method: "eth_blockNumber", | ||
params: [], | ||
}), | ||
}); | ||
|
||
let data = await resp.json(); | ||
|
||
if (data.result) { | ||
data.result = parseInt(data.result, 16); | ||
} | ||
}); | ||
|
||
console.log("decrypted content sent from lit action:", res); | ||
Lit.Actions.setResponse({ response: JSON.stringify(data) }); | ||
} catch (e) { | ||
Lit.Actions.setResponse({ response: e.message }); | ||
} | ||
}; | ||
|
||
export const litActionCode = `(${_litActionCode.toString()})();`; | ||
``` | ||
|
||
## Complete Example: Decrypting an API Key From Within an Action | ||
The following example demonstrates how you can decrypt an API key within a Lit Action. Once decrypted, the API key can be used to perform a remote API call. Check out the complete code example [here](https://github.com/LIT-Protocol/developer-guides-code/tree/master/decrypt-api-key-in-action). | ||
## Summary | ||
|
||
This guide demonstrates how to use Lit Actions to decrypt data within a Lit Action. | ||
|
||
If you'd like to learn more about Lit Actions, check out the [Lit Actions SDK](https://actions-docs.litprotocol.com/), or our [Advanced Topics](https://developer.litprotocol.com/category/advanced-topics-1) section on Lit Actions. |
Uh oh!
There was an error while loading. Please reload this page.