oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
74.22k stars 2.77k forks source link

`@types/bun@1.0.1` breaks `CryptoKey` #8159

Closed simylein closed 10 months ago

simylein commented 10 months ago

What version of Bun is running?

1.0.22+b400b36ca

What platform is your computer?

Darwin 23.2.0 arm64 arm

What steps can reproduce the bug?

import { createHash, getRandomValues, subtle } from 'crypto';

const enc = new TextEncoder();
const dec = new TextDecoder();

const encrypt = async (data: Uint8Array, key: CryptoKey): Promise<Uint8Array> => {
    const iv = getRandomValues(new Uint8Array(16));
    const buffer = await subtle.encrypt({ name: 'aes-cbc', iv }, key, data);
    return new Uint8Array([...iv, ...new Uint8Array(buffer)]);
};

const decrypt = async (data: Uint8Array, key: CryptoKey): Promise<Uint8Array> => {
    const iv = data.slice(0, 16);
    const buffer = await subtle.decrypt({ name: 'aes-cbc', iv }, key, data.slice(16));
    return new Uint8Array(buffer);
};

const data = enc.encode('the plaintext is encrypted into ciphertext using a secret key');
console.log('data:', dec.decode(data));

const key = await subtle.generateKey({ name: 'aes-cbc', length: 256 }, false, ['encrypt', 'decrypt']);

const encrypted = await encrypt(data, key);
console.log('encrypted:', createHash('sha256').update(encrypted).digest('hex'));

const decrypted = await decrypt(encrypted, key);
console.log('decrypted:', dec.decode(decrypted));

What is the expected behavior?

with @types/bun@1.0.0 type checking succeeds without failures

What do you see instead?

with @types/bun@1.0.1 type checking fails with

Argument of type 'import("crypto").webcrypto.CryptoKey' is not assignable to parameter of type 'CryptoKey'. Property 'prototype' is missing in type 'import("crypto").webcrypto.CryptoKey' but required in type 'CryptoKey'.ts(2345) lib.dom.d.ts(5887, 5): 'prototype' is declared here.

Argument of type 'import("crypto").webcrypto.CryptoKey' is not assignable to parameter of type 'CryptoKey'.ts(2345)

Additional information

The runtime works fine, it's just the type definition, can someone add the typescript label?

TiBianMod commented 10 months ago

headers also https://github.com/oven-sh/bun/issues/8081

😢

guest271314 commented 10 months ago

Node.js crypto is essentially not capable of being polyfilled - because Node.js uses an internal implementation. Use webcrypto property of node:crypto for subtle. [AskJS] Why is the internal crypto module so difficult to bundle as a standalone portable script?

The crypto module is not entirely Javascript. Some of its implementation uses native code which only runs in the nodejs environment and some of its implementation uses nodejs internals (like the thread pool).

guest271314 commented 10 months ago

This

import { createHash, getRandomValues, subtle } from 'crypto';

should be something like

import * as crypto from "node:crypto";
const { webcrypto } = crypto;
const { subtle } = webcrypto;
guest271314 commented 10 months ago

FYI node's KeyObject https://nodejs.org/api/crypto.html#class-keyobject is not the same as Web Cryptography API's CryptoKey, https://w3c.github.io/webcrypto/#cryptokey-interface. E.g., cf. https://github.com/WICG/webpackage/tree/main/js to https://github.com/guest271314/wbn-sign-webcrypto.

simylein commented 10 months ago

Oh right, thank you for the explanation. Then I guess it's a skill issue 😉. I think I can close this for now?

guest271314 commented 10 months ago

I would substitute Web Cryptography API for Node.js crypto. Might be a tedious effort, though possible, and once completed you should be able to run the same code in Bun, Deno, and Node.js.