Sodium JavaScript Cryptography Library
sodium-javascript is a pure JavaScript implementation of the libsodium cryptographic library's API, leveraging `tweetnacl` as its foundation. It was developed to provide a browser-compatible alternative to `sodium-native`, which is a Node.js native addon binding to the C libsodium library. The package's current stable version is 0.8.0, but it explicitly states 'WIP - Work In Progress' in its README and was last published over four years ago (January 2022). This suggests the project is largely unmaintained or abandoned. Its key differentiator was offering a pure JavaScript fallback for environments where native bindings are not feasible (e.g., browsers). For modern cross-platform libsodium usage, alternatives like `libsodium-wrappers` (which utilizes WebAssembly for better performance and broader API coverage) are generally recommended.
Common errors
-
TypeError: sodium.crypto_some_unimplemented_function is not a function
cause The specific libsodium function you are trying to use is not implemented in `sodium-javascript`, or the installed version is too old to include it.fixVerify the function exists in the `sodium-javascript` API by checking its source or `sodium-native` documentation (which it aims to mimic). If not implemented, you must use an alternative library or find another way to achieve the cryptographic goal. -
ReferenceError: Buffer is not defined
cause `Buffer` is a Node.js global. This error occurs when `sodium-javascript` is used directly in a browser environment without a `Buffer` polyfill or appropriate bundling.fixEnsure your browser environment has a `Buffer` polyfill (e.g., `buffer` npm package) if using a bundler like Webpack, or prefer `libsodium-wrappers` for browser-native execution. -
Error: bad secretbox message
cause This error typically indicates that the ciphertext, nonce, or key used for decryption is incorrect, corrupted, or does not match the parameters used during encryption. It's a common cryptographic integrity check failure.fixDouble-check that the `cipher`, `nonce`, and `key` buffers are exactly the same as those used for encryption. Ensure no data corruption occurred during storage or transmission. Also verify buffer lengths and types. -
Error: Module not found: Error: Can't resolve 'sodium-javascript' (or similar bundler/ESM import errors)
cause `sodium-javascript` is a CommonJS module. Direct `import ... from 'sodium-javascript'` syntax in an ES Module context might not be resolved correctly by some bundlers or Node.js versions without explicit configuration or a `package.json` `exports` map.fixIn Node.js ESM files, use `const sodium = require('sodium-javascript')` or dynamic import `const sodium = await import('sodium-javascript')`. In bundlers, ensure your configuration correctly handles CJS module imports into an ESM project.
Warnings
- breaking The package is labeled 'WIP - Work In Progress' in its README and has not been updated in over four years (last published January 2022). It should be considered abandoned and unsuitable for new production applications requiring robust security or active maintenance.
- gotcha Not all functions from the comprehensive libsodium API are implemented in `sodium-javascript`. The API documentation points to `sodium-native`, which is more feature-complete.
- breaking Being a pure JavaScript cryptographic library that is unmaintained, `sodium-javascript` might not incorporate the latest security patches or best practices for cryptographic primitives. Using unmaintained crypto libraries poses significant security risks.
- gotcha The API style, mimicking the low-level C libsodium, often requires manual buffer allocation for output and precise buffer sizing, which is error-prone and can lead to memory issues or incorrect results if not handled carefully. This contrasts with higher-level wrappers that manage buffers automatically.
- gotcha As a pure JavaScript implementation, `sodium-javascript` is generally slower than native C bindings (`sodium-native`) or WebAssembly-compiled versions (`libsodium-wrappers`), especially for intensive cryptographic operations.
Install
-
npm install sodium-javascript -
yarn add sodium-javascript -
pnpm add sodium-javascript
Imports
- sodium
import sodium from 'sodium-javascript'
const sodium = require('sodium-javascript') - crypto_secretbox_easy
import { crypto_secretbox_easy } from 'sodium-javascript'const sodium = require('sodium-javascript'); sodium.crypto_secretbox_easy(...) - submodule
import { submoduleName } from 'sodium-javascript/submodule-name'const sub = require('sodium-javascript/submodule-name')
Quickstart
const sodium = require('sodium-javascript')
const key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES)
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
sodium.randombytes_buf(key)
sodium.randombytes_buf(nonce)
const message = Buffer.from('Hello, World!')
const cipher = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES)
sodium.crypto_secretbox_easy(cipher, message, nonce, key)
console.log('Encrypted:', cipher.toString('hex'))
const plainText = Buffer.alloc(cipher.length - sodium.crypto_secretbox_MACBYTES)
sodium.crypto_secretbox_open_easy(plainText, cipher, nonce, key)
console.log('Plaintext:', plainText.toString())