Introduction

buddy-hashers provides a collection of secure password hashers with lightweight and extensible abstraction for build powerfull password authentication processes.

Table 1. Supported password hashers algorithms
Identifier Can I use it? Description

:bcrypt+blake2b-512

Recommended

BCrypt password hasher combined with blake2b-512

:pbkdf2+blake2b-512

Recommended

Password-Based Key Derivation Function 2 with blake2b-512

:pbkdf2+sha512

Recommended

Password-Based Key Derivation Function 2 with SHA256

:pbkdf2+sha3-256

Recommended

Password-Based Key Derivation Function 2 with SHA3-256

:bcrypt+sha512

Recommended

BCrypt password hasher combined with sha512 (default).

:pbkdf2+sha256

Yes

Password-Based Key Derivation Function 2 with SHA256

:bcrypt+sha384

Yes

BCrypt password hasher combined with sha384

:pbkdf2+sha1

Yes

Password-Based Key Derivation Function 2 (as defined in RFC2898)

:scrypt

Yes

Password-Based Key Derivation Function created by Colin Percival

Project Maturity

Since buddy-hashers is a young project there can be some API breakage.

Install

The simplest way to use buddy-core in a clojure project, is by including it in the dependency vector on your project.clj file:

[buddy/buddy-hashers "1.2.0"]

And is tested under JDK7 and JDK8.

Quick Start

Hashers module consists in two public functions: derive and check and both them are located on buddy.hashers namespace.

Let start deriving a password:

(require '[buddy.hashers :as hashers])

;; Generate hash from plain password
(hashers/derive "secretpassword")
;; => "bcrypt+sha512$4i9sd34m..."

(hashers/check "secretpassword" "bcrypt+sha512$4i9sd34m...")
;; => true

If no algorithm is specified, the :bcrypt+sha512 will be used by default. If you want to use a specific one, you can specify it using the optional options parameter:

;; Generate hash from plain password
(hashers/derive "secretpassword" {:alg :pbkdf2+sha256})
;; => "pbkdf2+sha256$4i9sd34m..."

(hashers/check "secretpassword" "pbkdf2+sha256$4i9sd34m...")
;; => true

Advanced options

Algorithm tunning params

Each algorithm can be tweaked passing additional parameters on the second argument to derive function. And options vary depending on the used algorithm.

Table 2. Table that deails available options and their defaults
Algorithm Available options Defaults

:bcrypt+blake2b-512

:salt, :iterations

iterations=12, salt=(random 16 bytes)

:bcrypt+sha384

:salt, :iterations

iterations=12, salt=(random 16 bytes)

:pbkdf2+blake2b-512

:salt, :iterations

iterations=50000, salt=(random 12 bytes)

:pbkdf2+sha512

:salt, :iterations

iterations=100000, salt=(random 12 bytes)

:pbkdf2+sha3_256

:salt, :iterations

iterations=100000, salt=(random 12 bytes)

:pbkdf2+sha1

:salt, :iterations

iterations=100000, salt=(random 12 bytes)

:scrypt

:salt, :cpucost, :memcost, :parallelism

salt=(random 12 bytes), cpucost=65536, memcost=8, parallelism=1

:bcrypt+sha512

:salt, :iterations

iterations=12, salt=(random 12 bytes)

:pbkdf2+sha256

:salt, :iterations

iterations=100000, salt=(random 12 bytes)

Limiting algorithms

Some times you don’t want to use all the supported algorithms and you only want to use a own set of algorithms in the password check process. That can be done passing additional parameter to the check function:

(def trusted-algs #{:pbkdf2+sha256 :bcrypt+sha512})

(hashers/check incoming-pwd derived-pwd {:limit trusted-algs})

The check function will return false if the incoming password uses an algorithm that does not allowed.

Rehash Hook

Choice a strong algorithm is important thing, but have a good update password-hashes policy is also very important and usually completelly forgotten. The password generated 3 years ago is weaker that one generated today…​

buddy-hashers comes with a solution for make this task easier. It consists in a setter hook that will be called when weaker password is detected, enabling for you the entry point for rehash the password and store it again to the database.

It there is an example on how it can be used:

(letfn [(setter [pwd]
          (let [pwd (hashers/derive pwd)]
            (do-the-db-update pwd)))]
  (hashers/check incoming-pwd derived-pwd {:setter setter}))

The setter will be called when the incoming password is valid but its config is weaker that the current default one.

Developers Guide

Philosophy

Five most important rules:

  • Beautiful is better than ugly.

  • Explicit is better than implicit.

  • Simple is better than complex.

  • Complex is better than complicated.

  • Readability counts.

All contributions to buddy-hashers should keep these important rules in mind.

Contributing

Unlike Clojure and other Clojure contributed libraries buddy-hashers does not have many restrictions for contributions. Just open an issue or pull request.

Get the Code

buddy-hashers is open source and can be found on github.

You can clone the public repository with this command:

git clone https://github.com/funcool/buddy-hashers

Run tests

For running tests just execute this:

lein test

License

buddy-hashers is licensed under Apache 2.0 License. You can see the complete text of the license on the root of the repository on LICENSE file.