a tiny cleanup for salt hash vs salt profile mismatch.
pcrypt uses v0.2.0 now.
README update for v0.2.0 release.
A simple golang password hashing package.
New "password hashing" algorithms (PHC) have emerged in order to counter the increase in hardware assets available to crack passwords easily when they are stolen.
Those new algorithms increase the cost of an attack and slow down the discovery of the original password. Unfortunately they requires various non-trivial parameters to be used properly.
This package attempts to provide a safe and easy interface to produce/verify a hashed password, while giving the ability to tune for specific/custom needs if necessary.
3 algorithms are used:
x/crypto/bcrypt
, FOR LEGACY reasons)x/crypto/scrypt
)x/crypto/argon2
)To keep things simple and to avoid a user to shoot himself in the foot, parameters choices are (for now) limited/translated into 2 static "profiles" for each algorithms:
You can also decide to use your own Argon2 or Scrypt custom parameters with this package.
It is an attempt to dimension crypto parameters to common use cases (interactive/web auth/blabla) vs file storage
Custom profiles allow a user to define its own hashing parameters if those default don't fit.
Commonly password hashing includes hashing parameters in order to provide interoperability.
if no interoperability is needed (outside your authentication needs) and to make things slightly more annoying for a regular attacker, you might "mask" your parameters (instead of embedding them in the resulting hash).
Public parameters will embbed the derivation parameters in the resulting hash.
This allows you to simply use the passwd.Compare()
function against a hash without
the need of a profile object.
Masked parameters will remove the derivation parameters from the resulting hash.
This requires you to passwd.NewMasked()
before calling the profile Compare()
method.
An attacker would have to not only grab the stored password, but also to guess the parameters you use with your key derivation in order to attack it offline.
!!! IMPORTANT !!! This is NOT what makes your hash safe, it just makes it slightly harder to attack offline.
Key'd hashes makes it impossible to bruteforce (unless collision in hashes of course or the secret leaks), key'd hashes try to guarantee that leaked password cannot be attacked offline.
We used the method described here.
This requires you to <profile>.SetKey()
before call the Hash()
or Compare()
function.
create a password hashing object with Argon2 default profile:
p, err := passwd.New(passwd.Argon2idDefault)
if err != nil {
// handle error
}
hashed, err := p.Hash( []byte("my1337p4ssw0rd!") )
if err != nil {
// handle error
}
// hashed value: $2id$GlQX3F.KSYw1JLVv.LKDT.$1$65536$8$32$97DO7W9m/I8CTEQFKDa.VvEBTX1WepVv4qaWlt0OqH6
check a hash against a password:
err := passwd.Compare(hashed, []byte("password"))
if err != nil {
// handle error
}
p, err := passwd.NewMasked(passwd.Argon2idDefault)
if err != nil {
// handle error
}
hashed, err := p.Hash( []byte("my1337p4ssw0rd!") )
if err != nil {
// handle error
}
// hashed value: $2id$ihFFCGUfBHTqUfvUIos6X.$AmClxc.3uj6LsxjVGqpOZggyqIL.wQJ9zjY23ztsETK
p, err := passwd.NewMasked(passwd.Argon2idDefault)
if err != nil {
// handle error
}
// set the hashing key.
err = p.SetKey([]byte("myhashingsecret")
if err != nil {
// handle error
}
hashed, err := p.Hash( []byte("my1337p4ssw0rd!") )
if err != nil {
// handle error
}
// hashed value: $2id$ihFFCGUfBHTqUfvUIos6X.$AmClxc.3uj6LsxjVGqpOZggyqIL.wQJ9zjY23ztsETK
check a hash against a password, use the profile you defined to compare:
err := p.Compare(hashed, []byte("password"))
if err != nil {
// handle error
}
This package exclusively uses crypto algorithm implementations shipped in go extended crypto packages (located in x/crypto/
)
This is a work in progress and the default are still being worked out/verified (feedback is welcome).
An example tool is provided in this repository:
Note: small issue with git.sr.ht that prevents for now to go get subpackages inside a module, i'm trying untangle the cause and provide a patch..
hopefully this helps understanding how to use this package.
v0.2.1: (MASTER BRANCH / NOT RELEASED/TAGGED THIS IS JUST MASTER).
v0.2.0:
v0.1.3:
v0.1.2: fix hash parsing.
v0.1.1: fix /issues/1
v0.1.0: initial release
bcrypt is just a wrapper to x/crypto/bcrypt
, only scrypt and argon support masked parameters.
bcrypt is implemented for migration purposes, passwd.Compare()
will works perfectly with x/crypto/bcrypt
hashed passwords while
using a modern profile to store new passwords.
Send patches and questions to ~eau/passwd@lists.sr.ht.
Subscribe to release announcements on ~eau/passwd-announce
Bugs & todo here: ~eau/passwd