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.
SignatureRequest is passed to the SismoConnectButton through the signature props
Responses are received through either:
the onResponse: (response: SismoConnectResponse) => void callback for offchain verification or,
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 createdconfig={config}// signature request must be made with at least an auth or one claimauth={{authType:AuthType.VAULT}}// your signature request// that needs to be encoded if you verify proofs in smart contractssignature={{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 }}/>
One or multiple claim requests can be made using the sismoConnect.request() method available on the sismoConnect variable.
Responses could be received through either:
the sismoConnect.getResponse() method for offchain verification or,
the sismoConnect.getResponseBytes() method for onchain verification.
One ClaimRequest - code example
App.tsx
import { useSismoConnect, SismoConnectResponse, AuthType } from"@sismo-core/sismo-connect-react";const { sismoConnect } =useSismoConnect({ config });functiononClick(){sismoConnect.request({// 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"} });}// Proofs are available in two differents types depending on usage (offchain or onchaon verification)constresponse:SismoConnectResponse|null=sismoConnect.getResponse();constresponseBytes:string|null=sismoConnect.getResponseBytes();if(response || responseBytes) {// Send response to the backend to verify it or,// Send responseBytes to smart contract to verify it. }
One or multiple ClaimRequests can be made using the sismoConnect.request() method available on a SismoConnect instance.
Responses could be received through either:
the sismoConnect.getResponse() method for offchain verification or,
the sismoConnect.getResponseBytes() method for onchain verification.
One ClaimRequest - code example
app.ts
import { SismoConnect, SismoConnectResponse, AuthType } from"@sismo-core/sismo-connect-client";constsismoConnect=SismoConnect({config});// your signature requestfunctiononClick(){sismoConnect.request({// 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"} });}// Receive the proofs in two different formatsconstresponse:SismoConnectResponse|null=sismoConnect.getResponse();constresponseBytes:string|null=sismoConnect.getResponseBytes();if(response || responseBytes) {// Send response to the backend to verify it or,// Send responseBytes to smart contract to verify it. }
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";constsismoConnect=SismoConnect({config});asyncfunctionverifyResponse(sismoConnectResponse:SismoConnectResponse) {// verifies the proofs contained in the sismoConnectResponseconstresult:SismoConnectVerifiedResult=awaitsismoConnect.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.
The sismo-connect-solidity package exposes a Sismo Connect Library, which can be inherited by your contract either using Foundry or Hardhat.
The Sismo Connect Library exposes:
a verify() function, which allows you to verify a proof generated by the Sismo Vault app with respect to some requests directly in your contract. The verify() function takes an object containing:
a responseBytes send from the front end,
a signature corresponding to the signature request made in the front end,
an auth or a claim.
SignatureRequest - code example
contractMyContractisSismoConnect { // inherits from Sismo Connect library// call SismoConnect constructor with your appIdconstructor(bytes16 appId) SismoConnect(buildConfig(appId)) {}functiondoSomethingUsingSismoConnect(bytesmemory sismoConnectResponse) public { SismoConnectVerifiedResult memory result =verify({ responseBytes: sismoConnectResponse,// signature request must be made with at least an auth or one claim auth:buildAuth({authType: AuthType.VAULT}),// we want to check if the signed message provided in the response is the signature of the user's address signature:buildSignature({message: abi.encode(msg.sender)}) });// do something once verified }}