llrt icon indicating copy to clipboard operation
llrt copied to clipboard

SyntaxError: Could not find export 'diffieHellman' in module 'crypto'

Open buddamus opened this issue 9 months ago • 4 comments

It appears that all of crypto is not in the build? When I try to run verify() below I get an error. This use case is for verifying a JWT with a public key using the jose library. We have a lambda authorizer that reads the JWT from a cookie and verifies it using a public key.

import * as jose from 'jose';

async function verify({ jwt, publicKeyBase64 }: { jwt: string; publicKeyBase64: string; }) {
    const publicKey: jose.KeyLike = await createPublicKeyFromBase64String(publicKeyBase64);
    //we're passing in the issuer so we can quickly ignore any jwts that don't have expected values
    const verifyResult = await jose.jwtVerify(jwt, publicKey, {
      issuer: JWT_ISSUER,
      //prevent algorith confusion attacks: https://portswigger.net/web-security/jwt/algorithm-confusion
      algorithms: [JWT_ALGORITHM],
      //prevent the scenario where a valid token was made with a very distant expiration
      maxTokenAge: 60 * 30,
      //add a small clock tolerance.. this can help with tests and enforcing maxTokenAge which requires 'iat' to be in the past.
      //if 'iat' is the same at Date.now(), the test will fail
      clockTolerance: 5,
    });    

    return verifyResult.payload as Record<string, string>;
  }

function chunkSubstr(str: string, size: number) {
    const numChunks = Math.ceil(str.length / size);
    const chunks: string[] = new Array<string>(numChunks);

    for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
      chunks[i] = str.substring(o, o + size);
    }

    return chunks;
  }

async function createPublicKeyFromBase64String(publicKeyBase64: string) {
    const publicKeyIn64CharLines = chunkSubstr(publicKeyBase64, 64).join('\n');
    const str = `-----BEGIN PUBLIC KEY-----\n${publicKeyIn64CharLines}\n-----END PUBLIC KEY-----`;
    return await jose.importSPKI(str, JWT_ALGORITHM);
  } 

buddamus avatar Mar 31 '25 20:03 buddamus

Hi @buddamus thanks for your report. We don't support the full Node Crypto APIs but WebCrypto/crypto.subtile.

I'm not familiar with Jose but is there an option to use web crypto? or manually verify JWT using web crypto algorithms?

richarddavison avatar Apr 01 '25 06:04 richarddavison

According to the docs:

Assumes runtime support of WebCryptoAPI and Fetch API

So I don't think we can pass in our own polyfill etc. I was looking for a quick lift and ship without refactoring and I unfortunately don't have time/permission for a rewrite.

Perhaps the README should be updated to clarify this:

crypto | ✔︎ | ✔︎*

buddamus avatar Apr 01 '25 13:04 buddamus

I couldn't get jose or jsonwebtoken working either. I've gone with using jsrsasign (a pure JS crypto library):

import { KJUR } from "jsrsasign";

const verify = async ({ jwt, publicKeyBase64 }: { jwt: string; publicKeyBase64: string; }) => 
  KJUR.jws.JWS.verifyJWT(jwt, publicKeyBase64, { alg: [JWT_ALGORITHM] });

This has been working for me since a fix in v0.4.0-beta.

ainsleyrutterford avatar Apr 11 '25 16:04 ainsleyrutterford

I would also test something like this since it relies on webcrypto APIs: https://github.com/pose/webcrypto-jwt

richarddavison avatar Apr 13 '25 19:04 richarddavison