изоморфный код для нативного node.js и криптографии браузера

Существует isomorphic-webcrypto, который делает вид, что делает это, но не делает этого: он создает отдельную сборку для каждой цели.

Для этого есть способ noble-crypto , но он основан на условиях if-else и не работает, если мне нужен изоморфный код mjs.

Наконец, существует метод eval require way для сквозного сборщика, но node не может использовать его в mjs.

Вкратце :

      const crypto = require("crypto"); // work only in node.js but not in mjs file.
const crypto = eval(`require("crypto")`); // pass-thru bundler, then work only in node.js but not in mjs file.
window.crypto; // work only in browser
import * as crypto from "crypto"; // could work from both but must be at top level of a module, so it can't be a conditional import.

Я хотел бы использовать собственное шифрование в node.js и в браузере изоморфным способом, чтобы иметь возможность прозрачно использовать собственный импорт mjs в node и браузере.

Как я могу это сделать?

1 ответ

Хорошо. Готовы к чему-то уродливому? :-) Вот мой последний хакджоб… IsomorphicCyrpto.js:

      export default
  globalThis.crypto ||
  (await import('node:crypto')).default.webcrypto
;

Это работает в Node.js v16 в модульном режиме ("type": "module"в package.json или эквивалентных аргументах CLI) и, вероятно, будет работать и с вашим упаковщиком… но кто знает. ;-) Любой, кто использует этот фрагмент кода, должен тщательно протестировать его на любых платформах, на которых он хочет его использовать.

В двух словах:

  • Мы используемglobalThis, который представляет globalпод Node.js, windowдля большинства контекстов браузера и, возможно, даже может быть рабочим контекстом.
  • Сначала мы проверяем, есть ли вещь. Если это так, мы, вероятно, в браузере и можем просто использовать его напрямую.
  • Если cryptoэто не проблема, мы, вероятно, на Node.js, и нам нужно импортировать модуль.
  • Поскольку это делается динамически, нам нужна динамическая , а не истинная import.
  • import()является асинхронным и возвращает обещание. Но эй, это все хорошо, потому что на высшем уровне awaitэто вещь в Node.js сейчас!

Чтобы затем использовать модуль:

      import crypto from './lib/IsomorphicCrypto.js';
console.log( crypto.randomUUID() );

Ужасно, но пока работает. Будем надеяться, что кто-то предложит лучшее решение, или контексты Node.js и браузера сойдутся в именовании в будущем.

Другие вопросы по тегам