Documentation ¶
Overview ¶
Package passwap provides a unified implementation between different password hashing algorithms. It allows for easy swapping between algorithms, using the same API for all of them.
Passwords hashed with passwap, using a certain algorithm and parameters can be stored in a database. If at a later moment paramers or even the algorithm is changed, passwap is still able to verify the "outdated" hashes and automatically return an updated hash when applicable. Only when an updated hash is returned, the record in the database needs to be updated.
Resulting password hashes are encoded using dollar sign ($) notation. It's origin lies in Glibc, but there is no clear standard on the matter For passwap it is choosen to follow suit with python's passlib identifiers to be (hopefully) as portable as possible. Suplemental information can be found:
Glibc: https://man.archlinux.org/man/crypt.5;
Passlib "Modular Crypt Format": https://passlib.readthedocs.io/en/stable/modular_crypt_format.html;
Password Hashing Competition string format: https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md;
Example ¶
// Create a new swapper which hashes using bcrypt, // verifies and upgrades scrypt. passwords := NewSwapper( bcrypt.New(bcrypt.DefaultCost), scrypt.Verifier, ) // Create an encoded bcrypt hash string of password with salt. encoded, err := passwords.Hash("good_password") if err != nil { panic(err) } fmt.Println(encoded) // $2a$10$eS.mS5Zc5YAJFlImXCpLMu9TxXwKUhgQxsbghlvyVwvwYO/17E2qy // Replace the swapper to hash using argon2id, // verifies and upgrades scrypt and bcrypt. passwords = NewSwapper( argon2.NewArgon2id(argon2.RecommendedIDParams), bcrypt.Verifier, scrypt.Verifier, ) // Attempt to verify encoded bcrypt string with a wrong password. // Returns an error and empty "updated" if updated, err := passwords.Verify(encoded, "wrong_password"); err != nil { fmt.Println(err) // passwap: password does not match hash } else if updated != "" { encoded = updated } fmt.Println(encoded) // $2a$10$eS.mS5Zc5YAJFlImXCpLMu9TxXwKUhgQxsbghlvyVwvwYO/17E2qy // encoded is unchanged. // Verify encoded bcrypt string with a good password. // Returns a new encoded string with argon2id hash // of password and new random salt. if updated, err := passwords.Verify(encoded, "good_password"); err != nil { panic(err) } else if updated != "" { encoded = updated } fmt.Println(encoded) // $argon2id$v=19$m=65536,t=1,p=4$d6SOdxdIip9BC7sM5H7PUQ$2E7OIz7C1NkMLOsXi5nSe5vfbthdc9N9SWVlArd200E // encoded is updated. // Verify encoded argon2 string with a good password. // "updated" now is empty because the parameters of the Hasher // match the one in the encoded string. if updated, err := passwords.Verify(encoded, "good_password"); err != nil { panic(err) } else if updated != "" { // updated is empty, nothing is stored encoded = updated } fmt.Println(encoded) // $argon2id$v=19$m=65536,t=1,p=4$d6SOdxdIip9BC7sM5H7PUQ$2E7OIz7C1NkMLOsXi5nSe5vfbthdc9N9SWVlArd200E // encoded in unchanged. // Replace the swapper again. This time we still // use argon2id, but increased the Time parameter. passwords = NewSwapper( argon2.NewArgon2id(argon2.Params{ Time: 2, Memory: 64 * 1024, Threads: 4, KeyLen: 32, SaltLen: 16, }), bcrypt.Verifier, scrypt.Verifier, ) // Verify encoded argon2id string with a good password. // Returns a new encoded string with argon2id hash // of password and new random salt, // because of paremeter mis-match. if updated, err := passwords.Verify(encoded, "good_password"); err != nil { panic(err) } else if updated != "" { encoded = updated } fmt.Println(encoded) // $argon2id$v=19$m=65536,t=2,p=4$44X+dwU+aSS85Kl1qH3/Jg$n/tQoAtx/I/Rt9BXHH9tScshWucltPPmB0HBLVtXCq0 // encoded is updated.
Output:
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrPasswordMismatch = errors.New("passwap: password does not match hash") ErrNoVerifier = errors.New("passwap: no verifier found for encoded string") )
Functions ¶
This section is empty.
Types ¶
type Hasher ¶
Hasher is capable of creating new hashes of passwords, and verify passwords against existing hashes created by itself.
type SkipErrors ¶
type SkipErrors []error
SkipErrors is only returned when multiple Verifiers matched an encoding string, but encountered an error decoding it.
func (SkipErrors) Error ¶
func (e SkipErrors) Error() string
type Swapper ¶
type Swapper struct {
// contains filtered or unexported fields
}
Swapper is capable of creating new hashes of passwords and verify passwords against existing hashes for which it has verifiers configured. Swapper also updates hashes that are not created by the main hasher or use outdated cost parameters.
func NewSwapper ¶
NewSwapper with Hasher used for creating new hashes and primary verifier. Suplemental verifiers can be provided and will be used as fallback.
func (*Swapper) Verify ¶
Verify a password against an existing encoded hash, using the configured Hasher or one of the Verifiers.
ErrNoVerifier is returned if no matching Verifier is found for the encoded string. ErrPasswordMismatch when the password hash doesn't match the encoded hash. When multiple Verifiers match and encounter an error during decoding, a SkipErrors is returned containing all those errors is returned.
If the used Verifier is different from the the current Hasher or the cost parameters differ, an updated encoded hash string is returned for the same (valid) password. In all other cases updated remains empty. When updated is not empty, it must be stored untill next use.
Directories ¶
Path | Synopsis |
---|---|
Package argon2 provides salt generation, hashing and verification for x/crypto/argon2.
|
Package argon2 provides salt generation, hashing and verification for x/crypto/argon2. |
internal
|
|
salt
Package salt provides utilities for generating salts.
|
Package salt provides utilities for generating salts. |
Package md5 provides hashing and verification or md5Crypt encoded passwords.
|
Package md5 provides hashing and verification or md5Crypt encoded passwords. |
Package scrypt provides salt generation, hashing and verification for x/crypto/scrypt.
|
Package scrypt provides salt generation, hashing and verification for x/crypto/scrypt. |
Package verifier provides types and interfaces for building verifiers, used by passwap.
|
Package verifier provides types and interfaces for building verifiers, used by passwap. |