{
  "path": "/posts/how-to-encrypt-and-decrypt-files-on-ipfs-using-lit",
  "site": "at://did:plc:ia2zdnhjaokf5lazhxrmj6eu/site.standard.publication/3mbykzswhqc2x",
  "tags": [
    "ipfs",
    "blockchain",
    "tutorials"
  ],
  "$type": "site.standard.document",
  "title": "How to Encrypt and Decrypt Files on IPFS Using Lit Protocol",
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreiccgitch63nvy35ivglwypndw3u5c5uzcn7ed2omhvv3x4tuxw7vq"
    },
    "mimeType": "image/jpeg",
    "size": 204585
  },
  "description": "Experience the power of decentralized storage, encryption, and token gating with this tutorial",
  "publishedAt": "2023-11-04T04:00:00.000Z",
  "textContent": "The most popular method used for sharing files off-chain in Web3 is IPFS, and there are some good reasons for that. However it does not come without its own share of problems, and one of those is the ability to share private files. IPFS is a public network so anyone with a CID can access and download that content, and this hinders projects that may want to token gate content or create subscriptions to content. With that said, encryption has proven to be one solution to this problem. Remarkably, the solution of asymmetric encryption is used in blockchain all the time and can be reused for the purpose of token gating. Lit Protocol is a decentralized middleware client that enables access controls to help extend asymmetric encryption to token gating based on crypto ownership, such as owning an NFT, ERC-20 token balance, or simply designating a recipient address. In this post, we’ll show you how you can combine the best of both worlds and create an app that will encrypt content, upload it to IPFS, and then given an encrypted CID, decrypt it.\n\nWhy IPFS?\n\nIPFS is public and openly available, but it’s also not permanent by default. This means that unlike blockchain storage protocols that make every piece of content permanent as soon as it’s uploaded, you can potentially remove content from IPFS. You’ll see why this is important as we explore encryption more deeply.\n\nThe biggest problem with encryption is that its always evolving. One encryption method we use today will be outdated one day in the future. An example is MD5 which was cracked almost perhaps 10 years ago but people still use it without knowing the risk. When we consider putting files on a decentralized network that are specifically designed to not be taken down, things get messy. Arweave is a common consideration for encryption and decentralized storage, however, their model puts content on the network permanently. There is the possibility those encrypted files could be cracked in another 10 years.\n\nIPFS is different in that content is not “permanent,” but rather it is “persistent.” It's a subtle difference but has massive ramifications. With IPFS, the content will only stay on the network if at least one IPFS node keeps the content “pinned,” which tells other nodes that might have a cached copy of the content to keep it available. As soon as there are no nodes pinning a particular CID, then the nodes holding that cache will dump it when they use garbage collection. It's a unique mechanism that helps prevent digital waste and ensures only the content we value will persist. The concepts of permanence and persistence are truly philosophical differences of approaching the same problem.\n\nWhen you combine IPFS with encryption, you get a unique situation where content that is no longer used can be unpinned. Granted it does not guarantee the content will be completely wiped from the network, but it does give users a level of control over their content they would normally not have with other decentralized storage networks. It is also unlikely that bad actors would go through the trouble and costs to keep encrypted content pinned for the purpose of decrypting it years down the road. The cost of storage helps balance situations like these. With that said let's actually build this thing!\n\n<aside>\nℹ️ <b>Disclosure:</b> There will always be limitations to encryption and eventually current methods may be cracked. Please be aware of the risk involved and be sure to read <a href=\"https://developer.litprotocol.com/v3/sdk/authentication/security\">Lit Protocol’s best practices for security.</a>\n</aside>\n\nBuilding the App\n\nWhat’s great about this project is that we already have most of what we need to build it! Pinata created a Next.js template a while back which we can use again and just add in our Lit Protocol SDK.\n\nTo follow this tutorial you will want to make sure you have the following:\n\n- Node.js 18 or higher\n- A Free Pinata Account\n- A text editor like VSCode\n\nBefore going any further make sure you get a free Pinata account so you can make an API key and get a free Dedicated Gateway for this project! Once you make an API key, save the JWT that we’ll use in a little bit, as well as the gateway domain for your Dedicated Gateways.\n\nThats it! To kick it off, simply run the command to use the Pinata Next.js Template\n\nYou will be prompted to choose your flavors of the app, such as Typescript vs Javascript, or Tailwindcss vs Vanilla CSS. For this template, I chose Typescript and Tailwindcss but feel free to choose your own. After giving it a name and making your selections go ahead and open the project in VSCode.\n\nBack in the terminal the next thing we’re going to do is install the Lit Protocol SDK. We’ll be using the V3 of the SDK which is in beta, and you can install based on their docs here or use this command:\n\nThe last thing you need to do to set up the project is open the .env.sample file which should look like this:\n\nPaste in the PINATA_JWT that you made earlier when you set up your Pinata account and also paste in the NEXT_PUBLIC_GATEWAY_URL with the format https://mygateway.mypinata.cloud with of course your own domain URL. Then change the name of the file from .env.sample to .env.local, a very important step for our app to work!\n\nNow lets go ahead and spin up the dev server with npm run dev and start building. All of our work will be done in just one file, pages/index.tsx; easy! We’ll start by importing the Lit Protocol SDK at the top of the file.\n\nInside the Home component, we’ll add another state variable that we’ll come back to later.\n\nThe great thing about this template is that it's already got uploads to IPFS with Pinata baked in with an /api/files route on the backend, so all we have to do is encrypt the file before we upload it. We’ll do this in the uploadFile function inside of Home, and it should look like this to start.\n\nAt the top of our try statement but underneath our setUploading state, we’ll initialize the LitNodeClient using the ceyenne network, connect our app to that network, then get the authSig. Lit Protocol is a decentralized network middleware that helps us do some cool token gating and lets us do encryption. In these few statements, we create a client that connects to that middleware network and then gets a signature from the user. This signature will be used for signing the encrypted files.\n\nNext up we’ll set up our access controls for this encrypted content. We’ll dive deeper into this later in the tutorial, but essentially this is the most important part of our app as it determines who can decrypt the content we encrypt. It could be something like token gating by NFT collection or a direct address. For now, we’ll keep it simple and allow anyone with a balance of 0 ETH or higher to decrypt it (that should be everyone with a wallet).\n\nThe fun part; encrypting! There are several methods of encryption that Lit Protocol offers through their SDK, such as just a string, or a file, and in our case, we’ll use the encryptFileAndZipWithMetadata method. This is handy because in order to decrypt a file, our recipient will need the accs parameters we set and a secure hash. We want a simple way for all of this to be packaged and included in our IPFS CID, and that's exactly what this method will do. All we have to do is pass in our access control conditions array, our authSig, the chain, our fileToUpload that we passed into the function argument, the litNodeClient, and finally a simple readme that will explain to whoever happens to download it from IPFS what they need to do with it.\n\nOne last little touch we need to do is adapt this encrypted zip file so it will be accepted by our /api/files endpoint, and we’ll do so with just two lines of code.\n\nAll together we should have an upload function that looks like this:\n\nOne thing to note is that there is a file size restriction when using the Next API routes, so if you have larger files you may want to move uploading to the client side and utilize pre-signed JWTs which we talk about in this post.\n\nWe now have encrypted uploads! If you upload a file through the app you should get a CID, and if you download the file it will result in a zip folder with all the stuff we just made. This is cool, but how do we decrypt it? How do we let other people decrypt it? Its actually pretty easy! We’re gonna make a new function right below our upload function called decryptFile(), which will take a fileToDecrypt CID. First thing we’ll do is fetch that file using our Dedicated Gateway and turn it into a blob.\n\nNow we can re-create the litNodeClient and get the auth signature. The beauty of this SDK is that once some signs they will not need to sign again unless they disconnect from the app, making the interactions fairly smooth.\n\nJust like we used encryptFileAndZipWithMetadata method, we have a matching method for decryption called decryptZipFileWithMetadata which we’ll use very similarly to the encryption. The zip folder has everything we need so all we have to pass in is the file blob, our litNodeClient, and the recipient authSig. Piece of cake! From this, we’ll extract the decryptedFile and metadata from our request.\n\nAll that’s left to do is deliver the file to the user! There are several ways you could go about it, for example, if you want to display the content to the user such as an image or video you could do so with a bit of formatting. In this example, we’ll just trigger a download to the recipient’s computer. All together we should have the following.\n\nOne small little change we’ll make to the JSX is a text input where someone can paste in a CID and a “Decrypt” button someone can press after pasting in their CID.\n\nWith all of this together, you should have an app with the following flow!\n\n<video muted autoplay style=\"width: 100%; height: auto; position: relative;\">\n    <source src=\"https://mktg.mypinata.cloud/ipfs/QmcoP5gj1gJyZNCDUHE2e1g1cbwvEHo6E56xMhPV8KaHaf/file-encryption.mp4\" type=\"video/mp4\">\n</video>\n\nYou can ",
  "canonicalUrl": "https://stevedylan.dev/posts/how-to-encrypt-and-decrypt-files-on-ipfs-using-lit"
}