Signature

A Signature is a specific message embedded in a generated proof that will be checked when verifying the proof. It can be requested from the Data Vault via a SignatureRequest.

Why a signature is often needed when verifying proofs onchain?

The signed message is not mandatory when you interact with your contracts, but it is very often needed. As far as your users are generating valid proofs, it could be quite easy for a third party to front-run them by just taking their proof and making their own call to your smart contracts with it.

To overcome this issue, we offer a way to embed a specific message in a proof. This way it can be thought of as a signature since this proof could not be valid without checking successfully that the signed message is correct onchain.

For example, it is mandatory to request the user to embed the address where they want to receive an airdrop in a proof. If a third party takes the proof, the call will be reverted with a signature mismatch message, effectively protecting your users from being front-run.

Example: You are a DAO voting platform, and you want to get the vote of a user onchain. To do so, the user will create a signature containing a message (his vote) that will be used to generate the proof. When verifying the proof onchain, you are also verifying that the proof contains the message. It is then impossible for a malicious actor to take your proof and vote for something else.

Type definitions

The SignatureRequest is an object with the following properties:

  • message (required): the message that the user is going to sign.

  • isSelectableByUser(optional): by default set to false. Allows the user to edit the message in the Sismo Data Vault app.

// Types (typescript version)
type SignatureRequest = {
    message: string;
    isSelectableByUser?: boolean;
};

Integrations

SignatureRequest is made in the front end using either the sismo-connect-react package or the sismo-connect-client package.

The proof with the requested signature is then verified either in a backend using the sismo-connect-server package or in a smart contract using the sismo-connect-solidity package.

If you are verifying your proofs in a smart contract, you will need to encode your signature with some ABI encoder like Viem or EthersJS.

Making a SignatureRequest - Front-end integration

Making an SignatureRequest is only possible if it is made alongside an auth or a claim request.

The SismoConnectButton React component is available from the sismo-connect-react package. It is a wrapper of the sismo-connect-client package.

  • SignatureRequest is passed to the SismoConnectButton through the signature props

  • Responses are received through either:

    1. the onResponse: (response: SismoConnectResponse) => void callback for offchain verification or,

    2. the onResponseBytes (response: string) => void callback for onchain verification.

SignatureRequest - code example

app.tsx
import { SismoConnectButton, SismoConnectClientConfig, SismoConnectResponse, AuthType } from "@sismo-core/sismo-connect-react";

<SismoConnectButton 
    // the client config created
    config={config}
    // signature request must be made with at least an auth or one claim
    auth={{authType: AuthType.VAULT}}
    // your signature request
    // that needs to be encoded if you verify proofs in smart contracts
    signature={{message: "0x00"}}
    onResponse={async (response: SismoConnectResponse) => {
	//Send the response to your server to verify it
	//thanks to the @sismo-core/sismo-connect-server package
    }}
    onResponseBytes={async (bytes: string) => {
        //Send the response to your contract to verify it
        //thanks to the @sismo-core/sismo-connect-solidity package
    }}
/>

Verifying a SignatureRequest

Once a user has generated the proof on the Sismo Data Vault App, your application must verify it. This can be made either offchain in your back end or onchain in your smart contract. The sismo-connect-server package exposes a SismoConnect variable.

A signature request can be verified offchain on a backend server using the sismoConnect.verify() method available on a SismoConnect instance.

If the proof is valid sismoConnect.verify() returns a result of type SismoConnectVerifiedResult else it will throw an error.

SignatureRequest - code example

import { SismoConnect, SismoConnectVerifiedResult, AuthType } from "@sismo-core/sismo-connect-server";

const sismoConnect = SismoConnect({config});

async function verifyResponse(sismoConnectResponse: SismoConnectResponse) {
  // verifies the proofs contained in the sismoConnectResponse
  const result: SismoConnectVerifiedResult = await sismoConnect.verify(
    sismoConnectResponse,
    {
      // signature request must be made with at least an auth or one claim
      auth: { authType: AuthType.VAULT },
      // your signature request
      signature: {message: "0x00"}
    }
  )
}

If you are using Nextjs, you will need to add this config in the next.config.js file to be able to verify the proof. You can find more information here.

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["@sismo-core/sismo-connect-server"],
  },
}

module.exports = nextConfig

Last updated