edge-runtime icon indicating copy to clipboard operation
edge-runtime copied to clipboard

crypto.subtle.importKey does not accept ArrayBuffer (ArrayBuffer.prototype mismatch)

Open tksst opened this issue 1 year ago • 8 comments

Node.js 20.11.1 [email protected]

Bug Report

Current behavior

foo.js:

(async () => {
	const key = new ArrayBuffer(8);
	const data = new ArrayBuffer(8);

	const importedKey = await crypto.subtle.importKey(
		"raw",
		key,
		{
			name: "HMAC",
			hash: { name: "SHA-256" },
		},
		false,
		["sign"],
	);

	await crypto.subtle.sign("HMAC", importedKey, data);
})();

cmd:

$ npm exec edge-runtime foo.js

result(error):

node:internal/crypto/webidl:45
  const err = new TypeError(message);
              ^

TypeError: Failed to execute 'importKey' on 'SubtleCrypto': 2nd argument is not instance of ArrayBuffer, Buffer, TypedArray, or DataView.
    at codedTypeError (node:internal/crypto/webidl:45:15)
    at makeException (node:internal/crypto/webidl:54:10)
    at converters.BufferSource (node:internal/crypto/webidl:221:11)
    at SubtleCrypto.importKey (node:internal/crypto/webcrypto:589:36)
    at evalmachine.<anonymous>:6:45
    at evalmachine.<anonymous>:19:3
    at Script.runInContext (node:vm:133:12)
    at runInContext (node:vm:287:6)
    at EdgeVM.evaluate (/dev/edge/node_modules/@edge-runtime/vm/dist/vm.js:26:38)
    at new EdgeVM (/dev/edge/node_modules/@edge-runtime/vm/dist/edge-vm.js:49:18) {
  code: 'ERR_INVALID_ARG_TYPE'
}

Node.js v20.11.1

Expected behavior/code

Done without error

Additional context/screenshots

The above code has been verified to work with raw Node.js, Firefox and Chrome.

ArrayBuffer.prototype seems to be different from the original. Node.js checks here: https://github.com/nodejs/node/blob/9b1bf44ea9e7785e38c93b7d22d32dbca262df6c/lib/internal/crypto/webidl.js#L183

return ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V);

Wrapping with uint8array is a workaround:

(async () => {
	const key = new ArrayBuffer(8);
	const data = new ArrayBuffer(8);

	const importedKey = await crypto.subtle.importKey(
		"raw",
		new Uint8Array(key),
		{
			name: "HMAC",
			hash: { name: "SHA-256" },
		},
		false,
		["sign"],
	);

	await crypto.subtle.sign("HMAC", importedKey, new Uint8Array(data));
})();

tksst avatar Feb 23 '24 16:02 tksst