IPFS & Arweave verification

How can we guarantee the integrity of the content attached to a promise?

As described previously, there are two ways of creating a promise: from the App, or from the contract. The former enables the App to generate an encrypted proof, containing both the IPFS CID and the Arweave ID, along with the Ethereum address of the user.

This is meaningful considering that, if the promise was issued from the application, we can vouch for the integrity of the content, as we are confident it has indeed been:

  • caught by our IPFS node, meaning its distribution is being covered by Web3 Storage through the Filecoin network ;

  • sent properly to the Arweave blockchain.

Regardless of whether the promise was created from the application or from the contract, users can still contribute to indexing the IPFS directory of a promise (Indexing an IPFS directory). This way, they can ensure that it will be permanently available.

How is the proof encrypted?

Right after sending files to IPFS, and optionally to Arweave, the application takes the returned hashes, along with the user address, and proceeds to encrypting them.

NewPromiseDrawer.js
const encryptedProof = encryptAES256(userAddress, ipfsCid, arweaveId);

This encryptAES256 function is entrusted with carrying out this AES 256 encryption, given a secret key shared with the External Adapter. Consider the following, available in the context of the application, in the repository.

encryptAES256.js
const encryptAES256 = (userAddress, ipfsCid, arweaveId) => {
  // Grab the secret key
  const key = process.env.NEXT_PUBLIC_AES_ENCRYPTION_KEY;
  // Join the user address with the hashes
  const data = userAddress + ipfsCid + arweaveId;

  // Generate a random iv in hex format
  const iv = CryptoJS.lib.WordArray.random(16).toString(CryptoJS.enc.Hex);

  // Encrypt in AES 256 CBC
  const encryptedData = CryptoJS.AES.encrypt(data, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7,
  });

  // Turn the encrypted data into a hex string
  const encryptedHex = Buffer.from(encryptedData.toString(), 'base64').toString(
    'hex',
  );

  // Prepend it with the random iv for use in decryption
  return iv + encryptedHex;
};

The returned string is then supplied as a parameter to the createPromiseContract function, which makes a request to the external adapter to verify it.

How does the EA verify the proof?

The External Adapter is written as a serverless function. Each time it is triggered with a request, the API server grabs the input parameters, performs the custom computation, and sends back its result (or an error, if anything happens in between).

The process following the request is described in The verification process.

Consider the following code, from the createRequest function in the external adapter ; it is documented so the process is more transparent to follow:

Once the result is returned to the VerifyStorage contract, it can fulfill the request and call the PromiseFactory to update the storage status for this promise.

Resources

Last updated