{"id":12206,"library":"tweetnacl","title":"TweetNaCl.js: Cryptographic Library","description":"TweetNaCl.js is a JavaScript port of the TweetNaCl/NaCl cryptographic library, designed for modern browsers and Node.js. It provides a thin layer of idiomatic high-level API over a faithful translation of the original C implementation, prioritizing security and correctness. The library ships with two versions: `nacl.js` (a direct port) and `nacl-fast.js` (which includes faster, optimized functions and is used by default when installed via npm). Currently at version 1.0.3, it maintains a stable release cadence with updates typically addressing security fixes or minor improvements. A key differentiator is its public domain license and a comprehensive audit by Cure53 in 2017, which found no security problems, cementing its reputation as a robust and secure cryptographic tool. All API functions operate on `Uint8Array` for byte handling.","status":"active","version":"1.0.3","language":"javascript","source_language":"en","source_url":"https://github.com/dchest/tweetnacl-js","tags":["javascript","crypto","cryptography","curve25519","ed25519","encrypt","hash","key","nacl","typescript"],"install":[{"cmd":"npm install tweetnacl","lang":"bash","label":"npm"},{"cmd":"yarn add tweetnacl","lang":"bash","label":"yarn"},{"cmd":"pnpm add tweetnacl","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Recommended for encoding/decoding strings to/from Uint8Array, as TweetNaCl.js functions exclusively operate on Uint8Array.","package":"tweetnacl-util-js","optional":true}],"imports":[{"note":"The library exports the main 'nacl' object as a default export for ESM compatibility, aligning with its CommonJS `module.exports` structure.","wrong":"import { nacl } from 'tweetnacl';","symbol":"nacl","correct":"import nacl from 'tweetnacl';"},{"note":"CommonJS import; `require('tweetnacl')` directly returns the 'nacl' object (specifically `nacl-fast.js` by default).","symbol":"nacl","correct":"const nacl = require('tweetnacl');"},{"note":"For TypeScript users, specific types like `BoxKeyPair` are available for explicit type annotations.","symbol":"BoxKeyPair","correct":"import type { BoxKeyPair } from 'tweetnacl';"}],"quickstart":{"code":"import nacl from 'tweetnacl';\n\n// Utility for converting strings to Uint8Array and vice-versa (not part of tweetnacl itself)\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\nfunction utf8ToUint8Array(str) {\n  return encoder.encode(str);\n}\n\nfunction uint8ArrayToUtf8(arr) {\n  return decoder.decode(arr);\n}\n\n// Generate a key pair for the sender and receiver\nconst senderKeyPair = nacl.box.keyPair();\nconst receiverKeyPair = nacl.box.keyPair();\n\n// A message to encrypt\nconst message = 'Hello, secure world! This is a secret message.';\nconst messageUint8 = utf8ToUint8Array(message);\n\n// Generate a random nonce for the encryption\nconst nonce = nacl.randomBytes(nacl.box.nonceLength);\n\n// Encrypt the message\nconst encryptedMessage = nacl.box(\n  messageUint8,\n  nonce,\n  receiverKeyPair.publicKey,\n  senderKeyPair.secretKey\n);\n\nconsole.log('Original message:', message);\nconsole.log('Encrypted message (Uint8Array):', encryptedMessage);\n\n// Decrypt the message\nconst decryptedMessageUint8 = nacl.box.open(\n  encryptedMessage,\n  nonce,\n  senderKeyPair.publicKey,\n  receiverKeyPair.secretKey\n);\n\nif (decryptedMessageUint8) {\n  const decryptedMessage = uint8ArrayToUtf8(decryptedMessageUint8);\n  console.log('Decrypted message:', decryptedMessage);\n} else {\n  console.error('Decryption failed!');\n}","lang":"typescript","description":"This quickstart demonstrates public-key authenticated encryption using `nacl.box`. It covers key pair generation, message encryption, and decryption, highlighting the use of `Uint8Array` for all data operations and the importance of a unique nonce."},"warnings":[{"fix":"Ensure your code checks for `null` or uses a general falsy check (`!result`) for failed decryption operations instead of strict `=== false`.","message":"In versions 1.0.0 and later, functions like `nacl.secretbox.open`, `nacl.box.open`, and `nacl.box.after` now return `null` instead of `false` when decryption fails (e.g., due to incorrect key, nonce, or tampered input). While `if (!result)` checks generally remain compatible, direct comparison `if (result == false)` will behave differently.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Upgrade immediately to `tweetnacl@1.0.3` or newer to ensure correct signature generation. Re-sign any critical data signed with affected versions.","message":"Version 1.0.3 includes an important security fix. A bug in the modulo reduction calculation for integers larger than 32 bits could lead to `nacl.sign` or `nacl.sign.detached` creating *incorrect signatures*. This issue specifically affected signature generation, not verification. Users of previous versions are strongly urged to upgrade.","severity":"breaking","affected_versions":"<1.0.3"},{"fix":"Ensure you are using `tweetnacl@0.14.3` or any later version (including current 1.x releases). Version 0.14.3 fixed this issue by reverting to the original, slower Poly1305 implementation until a corrected fast version was available, and subsequent versions resolved it completely.","message":"Versions 0.14.2 through 0.14.3 experienced a critical bug in the 'fast' version of Poly1305. This bug could occasionally produce incorrect results, potentially affecting the authenticity of `secretbox`, `secretbox.open`, `box`, and `box.open` functions. Although the chance of real-world impact was considered low, it was a significant vulnerability.","severity":"breaking","affected_versions":"0.14.2"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Always convert input data to `Uint8Array` before passing it to TweetNaCl.js functions. For Node.js Buffers, use `Buffer.from(myBuffer)` for copying, or `Buffer.isBuffer(myVar) ? Uint8Array.from(myVar) : myVar` for robust handling. For strings, use `new TextEncoder().encode(myString)` or `tweetnacl-util-js`.","cause":"TweetNaCl.js functions strictly expect `Uint8Array` instances for all byte operations. Passing strings, Arrays, or Node.js Buffers incorrectly will lead to type errors.","error":"Error: Argument 1 must be of type Uint8Array"},{"fix":"Ensure you are using the correct import statement: `import nacl from 'tweetnacl';` for ESM, or `const nacl = require('tweetnacl');` for CommonJS. Verify that your environment correctly handles module resolution, especially in bundler configurations.","cause":"This usually indicates that the `nacl` object was not imported correctly, or the import resulted in an undefined or partial object.","error":"TypeError: nacl.box is not a function"}],"ecosystem":"npm"}