bcrypt-ts
bcrypt-ts is a TypeScript-first, pure JavaScript implementation of the bcrypt password-hashing function, designed for both Node.js and browser environments. It provides cryptographic hashing for passwords, focusing on security features like salting and an adaptive iteration count to resist brute-force attacks. The current stable version is 8.0.1. The project appears to have a relatively active release cadence, with major versions (v6, v7, v8) released over time, often driven by Node.js version support or build system changes. Key differentiators from `bcrypt.js` include being fully written in TypeScript, providing separate ESM modules optimized for Node.js and browsers, offering better tree-shaking, and having a minified output. While compatible with the C++ `bcrypt` binding, it's inherently slower due to being a pure JavaScript implementation (approximately 30% slower according to the README, referencing `bcrypt.js` benchmarks), which means fewer iterations can be performed in the same timeframe, requiring careful consideration of the work factor.
Common errors
-
Error [ERR_REQUIRE_ESM]: require() of ES Module .../bcrypt-ts/dist/index.mjs from .../your-app.js not supported. Instead change the require of index.mjs to a dynamic import() which is available in all CommonJS modules.
cause `bcrypt-ts` v8.0.0 and later are pure ESM, but your project or file is attempting to import it using CommonJS `require()` syntax.fixUpdate your project to use ES module `import` syntax: `import { func } from 'bcrypt-ts';`. Ensure your `package.json` has `"type": "module"` or that the file importing `bcrypt-ts` has a `.mjs` extension. -
ERR_PNPM_OUTDATED_ENGINE The current Node.js version is v18.x.x which is not supported by the package bcrypt-ts@8.0.1. Its engine is compatible with "node": ">=20".
cause Your Node.js runtime version does not meet the minimum requirement specified by `bcrypt-ts` (Node.js >=20 for v8.x).fixUpgrade your Node.js environment to version 20 or newer. You can use a Node.js version manager like `nvm` to switch versions (e.g., `nvm install 20 && nvm use 20`). -
ReferenceError: crypto is not defined (when running in browser or bundler)
cause The Node.js bundle is being used in a browser environment, and it expects the Node.js `crypto` module to be available for secure randomness.fixEnsure your bundler (webpack, Vite, Rollup) is correctly configured to use the browser-specific bundle of `bcrypt-ts`. If issues persist, manually import from the browser bundle: `import { hash } from 'bcrypt-ts/browser'`.
Warnings
- breaking Version 8.0.0 and above drop support for CommonJS (cjs) and UMD builds. The package is now exclusively ESM. This requires projects to use `import` statements and have their environment configured for ESM.
- breaking Version 7.0.0 introduced a breaking change by dropping support for Node.js 18. Subsequent versions, including 8.x, require Node.js 20 or higher.
- breaking Version 6.0.0 changed the default hash generation to '2b' hashes. While bcrypt generally handles different versions, this indicates a change in the internal format used.
- gotcha bcrypt-ts is a pure JavaScript implementation and is approximately 30% slower than the native C++ bcrypt binding. This performance difference means that for the same security level (target time for hashing), you must use a lower 'salt rounds' (work factor) with `bcrypt-ts`.
- gotcha The maximum input password length for bcrypt is 72 bytes. Passwords longer than this will be truncated without explicit warning by the library itself for compatibility with the C++ binding. Note that UTF-8 characters can be up to 4 bytes.
Install
-
npm install bcrypt-ts -
yarn add bcrypt-ts -
pnpm add bcrypt-ts
Imports
- genSaltSync
const { genSaltSync } = require('bcrypt-ts')import { genSaltSync } from 'bcrypt-ts' - hash
const { hash } = require('bcrypt-ts')import { hash } from 'bcrypt-ts' - compareSync
import bcrypt from 'bcrypt-ts'; bcrypt.compareSync(...)
import { compareSync } from 'bcrypt-ts' - hash
import { hash } from 'bcrypt-ts'import { hash } from 'bcrypt-ts/node'
Quickstart
import { genSalt, hash, compare } from 'bcrypt-ts';
async function main() {
// Generate a salt with a work factor of 10
// A higher work factor increases security but also computation time
const saltRounds = 10;
console.log(`Generating salt with ${saltRounds} rounds...`);
const salt = await genSalt(saltRounds);
console.log('Salt generated:', salt);
// Hash a password using the generated salt
const password = process.env.USER_PASSWORD ?? 'mySecurePassword123!';
console.log('Hashing password...');
const hashedPassword = await hash(password, salt);
console.log('Hashed password:', hashedPassword);
// To store in your database, ensure the column can hold 60 characters
// Verify a password against the stored hash
const candidatePassword = process.env.LOGIN_PASSWORD ?? 'mySecurePassword123!';
console.log(`Comparing '${candidatePassword}' with hash...`);
const isMatch = await compare(candidatePassword, hashedPassword);
console.log('Password matches:', isMatch);
const wrongPassword = 'notThePassword';
console.log(`Comparing '${wrongPassword}' with hash...`);
const isWrongMatch = await compare(wrongPassword, hashedPassword);
console.log('Wrong password matches:', isWrongMatch);
}
main().catch(console.error);