Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ digest
generate-digest.ts

.cursor/rules
packages/networks/src/networks/vDatil
lit-auth-storage
.ctx
packages/auth-services/lit-auth-*
Expand Down
11 changes: 11 additions & 0 deletions apps/explorer/src/assets/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,12 @@ declare namespace Lit {
toSign,
publicKey,
sigName,
keySetIdentifier,
}: {
toSign: Uint8Array | number[];
publicKey: string;
sigName: string;
keySetIdentifier?: 'datil' | 'naga-keyset1';
}): Promise<string>;

/**
Expand Down Expand Up @@ -270,6 +272,7 @@ declare namespace Lit {
}): any;

/**
* @deprecated - deprecated unused function
* Claim a key through a key identifier, the result of the claim will be added to `claim_id`
* under the `keyId` given.
* @param {Object} params
Expand Down Expand Up @@ -308,12 +311,14 @@ declare namespace Lit {
dataToEncryptHash,
authSig,
chain,
keySetIdentifier,
}: {
accessControlConditions: string;
ciphertext: string;
dataToEncryptHash: string;
authSig: string;
chain: string;
keySetIdentifier?: 'datil' | 'naga-keyset1';
}): Promise<string>;

/**
Expand All @@ -332,12 +337,14 @@ declare namespace Lit {
dataToEncryptHash,
authSig,
chain,
keySetIdentifier,
}: {
accessControlConditions: string;
ciphertext: string;
dataToEncryptHash: string;
authSig: string;
chain: string;
keySetIdentifier?: 'datil' | 'naga-keyset1';
}): Promise<string>;

/**
Expand All @@ -352,10 +359,12 @@ declare namespace Lit {
toSign,
publicKey,
sigName,
keySetIdentifier,
}: {
toSign: Uint8Array;
publicKey: string;
sigName: string;
keySetIdentifier?: 'datil' | 'naga-keyset1';
}): Promise<string>;

/**
Expand Down Expand Up @@ -395,9 +404,11 @@ declare namespace Lit {
function encrypt({
accessControlConditions,
to_encrypt,
keySetIdentifier,
}: {
accessControlConditions: string;
to_encrypt: string;
keySetIdentifier?: 'datil' | 'naga-keyset1';
}): Promise<{
ciphertext: string;
dataToEncryptHash: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const code = String.raw`(async () => {
await Lit.Actions.encrypt({
accessControlConditions,
to_encrypt: ethers.utils.toUtf8Bytes(entropyHex),
keySetIdentifier: jsParams?.keySetIdentifier,
})
);
}
Expand Down Expand Up @@ -98,6 +99,7 @@ const code = String.raw`(async () => {
dataToEncryptHash: encryptResult.dataToEncryptHash, // Use original format
authSig: null,
chain: "ethereum",
keySetIdentifier: jsParams?.keySetIdentifier,
});

// Convert decrypted result to hex for comparison
Expand Down Expand Up @@ -158,4 +160,7 @@ export default {
"Encrypt data tied to the current action CID, decrypt it with decryptAndCombine, and verify the round trip.",
order: 30,
code,
jsParams: {
keySetIdentifier: "naga-keyset1",
},
} satisfies LitActionExample;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { LitActionExample } from "../types";

const code = String.raw`const { sigName, toSign, publicKey, } = jsParams;
const code = String.raw`const { sigName, toSign, publicKey, keySetIdentifier } = jsParams;
const { keccak256, arrayify } = ethers.utils;

(async () => {
Expand All @@ -12,6 +12,7 @@ const { keccak256, arrayify } = ethers.utils;
toSign: toSignBytes32Array,
publicKey,
sigName,
keySetIdentifier,
});
})();`;

Expand All @@ -24,5 +25,6 @@ export default {
jsParams: {
sigName: "sig1",
toSign: "Hello from Lit Action",
keySetIdentifier: "naga-keyset1",
},
} satisfies LitActionExample;
21 changes: 20 additions & 1 deletion apps/explorer/src/lit-actions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,12 @@ declare namespace Lit {
toSign,
publicKey,
sigName,
keySetIdentifier,
}: {
toSign: Uint8Array;
publicKey: string;
sigName: string;
keySetIdentifier?: 'datil' | 'naga-keyset1';
}): Promise<string>;
/**
* @param {Uint8array} toSign the message to sign
Expand Down Expand Up @@ -177,7 +179,14 @@ declare namespace Lit {
publicKey,
sigName,
signingScheme,
}: Uint8array): Uint8array;
keySetIdentifier,
}: {
toSign: Uint8Array;
publicKey: string;
sigName: string;
signingScheme: string;
keySetIdentifier?: 'datil' | 'naga-keyset1';
}): Uint8Array;
/**
* Sign data using the Lit Action's own cryptographic identity derived from its IPFS CID.
* This allows actions to sign as themselves (not as a PKP), enabling autonomous agent behavior,
Expand Down Expand Up @@ -405,12 +414,14 @@ declare namespace Lit {
dataToEncryptHash,
authSig,
chain,
keySetIdentifier,
}: {
accessControlConditions: Array<any>;
ciphertext: string;
dataToEncryptHash: string;
authSig: any;
chain: string;
keySetIdentifier?: 'datil' | 'naga-keyset1';
}): Promise<string>;
/**
* Decrypt to a single node
Expand All @@ -429,12 +440,14 @@ declare namespace Lit {
dataToEncryptHash,
authSig,
chain,
keySetIdentifier,
}: {
accessControlConditions: Array<any>;
ciphertext: string;
dataToEncryptHash: string;
authSig: any;
chain: string;
keySetIdentifier?: 'datil' | 'naga-keyset1';
}): Promise<string>;
/**
* Sign with ECDSA and automatically combine signature shares from all nodes into a complete signature
Expand All @@ -449,10 +462,12 @@ declare namespace Lit {
toSign,
publicKey,
sigName,
keySetIdentifier,
}: {
toSign: Uint8Array;
publicKey: string;
sigName: string;
keySetIdentifier?: 'datil' | 'naga-keyset1';
}): Promise<Uint8Array>;
/**
* Sign with any signing scheme and automatically combine signature shares from all nodes into a complete signature
Expand All @@ -474,11 +489,13 @@ declare namespace Lit {
publicKey,
sigName,
signingScheme,
keySetIdentifier,
}: {
toSign: Uint8Array;
publicKey: string;
sigName: string;
signingScheme: string;
keySetIdentifier?: 'datil' | 'naga-keyset1';
}): Promise<Uint8Array>;
/**
* Run a function only once across all nodes using leader election
Expand Down Expand Up @@ -518,9 +535,11 @@ declare namespace Lit {
function encrypt({
accessControlConditions,
to_encrypt,
keySetIdentifier,
}: {
accessControlConditions: Array<any>;
to_encrypt: string;
keySetIdentifier?: 'datil' | 'naga-keyset1';
}): Promise<{
ciphertext: string;
dataToEncryptHash: string;
Expand Down
66 changes: 66 additions & 0 deletions docs/sdk/auth-context-consumption/keysets.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Keysets in the JS SDK

Datil keys can be used on Naga by selecting a keyset per request. Keyset selection is **explicit and optional** – if omitted, the SDK defaults to `naga-keyset1`.

## When to pass `keySetIdentifier`

- Decrypt requests (`decrypt`): add `keySetIdentifier` to pick Datil vs Naga keys for decryption.
- PKP signing (`pkpSign` / chain helpers): add `keySetIdentifier` to sign with a specific keyset.
- Session key signing (`signSessionKey`): accepts `keySetIdentifier`, but sessions are always signed with the Naga keyset (Datil sessions are not valid on Naga).
- Lit Actions bindings: pass `keySetIdentifier` to `signEcdsa`, `sign`, `signAndCombineEcdsa`, `signAndCombine`, `decryptAndCombine`, `decryptToSingleNode`, and `encrypt`.

## Examples

### PKP Sign with a keyset

```ts
const signature = await litClient.chain.raw.pkpSign({
chain: 'ethereum',
signingScheme: 'EcdsaK256Sha256',
pubKey: pkpPublicKey,
toSign: new Uint8Array([1, 2, 3]),
sessionSigs, // or authContext
keySetIdentifier: 'datil', // or 'naga-keyset1'
});
```

### Lit Action signing with a keyset

```ts
const code = `
const go = async () => {
const resp = await Lit.Actions.signEcdsa({
toSign: new Uint8Array([1, 2, 3, 4]),
publicKey: "${pkpPublicKey}",
sigName: "sig",
keySetIdentifier: "datil", // or "naga-keyset1"
});
Lit.Actions.setResponse({ response: resp });
};
go();
`;

const result = await litClient.executeJs({
sessionSigs,
code,
useSingleNode: true,
});
```

### Decrypt with a keyset

```ts
const { decryptedData } = await litClient.decrypt({
accessControlConditions,
ciphertext,
dataToEncryptHash,
authContext,
chain: 'ethereum',
keySetIdentifier: 'datil',
});
```

> **Note:** If you pass `keySetIdentifier: "datil"` to `signSessionKey`, the session is still signed with the Naga keyset; Datil sessions are not accepted on Naga.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
HexPrefixedSchema,
LitResourceAbilityRequestSchema,
} from '@lit-protocol/schemas';
import { KEY_SET_IDENTIFIERS } from '@lit-protocol/constants';
import { z } from 'zod';

// =========== Default values ===========
Expand Down Expand Up @@ -42,5 +43,8 @@ export const AuthConfigSchema = z.preprocess(
statement: z.string().optional().default(''),
domain: DomainSchema.optional().default('localhost'),
resources: z.array(LitResourceAbilityRequestSchema).optional().default([]),
keySetIdentifier: z
.enum([KEY_SET_IDENTIFIERS.DATIL, KEY_SET_IDENTIFIERS.NAGA_KEYSET1])
.optional(),
})
);
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ const prepareCustomAuthRequestBody = async (
curveType: 'BLS' as const,
signingScheme: 'BLS' as const,
epoch: params.deps.currentEpoch,
keySetIdentifier: _authConfig.keySetIdentifier,
};

// Add lit action parameters - ensure at least one is present
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ const preparePkpAuthRequestBody = async (
curveType: 'BLS' as const,
signingScheme: 'BLS' as const,
epoch: params.deps.currentEpoch,
keySetIdentifier: _authConfig.keySetIdentifier,
};
};

Expand Down
7 changes: 7 additions & 0 deletions packages/constants/src/lib/constants/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ export const VMTYPE = {
export type VMTYPE_TYPE = ConstantKeys<typeof VMTYPE>;
export type VMTYPE_VALUES = ConstantValues<typeof VMTYPE>;

// Keyset identifiers used by Lit networks
export const KEY_SET_IDENTIFIERS = {
DATIL: 'datil',
NAGA_KEYSET1: 'naga-keyset1',
} as const;
export type KEY_SET_IDENTIFIER_VALUES = ConstantValues<typeof KEY_SET_IDENTIFIERS>;

/**
* Lit Protocol Network Public Key
*/
Expand Down
4 changes: 4 additions & 0 deletions packages/e2e/src/e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
registerPaymentDelegationTicketSuite,
} from '@lit-protocol/e2e';
import { registerWrappedKeysTests } from './test-helpers/executeJs/wrappedKeys';
import { registerKeysetTests } from './test-helpers/executeJs/keysets';

const SELECTED_NETWORK = process.env['NETWORK'];
const IS_PAID_NETWORK = SELECTED_NETWORK !== 'naga-dev';
Expand Down Expand Up @@ -308,6 +309,9 @@ describe('all', () => {
describe('wrapped keys', () => {
registerWrappedKeysTests();
});
describe('keysets', () => {
registerKeysetTests();
});
});
});

Expand Down
1 change: 1 addition & 0 deletions packages/e2e/src/helper/tests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export { createViemSignTypedDataTest } from './viem-sign-typed-data';
// We should move the above tests into their own category/folder like this one
export { createPregenDelegationServerReuseTest } from '../../test-helpers/signSessionKey/pregen-delegation';
export { registerWrappedKeysTests } from '../../test-helpers/executeJs/wrappedKeys';
export { registerKeysetTests } from '../../test-helpers/executeJs/keysets';
Loading
Loading