bcrypt for NodeJS

repository·master·Indexed 27 days ago

https://github.com/kelektiv/node.bcrypt.js

A Node.js binding for the bcrypt password hashing function, providing tools for secure salt generation, data hashing, and password comparison. It supports both asynchronous (callback and Promise-based) and synchronous APIs, with pre-built binaries for Windows, Linux, and macOS. Version 6.0.0 supports $2a$ and $2b$ prefix hashes and is compatible with Node 18+.

Tokens
1.6K
Snippets
4
Records
11
Agent score
43%

What's inside bcrypt

  1. Install bcrypt via NPM

    master

    Install the library using npm. Note that OS X users using Xcode 4.3.1 or above may need to run a specific command if they encounter xcodebuild errors during installation.

    Pre-built binaries are available for:

    • Windows x64 and arm64
    • Linux x64 and arm64 (GlibC and musl)
    • macOS x64 and arm64

    Only current stable and supported LTS releases (Node 18+) are actively tested.

    npm install bcrypt

    If xcodebuild errors occur on macOS:

    sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
  2. Configure Hashing Cost (Rounds)

    master

    The rounds parameter determines the computational cost. The actual number of iterations is $2^{rounds}$. Increasing the rounds significantly increases the time required to hash, which helps protect against brute-force attacks.

    Performance Estimates (approximate on 2GHz core):

    • rounds=10: ~10 hashes/sec
    • rounds=12: 2-3 hashes/sec
    • rounds=13: ~1 sec/hash
    • rounds=15: ~3 sec/hash
  3. Security Note: Timing Attacks

    master

    The bcrypt library is not susceptible to timing attacks because it compares full bcrypt hash digests rather than raw passwords. However, the comparison function itself is not time-safe (constant-time) and may exit early on a mismatch.

    Warning: Do not use the comparison function outside of the bcrypt library, as the security guarantees (preimage resistance of the hash) may no longer apply.

  4. Compare a password using async callbacks

    master

    Use bcrypt.compare to check if a provided plaintext password matches a stored hash.

    const bcrypt = require('bcrypt');
    // Load hash from your password DB.
    
    bcrypt.compare(myPlaintextPassword, hash, function(err, result) {
        // result == true if match
    });
  5. Hash a password using async callbacks (recommended)

    master

    For server-side applications, use the asynchronous API to avoid blocking the event loop. You can either generate a salt and hash in separate calls, or use the auto-gen method which handles both in one call.

    saltRounds determines the cost factor.

    const bcrypt = require('bcrypt');
    const saltRounds = 10;
    const myPlaintextPassword = 's0/\/\P4$$w0rD';
    
    // Technique 1: Separate salt and hash
    bcrypt.genSalt(saltRounds, function(err, salt) {
        bcrypt.hash(myPlaintextPassword, salt, function(err, hash) {
            // Store hash in your password DB.
        });
    });
    
    // Technique 2: Auto-gen salt and hash
    bcrypt.hash(myPlaintextPassword, saltRounds, function(err, hash) {
        // Store hash in your password DB.
    });
  6. BCrypt API Reference

    master

    The BCrypt object provides methods for generating salts, hashing data, and comparing hashes. Most methods support both synchronous and asynchronous (callback or Promise-based) execution.

    Salt Generation

    • genSaltSync(rounds, minor): Synchronously generates a salt.
      • rounds (optional): Cost of processing (default: 10).
      • minor (optional): Minor version of bcrypt (default: b).
    • genSalt(rounds, minor, cb): Asynchronously generates a salt. If no callback cb is provided, it returns a Promise.

    Hashing

    • hashSync(data, salt): Synchronously hashes data (string or Buffer) using the provided salt. If salt is a number, it is treated as the number of rounds.
    • hash(data, salt, cb): Asynchronously hashes data. If no callback cb is provided, it returns a Promise.

    Comparison

    • compareSync(data, encrypted): Synchronously compares data against encrypted hash.
    • compare(data, encrypted, cb): Asynchronously compares data against encrypted hash. Returns a Promise if no callback is provided.

    Utilities

    • getRounds(encrypted): Returns the number of rounds used in a given hash.
    • promises.use(promiseImplementation): Replaces the internal Promise implementation with a custom Promises/A+ compatible one.
  7. Security considerations for bcrypt

    master

    Password Length Limit

    Per the bcrypt implementation, only the first 72 bytes of a string are used. Any extra bytes are ignored. Note that this refers to bytes, not characters (e.g., UTF-8 emojis may consume more than 1 byte per character).

    Version Security Warnings

    • Upgrade to at least v5.0.0: Versions < 5.0.0 suffer from a bcrypt wrap-around bug that truncates passwords $\ge$ 255 characters, and they do not handle NUL characters properly, which can lead to severely weakened passwords.

    Hash Compatibility

    • Supports $2a$ and $2b$ prefix bcrypt hashes.
    • $2x$ and $2y$ hashes (from John the Ripper) are theoretically compatible with $2b$.
  8. Understand the Bcrypt Hash Format

    master

    Bcrypt hashes are 60 characters long and follow the structure: $[algorithm]$[cost]$[salt][hash].

    Example breakdown of $2b$10$nOUIs5kJ7naTuTFkBy1veuK0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa:

    • Algorithm Identifier: $2a$ or $2b$ (e.g., 2b)
    • Cost-factor: The exponent $n$ (e.g., 10 means $2^{10}$ iterations)
    • Salt: 16-byte (128-bit) salt, base64 encoded to 22 characters (e.g., nOUIs5kJ7naTuTFkBy1veu)
    • Hash: 24-byte (192-bit) hash, base64 encoded to 31 characters (e.g., K0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa)