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.
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.
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.
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);
};