nodejs / node

Node.js JavaScript runtime ✨🐢🚀✨
https://nodejs.org
Other
107.28k stars 29.45k forks source link

importKey method on crypto.webcrypto SubtleCrypto is not recognising array buffer. #55380

Closed lreher closed 5 days ago

lreher commented 5 days ago

Version

v20.17.0

Platform

MacOSDarwin22.6.0 Darwin Kernel Version 22.6.0: Wed Jul  5 22:22:05 PDT 2023; root:xnu-8796.141.3~6/RELEASE_ARM64_T6000 arm64

Subsystem

No response

What steps will reproduce the bug?

Execute the following:

let arrayBuffer = new ArrayBuffer(...) /// some array buffer

const publicKey = await crypto.webcrypto.subtle.importKey(
    'spki',
    arrayBuffer,
    {
      name: 'RSA-OAEP',
      hash: { name: 'SHA-256' },
    },
    false,
    ['encrypt']
  );

The function will error out stating that the second argument is not an ArrayBuffer.

How often does it reproduce? Is there a required condition?

Consistently.

What is the expected behavior? Why is that the expected behavior?

To correctly import the key. This works fine in node 17, it happens when upgrading to node 20.

What do you see instead?

TypeError: Failed to execute 'importKey' on 'SubtleCrypto': 2nd argument is not instance of ArrayBuffer, Buffer, TypedArray, or DataView.

Additional information

No response

RedYetiDev commented 5 days ago

Node.js doesn't provide a value "window", is this executing from the browser?

lreher commented 5 days ago

Apologies I took the code from some unit tests where we are creating a window.crypto object assigned to the crypto webview. I've updated the comment with the correct code.

This is running in nodejs.

panva commented 5 days ago
const kp = await crypto.subtle.generateKey({ name: 'Ed25519' }, true, ['sign', 'verify']);
const buffer = await crypto.subtle.exportKey('spki', kp.publicKey);

console.log(buffer)

await crypto.subtle.importKey('spki', buffer, 'Ed25519', true, ['verify'])
ArrayBuffer {
  [Uint8Contents]: <30 2a 30 05 06 03 2b 65 70 03 21 00 cd 34 cf 79 c6 82 6e 9b 2f 5c 6e c8 bb cd d2 02 21 92 51 aa a8 24 93 74 27 d9 37 e0 b4 53 2e 2e>,
  byteLength: 44
}

CryptoKey {
  type: 'public',
  extractable: true,
  algorithm: { name: 'Ed25519' },
  usages: [ 'verify' ]
}

This works just fine. Are you running your code in a test environment with modules like jsdom or similar? Those environments replace actual Node.js globals which is why "your" ArrayBuffer is not the same as Node's own ArrayBuffer global.

panva commented 5 days ago

You can see this in raw Node.js with just

node -e "crypto.subtle.importKey('spki', new ArrayBuffer(), 'Ed25519', true, ['verify']).catch(console.log)"

This complains about invalid keyData, meaning that the WebIDL validation of arguments has passed and new ArrayBuffer() is indeed accepted.

lreher commented 5 days ago

You are right, this was actually a JDOM issue. I'm closing the ticket, thank you for the support!