đŸšĒAccess control with zkTLS

Adding access control with zkTLS for encrypting a file involves two primary steps: creating access conditions for a Content Identifier (CID) and submitting proofs for verification.

Step 1: Creating Access Conditions for a CID

To enable zkTLS-based access control for any file or data, you must define access conditions for the respective CID.

import * as dotenv from 'dotenv'
dotenv.config()
import { ethers } from "ethers"
import axios from "axios";

const signAuthMessage = async (privateKey) => {
  const signer = new ethers.Wallet(privateKey);
  const messageRequested = await axios.get(
    `https://encryption.lighthouse.storage/api/message/${signer.address}`
  );
  const signedMessage = await signer.signMessage(
    messageRequested.data[0].message
  );
  return signedMessage;
};

const applyzkconditions = async () => {
  // CID of encrypted file
  // CID is generated by uploading a file with encryption
  // Only the owner of the file can apply access conditions
  const cid = "bafkreibwimyyrqiqhl7difiu3gl6a5znf2ml7tgrh3uekfsitvrqczkzr4";
  const publicKey = "0xa3c960b3ba29367ecbcaf1430452c6cd7516f588";
  const privateKey = process.env.PRIVATE_KEY_WALLET1;
  const nodeId = [1, 2, 3, 4, 5];
  const nodeUrl = nodeId.map(
    (elem) =>
      `https://encryption.lighthouse.storage/api/setZkConditions/${elem}`
  );

  const signedMessage = await signAuthMessage(privateKey);
  const config = {
    method: "post",
    headers: {
      Accept: "application/json",
      Authorization: `Bearer ${signedMessage}`,
    },
  };
  const apidata = {
    address: publicKey,
    cid: cid,
    conditions: [
      {
        id: 1,
        method: "City",
        returnValueTest: {
          comparator: "==",
          value: "New York",
        },
      },
    ],
  };
  const requestData = async (url) => {
    try {
      return await axios({
        url,
        data: apidata,
        ...config,
      });
    } catch (error) {
      console.log(error);
      return {
        isSuccess: false,
        error: JSON.parse(error.message),
      };
    }
  };
  const data = [];
  for (const [index, url] of nodeUrl.entries()) {
    const response = await requestData(url);
    data.push(response.data);
  }
};

This step sets the access rules for the data based on zkTLS proofs, such as verifying a user's location or other verifiable attributes.

Step 2: Verifying zkTLS Proof and Accessing the File

Once the conditions are set, users must submit their zkTLS proof along with the CID to gain access to the data.

const verifyAndDecrypt = async () => {
  const cid = "bafkreibwimyyrqiqhl7difiu3gl6a5znf2ml7tgrh3uekfsitvrqczkzr4";
  const publicKey = "0xa3c960b3ba29367ecbcaf1430452c6cd7516f588";
  const nodeId = [1, 2, 3, 4, 5];
  const nodeUrl = nodeId.map(
    (elem) =>
      `https://encryption.lighthouse.storage/api/verifyZkConditions/${elem}`
  );
  const signedMessage = await signAuthMessage(privateKey);
  const config = {
    method: "post",
    headers: {
      Accept: "application/json",
      Authorization: `Bearer ${signedMessage}`,
    },
  };
  const apidata = {
    address: publicKey,
    cid: cid,
    proof: proof_from_reclaim_protocol
  };
  const requestData = async (url) => {
    try {
      return await axios({
        url,
        data: apidata,
        ...config,
      });
    } catch (error) {
      console.log(error);
      return {
        isSuccess: false,
        error: JSON.parse(error.message),
      };
    }
  };
  const shards = [];
  for (const [index, url] of nodeUrl.entries()) {
    const response = await requestData(url);
    shards.push(response.data.payload);
  }

  const { masterKey: key, error: recoverError } = await recoverKey(shards);
  if (recoverError) {
    throw recoverError;
  }

  const decrypted = await decryptFile(cid, key);

  fs.createWriteStream("fileName.png").write(Buffer.from(decrypted));
  return "File decrypted successfully";
};

If the proof is successfully verified, the user will be granted access to the encrypted data.

Fetching Access Conditions for a CID

If you need to retrieve the current access conditions for a specific CID, Lighthouse provides an API to fetch these conditions.


const getZkConditions = async () => {
  const signedMessage = await signAuthMessage(privateKey);
  const config = {
    method: "get",
    headers: {
      Accept: "application/json",
      Authorization: `Bearer ${signedMessage}`,
    },
  };
  const response = await axios({
    url: `https://encryption.lighthouse.storage/api/getZkConditions/${cid}`,
    ...config,
  });
  console.log(response.data);
};

Last updated