panva / jose

JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes
MIT License
5.62k stars 315 forks source link

HMAC key data must not be empty #698

Closed CyberMew closed 3 months ago

CyberMew commented 3 months ago

What happened?

I am trying to use compactVerify (just to verify signature is matching my HS256 key, nothing else), but when sending in an empty string, as the secret parameter (after encoding it in TextEncoder), the compactVerify throws a non-JOSEError saying something like {stack: “Error: HMAC key data must not be empty” }. I was expecting a JOSEError to be thrown, as it happened within the jose function, so I can handle the specific error elegantly. Not sure if this is intended. Thank you.

Version

5.6.3

Runtime

Browser

Runtime Details

na

Code to reproduce

Just send in “” when encoding the secret key and use that for compactVerify.

Required

codespearhead commented 3 months ago

We need a minimal reproducible example, because passing an empty string to the key parameter in function compactVerify gives me the exact same error as passing the wrong key to it.

# docker build -t demo . && docker run --rm demo
FROM node:20.15.1-alpine3.20 AS base
WORKDIR /app

FROM base AS install-deps
RUN npm init -y && npm install jose@5.6.3

FROM install-deps AS add-demo
RUN cat <<'EOF' > verify.js
const { compactVerify } = require('jose');
const { TextEncoder } = require('util');

async function verifySignature() {
  const jws = 'eyJhbGciOiJIUzI1NiJ9.ew0KICAic3ViIjogIjEyMzQ1Njc4OTAiLA0KICAibmFtZSI6ICJBbmlzaCBOYXRoIiwNCiAgImlhdCI6IDE1MTYyMzkwMjINCn0.vVWIZr0v6c0Wv8dXURk7sp0CTVSN5xMt_Ip3vq1QzX0';
  //const secret = '24b893d1-10b7-476f-a512-1213419b65df';
  //const secret = 'wrong-key'
  const secret = '';
  encodedSecret = new TextEncoder().encode(secret)

  try {
    const { payload, protectedHeader } = await compactVerify(jws, encodedSecret);
    console.log("Verification succeeded:", payload, protectedHeader);
  } catch (error) {
    console.error('Error:', error);
  }
}

verifySignature()
EOF

CMD ["node", "verify.js"]
Error: JWSSignatureVerificationFailed: signature verification failed
    at flattenedVerify (/app/node_modules/jose/dist/node/cjs/jws/flattened/verify.js:89:15)
    at async compactVerify (/app/node_modules/jose/dist/node/cjs/jws/compact/verify.js:18:22)
    at async verifySignature (/app/verify.js:11:42) {
  code: 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED'
}
panva commented 3 months ago

Not sure if this is intended.

It is intended, the error comes from the underlying crypto runtime, in your case a WebCryptoAPI (that you can confirm by checking the value of jose.cryptoRuntime), when it does not support zero-length secrets.

👇 see below for expected behaviour when zero-length secrets are supported.

because passing an empty string to the key parameter in function compactVerify gives me the exact same error as passing the wrong key to it

That's expected behaviour when the underlying crypto runtime supports zero-length secrets.