Documentation ¶
Overview ¶
Package passwordhash provides functions to create and verify a password hash using a strong one-way hashing algorithm.
It supports "peppering" by encrypting the hashed passwords using a secret key.
It is based on the Argon2id algorithm (https://www.rfc-editor.org/info/rfc9106), as recommended by the OWASP Password Storage Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
Index ¶
- Constants
- type Hashed
- type Option
- type Params
- func (ph *Params) EncryptPasswordHash(key []byte, password string) (string, error)
- func (ph *Params) EncryptPasswordVerify(key []byte, password, hash string) (bool, error)
- func (ph *Params) PasswordHash(password string) (string, error)
- func (ph *Params) PasswordVerify(password, hash string) (bool, error)
Examples ¶
Constants ¶
const ( // DefaultAlgo is the default algorithm used to hash the password. // It corresponds to Type y=2. DefaultAlgo = "argon2id" // DefaultKeyLen is the default length of the returned byte-slice that can be used as cryptographic key (Tag length). // It must be an integer number of bytes from 4 to 2^(32)-1. DefaultKeyLen = 32 // DefaultSaltLen is the default length of the random password salt (Nonce S). // It must be not greater than 2^(32)-1 bytes. // The value of 16 bytes is recommended for password hashing. DefaultSaltLen = 16 // DefaultTime (t) is the default number of passes (iterations) over the memory. // It must be an integer value from 1 to 2^(32)-1. DefaultTime = 3 // DefaultMemory is the default size of the memory in KiB. // It must be an integer number of kibibytes from 8*p to 2^(32)-1. // The actual number of blocks is m', which is m rounded down to the nearest multiple of 4*p. DefaultMemory = 64 * 1024 // DefaultMinPasswordLength is the default minimum length of the input password (Message string P). // It must have a length not greater than 2^(32)-1 bytes. DefaultMinPasswordLength = 8 // DefaultMaxPasswordLength is the default maximum length of the input password (Message string P). // It must have a length not greater than 2^(32)-1 bytes. DefaultMaxPasswordLength = 4096 )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Hashed ¶
type Hashed struct { // Params contains the hashing parameters. Params *Params `json:"P"` // Salt is the password salt (Nonce S) of length Params.SaltLen. // The salt should be unique for each password. Salt []byte `json:"S"` // Key is the hashed password (Tag) of length Params.KeyLen. Key []byte `json:"K"` }
Hashed contains the hashed password key and hashing parameters.
type Option ¶
type Option func(*Params)
Option is a type alias for a function that configures the password hasher.
func WithKeyLen ¶
WithKeyLen overwrites the default length of the returned byte-slice that can be used as cryptographic key (Tag length). It must be an integer number of bytes from 4 to 2^(32)-1. The default value is 32 bytes.
func WithMaxPasswordLength ¶ added in v1.88.0
WithMaxPasswordLength overwrites the default maximum length of the input password (Message string P). It must have a length not greater than 2^(32)-1 bytes.
func WithMemory ¶
WithMemory overwrites the default size of the memory in KiB. It must be an integer number of kibibytes from 8*p to 2^(32)-1. The actual number of blocks is m', which is m rounded down to the nearest multiple of 4*p.
func WithMinPasswordLength ¶ added in v1.88.0
WithMinPasswordLength overwrites the default maximum length of the input password (Message string P). It must have a length not greater than 2^(32)-1 bytes.
func WithSaltLen ¶
WithSaltLen overwrites the default length of the random password salt (Nonce S). It must be not greater than 2^(32)-1 bytes. The value of 16 bytes is recommended for password hashing.
func WithThreads ¶
WithThreads overwrites the default number ot threads (p) Threads represents the degree of parallelism p that determines how many independent (but synchronizing) computational chains (lanes) can be run. According to the RFC9106 it must be an integer value from 1 to 2^(24)-1, but in this implementation is limited to 2^(8)-1.
type Params ¶
type Params struct { // Algo is the algorithm used to hash the password. // It corresponds to Type y=2. Algo string `json:"A"` // Version is the algorithm version. Version uint8 `json:"V"` // KeyLen is the length of the returned byte-slice that can be used as cryptographic key (Tag length). // It must be an integer number of bytes from 4 to 2^(32)-1. KeyLen uint32 `json:"K"` // SaltLen is the length of the random password salt (Nonce S). // It must be not greater than 2^(32)-1 bytes. // The value of 16 bytes is recommended for password hashing. SaltLen uint32 `json:"S"` // Time (t) is the default number of passes over the memory. // It must be an integer value from 1 to 2^(32)-1. Time uint32 `json:"T"` // Memory is the size of the memory in KiB. // It must be an integer number of kibibytes from 8*p to 2^(32)-1. // The actual number of blocks is m', which is m rounded down to the nearest multiple of 4*p. Memory uint32 `json:"M"` // Threads (p) is the degree of parallelism p that determines how many independent // (but synchronizing) computational chains (lanes) can be run. // According to the RFC9106 it must be an integer value from 1 to 2^(24)-1, // but in this implementation is limited to 2^(8)-1. Threads uint8 `json:"P"` // contains filtered or unexported fields }
Params contains the parameters for hashing the password.
func (*Params) EncryptPasswordHash ¶
EncryptPasswordHash extends the PasswordHash method by encrypting the password hash using the provided key (pepper). As the key is not stored along the password hash, it provides an additional layer of protection.
func (*Params) EncryptPasswordVerify ¶
EncryptPasswordVerify extends the PasswordVerify method by decrypting the password hash using the provided key (pepper).
Example ¶
package main import ( "fmt" "log" "github.com/Vonage/gosrvlib/pkg/passwordhash" ) func main() { opts := []passwordhash.Option{ passwordhash.WithKeyLen(32), passwordhash.WithSaltLen(16), passwordhash.WithTime(3), passwordhash.WithMemory(16_384), passwordhash.WithThreads(1), passwordhash.WithMinPasswordLength(16), passwordhash.WithMaxPasswordLength(128), } p := passwordhash.New(opts...) key := []byte("0123456789012345") secret := "Example-Password-02" hash, err := p.EncryptPasswordHash(key, secret) if err != nil { log.Fatal(err) } ok, err := p.EncryptPasswordVerify(key, secret, hash) if err != nil { log.Fatal(err) } fmt.Println(ok) ok, err = p.EncryptPasswordVerify(key, "Example-Wrong-Password-02", hash) if err != nil { log.Fatal(err) } fmt.Println(ok) }
Output: true false
func (*Params) PasswordHash ¶
PasswordHash generates a hashed password using the provided password string. It generates a random salt of length ph.SaltLen and uses the argon2id algorithm to hash the password with the salt, using the parameters specified in ph. The resulting hashed password, the salt and the parameters are returned as a json encoded as a base64 string.
func (*Params) PasswordVerify ¶
PasswordVerify verifies if a given password matches a hashed password generated with the PasswordHash method. It returns true if the password matches the hashed password, otherwise false.
Example ¶
package main import ( "fmt" "log" "github.com/Vonage/gosrvlib/pkg/passwordhash" ) func main() { opts := []passwordhash.Option{ passwordhash.WithKeyLen(32), passwordhash.WithSaltLen(16), passwordhash.WithTime(3), passwordhash.WithMemory(16_384), passwordhash.WithThreads(1), passwordhash.WithMinPasswordLength(16), passwordhash.WithMaxPasswordLength(128), } p := passwordhash.New(opts...) secret := "Example-Password-01" hash, err := p.PasswordHash(secret) if err != nil { log.Fatal(err) } ok, err := p.PasswordVerify(secret, hash) if err != nil { log.Fatal(err) } fmt.Println(ok) ok, err = p.PasswordVerify("Example-Wrong-Password-01", hash) if err != nil { log.Fatal(err) } fmt.Println(ok) }
Output: true false