Skip to main content

Signing with EIP191

You can also use EIP191 eth_personal_sign to sign a message, instead of a transaction or raw signature.

This can be done with LitActions.ethPersonalSignMessageEcdsa({ message, publicKey , sigName }); when signing. It will prepend "\x19Ethereum Signed Message:\n" to the message and then hash and sign it according to

import * as LitJsSdk from '@lit-protocol/lit-node-client';
import fs from "fs";
import { serialize, recoverAddress } from "@ethersproject/transactions";
import {
} from "@ethersproject/bytes";
import { recoverPublicKey, computePublicKey } from "@ethersproject/signing-key";
import { verifyMessage } from "@ethersproject/wallet";

// this code will be run on the node
const litActionCode = `
const go = async () => {
// this requests a signature share from the Lit Node
// the signature share will be automatically returned in the HTTP response from the node
// all the params (toSign, publicKey, sigName) are passed in from the LitJsSdk.executeJs() function
const sigShare = await LitActions.ethPersonalSignMessageEcdsa({ message, publicKey , sigName });


// you need an AuthSig to auth with the nodes
// normally you would obtain an AuthSig by calling LitJsSdk.checkAndSignAuthMessage({chain})
const authSig = {
sig: "0x2bdede6164f56a601fc17a8a78327d28b54e87cf3fa20373fca1d73b804566736d76efe2dd79a4627870a50e66e1a9050ca333b6f98d9415d8bca424980611ca1c",
derivedVia: "web3.eth.personal.sign",
"localhost wants you to sign in with your Ethereum account:\n0x9D1a5EC58232A894eBFcB5e466E3075b23101B89\n\nThis is a key for Partiful\n\nURI: https://localhost/login\nVersion: 1\nChain ID: 1\nNonce: 1LF00rraLO4f7ZSIt\nIssued At: 2022-06-03T05:59:09.959Z",
address: "0x9D1a5EC58232A894eBFcB5e466E3075b23101B89",

const go = async () => {
const message = "Hello World";
const litNodeClient = new LitJsSdk.LitNodeClient({
litNetwork: "custom",
bootstrapUrls: [
await litNodeClient.connect();
const signatures = await litNodeClient.executeJs({
code: litActionCode,
jsParams: {
// this is the string "Hello World" for testing
sigName: "sig1",
console.log("signatures: ", signatures);
const sig = signatures.sig1;
const dataSigned = "0x" + sig.dataSigned;
const encodedSig = joinSignature({
r: "0x" + sig.r,
s: "0x" + sig.s,
v: sig.recid,

console.log("encodedSig", encodedSig);
console.log("sig length in bytes: ", encodedSig.substring(2).length / 2);
console.log("dataSigned", dataSigned);
const splitSig = splitSignature(encodedSig);
console.log("splitSig", splitSig);

const recoveredPubkey = recoverPublicKey(dataSigned, encodedSig);
console.log("uncompressed recoveredPubkey", recoveredPubkey);
const compressedRecoveredPubkey = computePublicKey(recoveredPubkey, true);
console.log("compressed recoveredPubkey", compressedRecoveredPubkey);
const recoveredAddress = recoverAddress(dataSigned, encodedSig);
console.log("recoveredAddress", recoveredAddress);

const recoveredAddressViaMessage = verifyMessage(message, encodedSig);
console.log("recoveredAddressViaMessage", recoveredAddressViaMessage);