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
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 thecryptovariable to the Web Crypto APIcrypto.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:
import * as crypto from 'crypto;at the top of the filecryptovariable will default to usewindow.crypto, aka the Web Crypto APIcrypto.subtle.digest()will work as intended.window.crypto.subtle.digest()instead of the predefinedcryptovariable.