Flask-Bcrypt

Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application.

Due to the recent increased prevelance of powerful hardware, such as modern GPUs, hashes have become increasingly easy to crack. A proactive solution to this is to use a hash that was designed to be “de-optimized”. Bcrypt is such a hashing facility; unlike hashing algorithms such as MD5 and SHA1, which are optimized for speed, bcrypt is intentionally structured to be slow.

For sensitive data that must be protected, such as passwords, bcrypt is an advisable choice.

Installation

Install the extension with one of the following commands:

$ easy_install flask-bcrypt

or alternatively if you have pip installed:

$ pip install flask-bcrypt

Note

You need Python Development Headers to install py-bcrypt package, needed as a dependency. If you are on Mac OS or Windows, you probably have it already installed. Otherwise look for python-dev package for Debian-based distributives and for python-devel package for RedHat-based.

Usage

To use the extension simply import the class wrapper and pass the Flask app object back to here. Do so like this:

from flask import Flask
from flask.ext.bcrypt import Bcrypt

app = Flask(__name__)
bcrypt = Bcrypt(app)

Two primary hashing methods are now exposed by way of the bcrypt object. In Python 2, use them like so:

pw_hash = bcrypt.generate_password_hash('hunter2')
bcrypt.check_password_hash(pw_hash, 'hunter2') # returns True

In Python 3, you need to use decode(‘utf-8’) on generate_password_hash(), like below:

pw_hash = bcrypt.generate_password_hash(‘hunter2’).decode(‘utf-8’)

API

class flask_bcrypt.Bcrypt(app=None)

Bcrypt class container for password hashing and checking logic using bcrypt, of course. This class may be used to intialize your Flask app object. The purpose is to provide a simple interface for overriding Werkzeug’s built-in password hashing utilities.

Although such methods are not actually overriden, the API is intentionally made similar so that existing applications which make use of the previous hashing functions might be easily adapted to the stronger facility of bcrypt.

To get started you will wrap your application’s app object something like this:

app = Flask(__name__)
bcrypt = Bcrypt(app)

Now the two primary utility methods are exposed via this object, bcrypt. So in the context of the application, important data, such as passwords, could be hashed using this syntax:

password = 'hunter2'
pw_hash = bcrypt.generate_password_hash(password)

Once hashed, the value is irreversible. However in the case of validating logins a simple hashing of candidate password and subsequent comparison. Importantly a comparison should be done in constant time. This helps prevent timing attacks. A simple utility method is provided for this:

candidate = 'secret'
bcrypt.check_password_hash(pw_hash, candidate)

If both the candidate and the existing password hash are a match check_password_hash returns True. Otherwise, it returns False.

Namespacing Issues

It’s worth noting that if you use the format, bcrypt = Bcrypt(app) you are effectively overriding the bcrypt module. Though it’s unlikely you would need to access the module outside of the scope of the extension be aware that it’s overriden.

Alternatively consider using a different name, such as flask_bcrypt = Bcrypt(app) to prevent naming collisions.

Additionally a configuration value for BCRYPT_LOG_ROUNDS may be set in the configuration of the Flask app. If none is provided this will internally be assigned to 12. (This value is used in determining the complexity of the encryption, see bcrypt for more details.)

You may also set the hash version using the BCRYPT_HASH_PREFIX field in the configuration of the Flask app. If not set, this will default to 2b. (See bcrypt for more details)

By default, the bcrypt algorithm has a maximum password length of 72 bytes and ignores any bytes beyond that. A common workaround is to hash the given password using a cryptographic hash (such as sha256), take its hexdigest to prevent NULL byte problems, and hash the result with bcrypt. If the BCRYPT_HANDLE_LONG_PASSWORDS configuration value is set to True, the workaround described above will be enabled. Warning: do not enable this option on a project that is already using Flask-Bcrypt, or you will break password checking. Warning: if this option is enabled on an existing project, disabling it will break password checking.

Parameters:app – The Flask application object. Defaults to None.
check_password_hash(pw_hash, password)

Tests a password hash against a candidate password. The candidate password is first hashed and then subsequently compared in constant time to the existing hash. This will either return True or False.

Example usage of check_password_hash would look something like this:

pw_hash = bcrypt.generate_password_hash('secret', 10)
bcrypt.check_password_hash(pw_hash, 'secret') # returns True
Parameters:
  • pw_hash – The hash to be compared against.
  • password – The password to compare.
generate_password_hash(password, rounds=None, prefix=None)

Generates a password hash using bcrypt. Specifying rounds sets the log_rounds parameter of bcrypt.gensalt() which determines the complexity of the salt. 12 is the default value. Specifying prefix sets the prefix parameter of bcrypt.gensalt() which determines the version of the algorithm used to create the hash.

Example usage of generate_password_hash might look something like this:

pw_hash = bcrypt.generate_password_hash('secret', 10)
Parameters:
  • password – The password to be hashed.
  • rounds – The optional number of rounds.
  • prefix – The algorithm version to use.
init_app(app)

Initalizes the application with the extension.

Parameters:app – The Flask application object.
flask_bcrypt.generate_password_hash(password, rounds=None)

This helper function wraps the eponymous method of Bcrypt. It is intended to be used as a helper function at the expense of the configuration variable provided when passing back the app object. In other words this shortcut does not make use of the app object at all.

To this this function, simple import it from the module and use it in a similar fashion as the method would be used. Here is a quick example:

from flask.ext.bcrypt import generate_password_hash
pw_hash = generate_password_hash('hunter2', 10)
Parameters:
  • password – The password to be hashed.
  • rounds – The optional number of rounds.
flask_bcrypt.check_password_hash(pw_hash, password)

This helper function wraps the eponymous method of Bcrypt. It is intended to be used as a helper function at the expense of the configuration variable provided when passing back the app object. In other words this shortcut does not make use of the app object at all.

To this this function, simple import it from the module and use it in a similar fashion as the method would be used. Here is a quick example:

from flask.ext.bcrypt import check_password_hash
check_password_hash(pw_hash, 'hunter2') # returns True
Parameters:
  • pw_hash – The hash to be compared against.
  • password – The password to compare.