passwordhash

package
v1.90.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 20, 2024 License: MIT Imports: 7 Imported by: 0

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

Examples

Constants

View Source
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

func WithKeyLen(v uint32) Option

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

func WithMaxPasswordLength(v uint32) Option

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

func WithMemory(v uint32) Option

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

func WithMinPasswordLength(v uint32) Option

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

func WithSaltLen(v uint32) Option

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

func WithThreads(v uint8) Option

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.

func WithTime

func WithTime(v uint32) Option

WithTime (t) is the default number of passes (iterations) over the memory. It must be an integer value from 1 to 2^(32)-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 New

func New(opts ...Option) *Params

New creates a new instance of Params with the provided options applied.

func (*Params) EncryptPasswordHash

func (ph *Params) EncryptPasswordHash(key []byte, password string) (string, error)

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

func (ph *Params) EncryptPasswordVerify(key []byte, password, hash string) (bool, error)

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

func (ph *Params) PasswordHash(password string) (string, error)

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

func (ph *Params) PasswordVerify(password, hash string) (bool, error)

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL