Skip to main content
This documentation outlines the process of creating and verifying proofs using the Signer Service API. The flow involves multiple steps, from converting a digital asset to creating a verifiable signature.

createProof

This function orchestrates all the API calls in sequence to generate a proof.
export async function createProof(file, description) {
  const fileBase64 = await fileToBase64(file);

  let messageHashOutput = await messageHashAPI(fileBase64);
  let blindedSignature = await commitAPI(description, messageHashOutput);
  let getChallengeResult = await getChallengeAPI(blindedSignature);
  let solveChallengeResult = await solveChallengeAPI(getChallengeResult);  
  let unblindSignatureResult = await unblindSignatureAPI(solveChallengeResult);  

  return unblindSignatureResult;
}
1

Convert your digital asset/content

First, the digital asset is converted to a Base64 string.
2

Blind your Content

Call the messageHashAPI function to hash the Base64-encoded message.
3

Submit your Signing request

Use commitAPI and pass the hash and public description to create a blinded signature.
4

Make a ZK proof for Content

Retrieve a ZK challenge for the commitment signature using the getChallengeAPI.
5

Solve ZK challenge

Use the solveChallengeAPI to solve the ZK challenge.
6

Unblind the signature

Call the unblindSignatureAPI to unblind the signature.
7

Create verifiable signature

The self verifiable signature is returned as JSON.

1. fileToBase64

Purpose:

Converts a file into a base64-encoded string without the metadata portion (data:…). This is the first step before sending the file content to any API.
function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    
    reader.onload = () => resolve(reader.result.split(',')[1]);  // Extract base64 string without the metadata part
    reader.onerror = error => reject(error);
  });
}
This function is used to read a file, converting it into a Base64 string that will be sent to the messageHashAPI for hashing.

2. messageHashAPI

Purpose:

Hashes the base64-encoded file content by sending it to an API.
async function messageHashAPI(base64Data) {
  const response = await fetch('https://api.truthstamp.ai/recipient/messageHash', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': API_KEY
    },
    body: JSON.stringify({
      message: JSON.stringify(base64Data),
    }),
  });

  if (!response.ok) {
    throw new Error('Failed to call the messageHashAPI');
  }  
  return response.json();
}

3. commitAPI

Purpose:

Creates a blinded signature by sending the hashed message and a description to the API.
async function commitAPI(description, messageHashOutput) {
  const response = await fetch('https://api.truthstamp.ai/signer/commit', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': API_KEY
    },
    body: JSON.stringify({
      commonInfo: description,
      blindedMessage: messageHashOutput.messageHash,
    }),
  });

  if (!response.ok) {
    throw new Error('Failed to call the commitAPI');
  }

  return response.json();
}

4. getChallengeAPI

Purpose:

Requests a ZK challenge from the API using the blinded signature created earlier.
async function getChallengeAPI(blindedSignatureOutput) {
  const response = await fetch('https://api.truthstamp.ai/recipient/getChallenge', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': API_KEY
    },
    body: JSON.stringify({
      "signatureCommitmentString": blindedSignatureOutput.signatureCommitmentString,
      "blindedMessage": blindedSignatureOutput.blindedMessage,
      "commonInfo": blindedSignatureOutput.commonInfo,
      "publicKey": blindedSignatureOutput.publicKey
    }),
  });

  if (!response.ok) {
    throw new Error('Failed to call the getChallengeAPI');
  }

  return response.json();
}

5. solveChallengeAPI

Purpose:

Solves the ZK challenge using the challenge format returned by the previous step.
async function solveChallengeAPI(getChallengeResultOut) {
  const response = await fetch('https://api.truthstamp.ai/signer/challenge', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': API_KEY
    },
    body: JSON.stringify({
      "challengeFormat": getChallengeResultOut.challengeFormat,
      "signatureCommitmentOut": getChallengeResultOut.signatureCommitmentOut,
      "publicKey": getChallengeResultOut.publicKey,
      "blindedMessage": getChallengeResultOut.blindedMessage,
      "commonInfo": getChallengeResultOut.commonInfo
    }),
  });

  if (!response.ok) {
    throw new Error('Failed to call the solveChallengeAPI');
  }

  return response.json();
}

6. unblindSignatureAPI

Purpose:

Unblinds the signature using the ZK challenge solution recieved.
async function unblindSignatureAPI(solveChallengeResult) {
  const response = await fetch('https://api.truthstamp.ai/recipient/unblindSignature', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': API_KEY
    },
    body: JSON.stringify({
      "challengeOut": solveChallengeResult.challengeOut,
      "solutionFormat": solveChallengeResult.solutionFormat,
      "signatureCommitmentOut": solveChallengeResult.signatureCommitmentOut,
      "publicKey": solveChallengeResult.publicKey,
      "blindedMessage": solveChallengeResult.blindedMessage,
      "commonInfo": solveChallengeResult.commonInfo
    }),
  });

  if (!response.ok) {
    throw new Error('Failed to call the unblindSignature');
  }
  return response.json();
}

verifyProof

This function is used to verify the proof.
export async function verifyProof(proofData) {
  let verifySignatureResult;
  try {
    verifySignatureResult = await verifySignatureAPI(proofData);
  } catch (error) {
    return 'Invalid format';
  }
  return verifySignatureResult;
}
1

Verify Signature

Pass the proof data to the verifySignatureAPI.
2

Return Result

Return the verification result.

verifySignatureAPI

Purpose:

Verifies the signature and return true/false.
async function verifySignatureAPI(unblindSignatureResult) {
  const response = await fetch('https://api.truthstamp.ai/verifier/verifySignature', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': API_KEY
    },
    body: JSON.stringify({
      "publicKey": unblindSignatureResult.publicKey,
      "commonInfo": unblindSignatureResult.commonInfo,
      "signatureString": unblindSignatureResult.signatureString,
      "m1Hat": unblindSignatureResult.m1Hat
    }),
  });

  if (!response.ok) {
    throw new Error('Failed to call the verifySignatureAPI');
  }

  return response.json();  // Assuming the verifySignatureAPI returns JSON
}