{"id":11238,"library":"libsodium-wrappers","title":"libsodium-wrappers","description":"libsodium-wrappers provides a JavaScript/TypeScript binding for the highly regarded Sodium cryptographic library, compiled to WebAssembly with a pure JavaScript fallback. It is currently stable at version 0.8.3, wrapping libsodium 1.0.22. The package offers comprehensive, high-performance cryptographic operations for both web browsers (Chrome, Firefox, Edge, Safari, Mobile Safari) and server-side environments like Node.js and Bun. It comes in two variants: a standard version with commonly used functions and a 'sumo' version that includes the full, exhaustive libsodium API. Since version 0.8.1, the library automatically includes TypeScript definitions, simplifying development in typed environments. Users must `await sodium.ready` to ensure the underlying cryptographic engine is fully initialized before using any functions or constants. The library maintains a regular release cadence to incorporate upstream libsodium updates and address issues.","status":"active","version":"0.8.3","language":"javascript","source_language":"en","source_url":"https://github.com/jedisct1/libsodium.js","tags":["javascript","crypto","sodium","libsodium","nacl","chacha20","poly1305","curve25519","ed25519","typescript"],"install":[{"cmd":"npm install libsodium-wrappers","lang":"bash","label":"npm"},{"cmd":"yarn add libsodium-wrappers","lang":"bash","label":"yarn"},{"cmd":"pnpm add libsodium-wrappers","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The primary `sodium` object is a default export and must be awaited via `sodium.ready` before use. Cryptographic functions and constants are dynamically added to this object after `ready` resolves, so they cannot be destructured directly at the import statement.","wrong":"import { sodium } from 'libsodium-wrappers';","symbol":"sodium","correct":"import sodium from 'libsodium-wrappers';"},{"note":"Helper functions like `from_string`, `to_string`, `from_hex`, and the `ready` promise itself can be imported as named exports from ESM modules. However, cryptographic functions (e.g., `crypto_secretbox_keygen`) are *not* named exports and must be accessed via the default `sodium` object after `await sodium.ready`.","wrong":"import { ready } from 'libsodium-wrappers';\nconsole.log(sodium.crypto_secretbox_keygen());","symbol":"ready","correct":"import { ready, from_string, to_string } from 'libsodium-wrappers';"},{"note":"For CommonJS environments, `require` provides the `sodium` object. Similar to ESM, `sodium.ready` is a promise that *must* be awaited before any cryptographic operations are called. Attempting to use functions before `ready` resolves will result in `TypeError`s.","wrong":"const sodium = require('libsodium-wrappers');\nconst key = sodium.crypto_secretbox_keygen();","symbol":"sodium","correct":"const sodium = require('libsodium-wrappers');\n(async () => { await sodium.ready; /* use sodium */ })();"}],"quickstart":{"code":"import sodium from 'libsodium-wrappers';\n\nasync function encryptDecryptStream() {\n  await sodium.ready;\n\n  // Generate a key for secret stream encryption\n  const key = sodium.crypto_secretstream_xchacha20poly1305_keygen();\n\n  // Initialize a push state and get the header\n  const { state: state_out, header } =\n    sodium.crypto_secretstream_xchacha20poly1305_init_push(key);\n\n  // Push messages with different tags\n  const message1 = sodium.from_string('This is the first secret message.');\n  const c1 = sodium.crypto_secretstream_xchacha20poly1305_push(\n    state_out, message1, null,\n    sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE\n  );\n\n  const message2 = sodium.from_string('And this is the final message.');\n  const c2 = sodium.crypto_secretstream_xchacha20poly1305_push(\n    state_out, message2, null,\n    sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL\n  );\n\n  console.log('Encrypted message 1 (hex):', sodium.to_hex(c1));\n  console.log('Encrypted message 2 (hex):', sodium.to_hex(c2));\n\n  // Initialize a pull state with the header and key\n  const state_in = sodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key);\n\n  // Pull and decrypt the first message\n  const r1 = sodium.crypto_secretstream_xchacha20poly1305_pull(state_in, c1);\n  const { message: m1_bytes, tag: tag1 } = r1;\n  const m1 = sodium.to_string(m1_bytes);\n  console.log('Decrypted message 1:', m1, '(Tag:', tag1, ')');\n\n  // Pull and decrypt the second (final) message\n  const r2 = sodium.crypto_secretstream_xchacha20poly1305_pull(state_in, c2);\n  const { message: m2_bytes, tag: tag2 } = r2;\n  const m2 = sodium.to_string(m2_bytes);\n  console.log('Decrypted message 2:', m2, '(Tag:', tag2, ')');\n\n  // Ensure the tags are correct\n  if (tag1 === sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE &&\n      tag2 === sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) {\n    console.log('Stream messages successfully encrypted and decrypted with correct tags.');\n  } else {\n    console.error('Tag mismatch!');\n  }\n}\n\nencryptDecryptStream();","lang":"typescript","description":"This example demonstrates end-to-end secret stream encryption and decryption using libsodium-wrappers, showcasing key generation, message pushing with tags, and message pulling."},"warnings":[{"fix":"Always `await sodium.ready;` before using any cryptographic functions or constants from the default `sodium` export.","message":"All cryptographic functions and constants are only available after the `sodium.ready` promise has resolved. Attempting to call them before initialization will result in a `TypeError`.","severity":"breaking","affected_versions":">=0.7.0"},{"fix":"Always use `import sodium from 'libsodium-wrappers'; await sodium.ready;` and then access functions as `sodium.crypto_...`. Only helper utilities like `from_string`, `to_hex`, and `ready` itself can be named imports.","message":"Cryptographic functions (e.g., `crypto_secretbox_easy`) and constants (e.g., `crypto_secretbox_KEYBYTES`) are not available as named exports in ESM modules. They must be accessed via the default `sodium` object after it has initialized.","severity":"gotcha","affected_versions":">=0.7.16"},{"fix":"Ensure target environments meet the minimum compatibility requirements (Mobile Safari >= 8.0, Safari >= 6, Chrome >= 16, Firefox >= 21, Edge >= 0.11, NodeJS, Bun, Opera >= 15).","message":"Older versions of Mobile Safari on iOS (< 8.0) and Safari (< 6) are noted to produce incorrect cryptographic results. Developers targeting these environments should exercise extreme caution or use alternative libraries.","severity":"gotcha","affected_versions":"<0.8.0"},{"fix":"For most projects, `libsodium-wrappers` is recommended. Only use `libsodium-wrappers-sumo` if you explicitly require functions not present in the standard version, and understand the implications of using advanced/low-level primitives.","message":"The `libsodium-wrappers` package (standard) includes commonly used high-level functions, while `libsodium-wrappers-sumo` provides the full, often low-level and undocumented, libsodium API, including functions like `crypto_pwhash_*`. Using the `sumo` version increases bundle size and exposes potentially misuse-prone functions.","severity":"gotcha","affected_versions":">=0.7.0"},{"fix":"Upgrade to `libsodium-wrappers` version 0.7.16 or newer for full ESM compatibility. Ensure your build system is configured to handle `.mjs` extensions if direct file paths are being used.","message":"ESM (ECMAScript Module) support was added in version 0.7.16. Older versions may not correctly resolve `import` statements or use `.mjs` extensions, leading to module resolution errors in modern JavaScript environments.","severity":"breaking","affected_versions":"<0.7.16"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure `await sodium.ready;` is executed before any calls to `sodium`'s cryptographic methods.","cause":"Attempting to use a cryptographic function before the `sodium.ready` promise has resolved.","error":"TypeError: sodium.crypto_secretstream_xchacha20poly1305_keygen is not a function"},{"fix":"Verify the package is installed (`npm install libsodium-wrappers`). Check import paths, especially when mixing CommonJS and ESM. For bundler issues, review configuration (e.g., Next.js with Turbopack might need specific handling for WASM modules).","cause":"Incorrect import path, package not installed, or module resolution issues in the build system (e.g., webpack, Turbopack, or Jest).","error":"ERR_MODULE_NOT_FOUND: Cannot find package 'libsodium-wrappers'"},{"fix":"When testing, ensure Jest (or similar) is correctly configured for ESM and/or browser-like environments. You might need to mock the library or configure Jest's `moduleNameMapper` or `transformIgnorePatterns` to handle it correctly. Some users have found solutions by ensuring proper WebAssembly loading in their test runner.","cause":"This error can occur in testing environments (like Jest) where the global `window` object or module loading context is not fully emulated as expected by libsodium-wrappers' internal initialization logic.","error":"TypeError: Cannot read properties of undefined (reading 'sodium')"}],"ecosystem":"npm"}