Skip to main content

Exporting a Wrapped Key

This guide covers the exportPrivateKey function from the Wrapped Keys SDK. For an overview of what a Wrapped Key is and what can be done with it, please go here.

Using the exportPrivateKey function, you can export existing Wrapped Keys to decrypt and obtain their underlying private keys. The Wrapped Keys SDK will look up the corresponding encryption metadata (ciphertext and dataToEncryptHash) for your PKP in Lit's private DynamoDB instance. If found, it well then use your provided PKP Session Signatures to authorize decryption of the private key, and will return it to you in clear text.

Below we will walk through an implementation of exportPrivateKey. The full code implementation can be found here.

Prerequisites

Before continuing with this guide, you should have an understanding of:

exportPrivateKey's Interface

Source code

/** Exports a previously persisted private key from the wrapped keys service for direct use by the caller, along with the keys metadata
*/
export async function exportPrivateKey(
params: {
pkpSessionSigs: SessionSigsMap;
litNodeClient: ILitNodeClient;
}
): Promise<{
pkpAddress: string;
decryptedPrivateKey: string;
publicKey: string;
litNetwork: LIT_NETWORKS_KEYS;
keyType: string;
}>

Parameters

pkpSessionSigs

When a Wrapped Key is generated, it's encrypted with the following Access Control Conditions:

[
{
contractAddress: '',
standardContractType: '',
chain: CHAIN_ETHEREUM,
method: '',
parameters: [':userAddress'],
returnValueTest: {
comparator: '=',
value: pkpAddress,
},
},
];

where pkpAddress is the addressed derived from the pkpSessionSigs. This restricts the decryption of the Wrapped Key to only those whom can generate valid Authentication Signatures from the PKP which generated the Wrapped Key.

A valid pkpSessionSigs object can be obtained using the getPkpSessionSigs helper method available on an instance of LitNodeClient. We dive deeper into obtaining a pkpSessionSigs using getPkpSessionSigs in the Generating PKP Session Signatures section of this guide.

litNodeClient

This is an instance of the LitNodeClient that is connected to a Lit network.

Return Value

pkpAddress

This is the Ethereum address for the PKP that is associated with the Wrapped Key i.e. the PKP that created the Session Signatures when the Wrapped Key was imported/generated, and used for encrypting the private key. The address is derived from the provided pkpSessionSigs.

decryptedPrivateKey

danger

This return value is the private key unencrypted and clear text.

Be mindful when and where you're calling this method as to not expose the private key to anyone who should not have direct access to it.

This is the underlying private key for the Wrapped Key that was either imported into the Lit network, or generated by a Wrapped Keys Lit Action.

publicKey

This is the corresponding public key for the wrapped private key that was either imported into the Lit network, or generated by a Wrapped Keys Lit Action.

litNetwork

This is the Lit network that the LitNodeClient was connected to when the Wrapped Key was created.

keyType

This is the algorithm used to generate the underlying private key for the Wrapped Key.

Example Implementation

Now that we know what the exportPrivateKey function does, it's parameters, and it's return values, let's now dig into a complete implementation.

The full code implementation can be found here.

Installing the Required Dependencies

npm install \
@lit-protocol/auth-helpers \
@lit-protocol/constants \
@lit-protocol/lit-auth-client \
@lit-protocol/lit-node-client \
@lit-protocol/wrapped-keys \
ethers@v5

Instantiating an Ethers Signer

The ETHEREUM_PRIVATE_KEY environment variable is required. The corresponding Ethereum address needs to have ownership of the PKP we will be using to generate the pkpSessionSigs.

import * as ethers from 'ethers';

const ethersSigner = new ethers.Wallet(
process.env.ETHEREUM_PRIVATE_KEY,
new ethers.providers.JsonRpcProvider(
"https://chain-rpc.litprotocol.com/http"
)
);

Instantiating a LitNodeClient

Here we are instantiating an instance of LitNodeClient and connecting it to the cayenne Lit network.

import { LitNodeClient } from "@lit-protocol/lit-node-client";
import { LitNetwork } from "@lit-protocol/constants";

const litNodeClient = new LitNodeClient({
litNetwork: LitNetwork.Cayenne,
debug: false,
});
await litNodeClient.connect();

Generating PKP Session Signatures

The LIT_PKP_PUBLIC_KEY environment variable is required. This PKP should be owned by the corresponding Ethereum address for the ETHEREUM_PRIVATE_KEY environment variable.

The PKP's Ethereum address will be used for the Access Control Conditions used to encrypt the generated private key, and by default, will be the only entity able to authorize decryption of the private key.

note

The expiration used for the Auth Method must be 10 minutes or less to be valid.

note

The Auth Method used in this example implementation is signing a Sign in With Ethereum (EIP-4361) message using an Externally Owned Account (EOA), but any Auth Method can be used to authenticate with Lit to get PKP Session Signatures.

import { EthWalletProvider } from "@lit-protocol/lit-auth-client";
import {
LitAbility,
LitActionResource,
LitPKPResource,
} from "@lit-protocol/auth-helpers";

const pkpSessionSigs = await litNodeClient.getPkpSessionSigs({
pkpPublicKey: process.env.LIT_PKP_PUBLIC_KEY,
authMethods: [
await EthWalletProvider.authenticate({
signer: ethersSigner,
litNodeClient,
expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(), // 10 minutes
}),
],
resourceAbilityRequests: [
{
resource: new LitActionResource("*"),
ability: LitAbility.LitActionExecution,
},
],
expiration: new Date(Date.now() + 1000 * 60 * 10).toISOString(), // 10 minutes
});

Exporting a Wrapped Key

danger

The return value from successfully calling exportPrivateKey includes the unencrypted private key in clear text.

Be mindful when and where you're calling this method as to not expose the private key to anyone who should not have direct access to it.

Now that we have all that we need, we can call exportPrivateKey to export the underlying private key for the Wrapped Key:

import { api } from "@lit-protocol/wrapped-keys";

const { exportPrivateKey } = api;

const exportedPrivateKeyResult = await exportPrivateKey({
pkpSessionSigs,
litNodeClient,
});

Summary

The full code implementation can be found here.

After executing the example implementation above, you will have exported the underlying private key for the Wrapped Key associated with the PKP that produced the provided pkpSessionSigs.