Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

bcrypt

import bcrypt

Generating and verifying bcrypt password hashes, and reading information back out of an existing hash (its cost factor and salt).

hash() and compare() are the two functions almost every caller needs: hash a password before storing it, then compare a login attempt against the stored hash later. The salt is generated internally by a real cryptographically secure random source, embedded in the returned hash string, and never needs to be handled separately.

Example,

%> import bcrypt
%> var stored = bcrypt.hash('correct horse battery staple')
%> stored
'$2b$10$N9qo8uLOickgx2ZMRZoMy.MrqmVwj0dJmwB3vk...'
%> bcrypt.compare('correct horse battery staple', stored)
true
%> bcrypt.compare('wrong password', stored)
false

The bcrypt API

Every public name in bcrypt, wherever it is declared. Each links to the page that documents it.

NameKindSummary
bcrypt.DEFAULT_LOG2_ROUNDSconstantDefault cost factor used by hash() when rounds isn’t given.
bcrypt.comparefunctionChecks whether str is the password known_hash was generated from.
bcrypt.get_roundsfunctionReads the cost factor a hash was generated with back out of it.
bcrypt.get_saltfunctionReads the salt portion out of a hash: the first 29 characters, covering the $2x$rounds$salt prefix.
bcrypt.hashfunctionHashes str with bcrypt, generating a fresh random salt internally on every call: hashing the same string…
bcrypt.needs_rehashfunctionChecks whether a stored hash was generated with a lower cost factor than target_rounds, meaning it should…

Constants

DEFAULT_LOG2_ROUNDS

bcrypt.DEFAULT_LOG2_ROUNDS: number = 10

Default cost factor used by hash() when rounds isn’t given. Higher means slower to compute (and slower to brute-force): each increment roughly doubles the work. 10 is a reasonable default for an interactive login flow; raise it over time as hardware gets faster (see needs_rehash()).

Functions

hash()

bcrypt.hash(str: string, rounds: ?number) -> string

Hashes str with bcrypt, generating a fresh random salt internally on every call: hashing the same string twice always produces two different (but equally valid) hashes.

Parameters

  • str (string)
  • rounds (?number) — The cost factor, 4-31. Default DEFAULT_LOG2_ROUNDS.

Returns string

Raises Error if rounds is out of range.

compare()

bcrypt.compare(str: string, known_hash: string)

Checks whether str is the password known_hash was generated from.

Parameters

  • str (string)
  • known_hash (string)

Returns — bool: false for a wrong password, and also false (rather than raising) for a known_hash that isn’t a well-formed bcrypt hash at all.

get_rounds()

bcrypt.get_rounds(hash: string) -> number

Reads the cost factor a hash was generated with back out of it.

Parameters

  • hash (string)

Returns number

Raises Error if hash isn’t a well-formed bcrypt hash.

get_salt()

bcrypt.get_salt(hash: string) -> string

Reads the salt portion out of a hash: the first 29 characters, covering the $2x$rounds$salt prefix.

Parameters

  • hash (string)

Returns string

Raises Error if hash is shorter than a real bcrypt hash.

Note: this does not validate that hash is actually a well-formed bcrypt hash; call get_rounds() first if you need that checked.

needs_rehash()

bcrypt.needs_rehash(hash: string, target_rounds: number) -> bool

Checks whether a stored hash was generated with a lower cost factor than target_rounds, meaning it should be re-hashed (at the user’s next successful login, typically) to bring it up to the current standard.

Example,

%> if bcrypt.compare(password, user.password_hash) {
..   if bcrypt.needs_rehash(user.password_hash, 12) {
..     user.password_hash = bcrypt.hash(password, 12)
..   }
..   # ... proceed with login
.. }

Parameters

  • hash (string)
  • target_rounds (number)

Returns bool


2022, Richard Ore and The Zuri Contributors