README

go-hmaccrypt provides very strong password digests using a combination of a
peppered hash-based message authentication code (HMAC) and a salted adaptive
key derivation function like bcrypt.

A digest of each password is generated using e.g. HMAC-SHA512 with a pepper--a
value stored separately from the final digests--after which a bcrypt digest
of the HMAC digest is generated. The bcrypt digest is saved in e.g. a database.

With this approach, you can ensure the safety of user passwords even if an
SQL injection compromises the contents of your database's users table, or if
a weakness is found in e.g. bcrypt.

This approach is described on
https://wiki.mozilla.org/WebAppSec/Secure_Coding_Guidelines#Password_Storage

go-hmaccrypt can be used safely by multiple goroutines.

== Installation

go get github.com/pmylund/go-hmaccrypt

== Documentation

go doc github.com/pmylund/go-hmaccrypt
or http://go.pkgdoc.org/github.com/pmylund/go-hmaccrypt

== Usage

import (
	"crypto/sha512"
	"github.com/pmylund/go-hmaccrypt"
)

pepper := []byte("randomly generated sequence stored on disk or in the source")
crypt := hmaccrypt.New(sha512.New, pepper)

password := []byte("f00b4r!")
digest, err := crypt.Bcrypt(password, 10)
if err != nil {
	...
}
// save the bcrypt digest in the database

if err := crypt.BcryptCompare(digest, password); err == nil {
	// the password is a match
	...
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type HmacCrypt

type HmacCrypt struct {
	// contains filtered or unexported fields
}

func New

func New(hash func() hash.Hash, pepper []byte) *HmacCrypt

Returns a HmacCrypt using the specified hash (e.g. sha512.New) and pepper for its HMAC function. The pepper should be stored separately from the returned digests. If the digests are stored in a database, it is a good idea to store the pepper on the disk, or as a constant in the application itself.

func (*HmacCrypt) Bcrypt

func (c *HmacCrypt) Bcrypt(password []byte, cost int) ([]byte, error)

Generates a new bcrypt(HMAC-hash(password, pepper), salt(cost)) digest of a password with a given bcrypt cost/work factor, e.g. 10 (bcrypt.DefaultCost). Use BcryptCompare to compare a password to an existing digest.

func (*HmacCrypt) BcryptCompare

func (c *HmacCrypt) BcryptCompare(digest, password []byte) error

Compares an existing bcrypt digest to HMAC-hash(password, pepper). Returns an error if there is no match.

Source Files