Documentation Index
Fetch the complete documentation index at: https://developer.litprotocol.com/llms.txt
Use this file to discover all available pages before exploring further.
Gating Logic — AKA Access Control Conditions
The older Datil / Naga Lit SDK offered a fluent builder for declaring access control conditions (ACCs): structured objects that describe who may decrypt ciphertext or call an action. A typical condition using the SDK looks like this:Action-Identity Signing — Immutable Proofs
Every Lit Action has a cryptographic identity derived from its IPFS CID.Lit.Actions.getLitActionPrivateKey() retrieves a private key that is deterministically derived from the content hash of the action code. There is no way to produce that key outside of that exact code running inside the Lit network.
This means any signature produced with this key carries a guarantee: the data was produced by that specific, immutable action. If the action code changes by a single byte, it gets a new IPFS CID, a new key, and a new identity. There is no way to forge the signature without controlling both the Lit network and the exact source code.
This is useful any time you want to produce a verifiable proof — a signed output that a smart contract, API, or third party can verify came from a specific computation, not an arbitrary off-chain script.
Example: Signing a Price Feed
- Retrieve the action’s public key or wallet address via
Lit.Actions.getLitActionPublicKey({ ipfsId })(callable from inside another action) or by fetching it once and caching it. - Call
ethers.utils.verifyMessage(payload, signature)and compare the recovered address to the known action address.
Use
getLitActionPrivateKey when the proof must be tied to the action code itself. Use getPrivateKey({ pkpId }) when the proof must be tied to a specific PKP wallet (e.g. an account or a user’s identity). Both patterns produce verifiable signatures; they differ in what identity the signature is bound to.What if Someone Else Runs My Action?
A common concern with Action-Identity Signing is: what happens if someone copies my Lit Action and runs it themselves? In many cases, it doesn’t matter. Because the action’s identity is tied to its IPFS CID, anyone running the same action is executing the exact same immutable code. If your action only does a single thing — like signing a price feed — then someone else running it is simply paying for the execution on your behalf. The output carries the same cryptographic guarantee regardless of who triggered it. This applies to pure, side-effect-free actions. If your action writes to an external database, calls a third-party API, or triggers transactions, unauthorized execution could cause duplicate writes or exhaust rate limits. If you need to restrict who can execute the action, there are three layers of control:-
API key scoping (primary). Configure which API keys have
executepermission on which groups through the Dashboard. This is enforced at the API gateway before the action runs, so unauthorized callers never reach your code. -
PKP address check. If the group is configured so that only a specific PKP can be used with the action, you can check the PKP address as a parameter inside the action. Although
js_paramsare caller-supplied, the ownership model makes this reliable: the caller can only use PKPs that belong to their account and are permitted within the group. An attacker cannot pass an arbitrary PKP address because the gateway already verified that the PKP is owned by the caller’s account.
- Signature verification (defense-in-depth). For additional assurance beyond the ownership model, require the caller to sign a challenge and verify the signature cryptographically inside the action. The
messageshould include a nonce or timestamp so that a previously captured signature cannot be replayed:
Encrypt / Decrypt — PKP Wallets as Data Vaults
One PKP per logical data boundary
The best practice for encrypting a set of related data is to create a dedicated PKP wallet for that data boundary. The PKP’s derived symmetric key is then used to encrypt everything in that boundary — user records, API keys, configuration, documents, whatever belongs together.ciphertext anywhere — IPFS, a database, a smart contract — without risk. Without the PKP’s derived key (which never leaves the TEE), the ciphertext is opaque.
Giving dApp users access through gating conditions
To let a dApp user read encrypted data, you give them access to a decrypt action that enforces your gating conditions before callingLit.Actions.Decrypt. The user calls the action with a reference to the vault PKP; if their condition is met, they receive the plaintext. If not, they receive an error.
The symmetric key is never shared. It is derived inside the TEE, used to decrypt, and discarded. The user only ever sees the plaintext result — and only if the action’s gating logic allows it.
Securing RPC URLs — Hiding API Keys with Encryption
Many RPC providers require an API key appended to the endpoint URL (e.g.https://mainnet.infura.io/v3/YOUR_API_KEY). Passing the full URL as a js_params value would expose the key to anyone who can inspect the action call. Instead, you can encrypt the secret portion of the URL and let the Lit Action decrypt and reassemble it at runtime inside the TEE.
This pattern provides two guarantees:
- The API key is never visible to the caller or in the transaction parameters — it only exists in plaintext inside the TEE during execution.
- The action is verifiably calling a specific chain — the base URL is passed in the clear (or hardcoded), so observers can confirm which network the action targets, while the confidential key portion stays hidden.
Setup: Encrypt the API key
Use a dedicated “secrets” PKP to encrypt the API key once. Store the resulting ciphertext alongside the action or in your configuration.Usage: Decrypt and connect at runtime
The production action receives the encrypted API key, decrypts it inside the TEE, and assembles the full RPC URL.You should hard-code the base URL directly in the action code rather than passing it as a parameter. Because the action is pinned to IPFS, hardcoding makes the target chain immutable — verifiable by anyone who inspects the action’s CID.
Why this is safe to expose
Sharing a PKP ID (the wallet address) with users is safe because:- The private key is only accessible inside a Lit Action running in a TEE — it is never returned to callers and never leaves the node.
- The symmetric key used for encryption is derived from the private key inside the TEE. It is also never returned.
- The ciphertext is meaningless without the derived key.
- The only way to get plaintext is to run an action that holds the right PKP and chooses to call
Decrypt— so your gating logic is the sole enforcement point.
pkpId and the ciphertext indefinitely. They gain access to the plaintext only if and when the gating logic inside the action is satisfied.