reactjsnode.jsnext.jscryptographywebcrypto-api

crypto.subtle is undefined even though I'm using http://localhost:3000


I'm trying to use crypto.subtle.digest() as part of a checksum function for a file upload project I'm working on but for some reason I keep getting the following error:

upload-form.tsx:129 Uncaught TypeError: Cannot read properties of undefined (reading 'digest')

Which suggests that crypto.subtle is undefined. I understand that crypto.subtle is only available in a secure contexts (HTTPS), but I am trying to use it within http://localhost:3000 which I read was also considered a secure context. I have tried it in both Chrome & Firefox, and get the same undefined error in both.

For Context:

I am using NextJS 14.1.0 and Node.js v20.11.0

I tested this on http://localhost:3000 on Chrome v121.0.6167.160 and Firefox ESR v115.3.0esr

I am using import * as crypto from "crypto" within a Client Component (I have "use client"; at the top)

This is the checksum function I'm using which I got from this Youtube tutorial but only briefly shows it.

The comments are from ChatGPT who also came up with basically the same function.

//upload-form.tsx
"use client";

... //imports

import * as crypto from "crypto";

... //some code

const computeSHA256 = async (file: File) => {
  // Convert file to an array buffer
  const buffer = await file.arrayBuffer();
  
  // Calculate SHA-256 hash
  const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);

  // Convert hashBuffer to hexadecimal representation
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  const hashHex = hashArray
    .map((byte) => byte.toString(16).padStart(2, "0"))
    .join("");

  return hashHex;
};

... //rest of file

Using crypto.webcrypto.subtle.digest(), I get the error:

upload-form.tsx:133 Uncaught TypeError: Cannot read properties of undefined (reading 'subtle')

Which suggests that crypto.webcrypto is undefined.

If I use window.crypto.subtle.digest() instead, then the function runs perfectly fine, but I am wondering if that is the right way to go about it.

I used console.log(crypto) to see what properties it had, and neither webcrypto or subtle was there.

Directly printing window.crypto within Chrome's console shows that it does have subtle


Solution

  • Okay, so after looking into the github repo provided by the owner of the Youtube tutorial, I noticed that he never actually used import crypto from 'crypto' at the top of his file. I wondered how he was able to use crypto without importing it, but I guess it turns out that without the import, javascript/react/nextjs (??) will default the crypto variable to the Web Crypto API crypto.

    I had no clue that this was a thing.

    If my understanding is correct, then, this is the same as just using window.crypto, which was what I was using to get the function to work initially.

    To sum up: