Documentation
¶
Overview ¶
Package algorithms defines an interface for password hashing algorithms and provides implementations of several popular algorithms using this interface.
The following algorithms are implemented:
Custom Algorithms ¶
The library is extensible, allowing custom algorithms to be registered with Add. Algorithms must implement the Algorithm interface.
If you are viewing this documentation on pkg.go.dev, a minimal example is provided below.
Example (CustomAlgorithm) ¶
package main
import (
"fmt"
"slices"
"strings"
"codefloe.com/binanary/passgo"
"codefloe.com/binanary/passgo/algorithms"
)
const PlaintextID algorithms.AlgID = "plaintext"
const plaintextHashID algorithms.HashID = "plain"
type Plaintext struct {
Reversed bool
}
func (p Plaintext) ApplyDefaults() (algorithms.AlgID, algorithms.Algorithm) {
return PlaintextID, p
}
func (h Plaintext) RawHash(password []byte, salt []byte) (hash []byte, err error) {
return password, nil
}
func (h Plaintext) Encode(rawHash []byte, salt []byte) (encodedHash string) {
if h.Reversed {
slices.Reverse(rawHash)
}
return fmt.Sprintf("$%s$r=%t$%s", plaintextHashID, h.Reversed, rawHash)
}
func (h Plaintext) IsOutdated(parsedAlgorithm algorithms.Algorithm) bool {
return true
}
func decodePlaintext(encodedHash string) (alg algorithms.Algorithm, rawHash []byte, salt []byte, err error) {
segments := strings.Split(encodedHash, "$")
if len(segments) != 4 {
return nil, nil, nil, fmt.Errorf("expected 4 segments, got %d", len(segments))
}
var reversed bool
_, err = fmt.Sscanf(segments[2], "r=%t", &reversed)
if err != nil {
return nil, nil, nil, err
}
rawHash = []byte(segments[3])
if reversed {
slices.Reverse(rawHash)
}
return Plaintext{Reversed: reversed}, rawHash, nil, nil
}
func main() {
password := "Hello GoPass"
algorithms.Add(PlaintextID, decodePlaintext, plaintextHashID)
hasher := passgo.NewHasher(Plaintext{Reversed: true}, passgo.HasherOptions{})
hash, err := hasher.Hash(password)
if err != nil {
fmt.Println("error while hashing")
return
}
match, _, err := hasher.Compare(hash, password)
if err != nil {
fmt.Println(err)
fmt.Println("error while comparing")
return
}
if match {
fmt.Printf("password %q matched hash %q", password, hash)
} else {
fmt.Println("failed to match")
return
}
}
Output: password "Hello GoPass" matched hash "$plain$r=true$ssaPoG olleH"
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrDuplicateAlgorithm = errors.New("algorithms: an algorithm with that id already exists")
var ErrNilDecoder = errors.New("algorithms: decoder cannot be nil")
Functions ¶
func Add ¶
func Add(algID AlgID, decoder DecoderFunc, hashIDs ...HashID) error
Add registers a custom algorithm by associating it with a decoder and one or more hashIDs. HashIDs that collide with existing values will overwrite them. HashIDs that include '$' will be skipped.
ErrDuplicateAlgorithm is returned if the AlgID is already in use. ErrNilDecoder is returned if decoder is nil.
func GetDecoder ¶
func GetDecoder(id HashID) (name AlgID, decoder DecoderFunc)
GetDecoder returns the AlgID and DecoderFunc associated with the id. If the id is not recognized, it returns the empty string and a nil.
Types ¶
type AlgID ¶
type AlgID string
AlgID is a unique identifier for an Algorithm.
const Argon2idID AlgID = "argon2id"
const BcryptID AlgID = "bcrypt"
const ScryptID AlgID = "scrypt"
type Algorithm ¶
type Algorithm interface {
// ApplyDefaults replaces zero values with recommended defaults for the configuration parameters of the algorithm.
// This can be a no-op for algorithms that do not hold state.
//
// The returned id must be an AlgID registered using the Add function.
ApplyDefaults() (id AlgID, alg Algorithm)
// RawHash returns the result of running the hashing algorithm on the password.
//
// The returned hash must never be nil unless an error is also returned.
RawHash(password []byte, salt []byte) (hash []byte, err error)
// Encode converts a raw hash and salt into a string suitable for storage and eventual decoding.
// The returned string must start with "$<id>$", where <id> is a HashID registered using the Add function.
Encode(rawHash []byte, salt []byte) (encodedHash string)
// IsOutdated determines whether a hash produced by the parsedAlgorithm is considered outdated (for example, if the work factors are lower).
// parsedAlgorithm is guaranteed to have the same concrete type as the receiver.
IsOutdated(parsedAlgorithm Algorithm) (outdated bool)
}
type Argon2id ¶
type Argon2id struct {
Memory int // The number of blocks used (each is 1 kibibyte). Parameter m in the spec.
Iterations int // The number of passes performed. Parameter t in the spec.
Parallelism int // The number of lanes (threads) used. Parameter p in the spec.
KeyLength int // The length (in bytes) of the raw hash. Parameter T in the spec. This value is not used in determining whether a password is outdated.
}
Argon2id was the winner of the Password Hashing Competition and is standardized by RFC 9106.
Its parameters are described in the inputs and outputs section of the RFC. Leave fields unset to use recommended defaults.
func (Argon2id) ApplyDefaults ¶
func (Argon2id) IsOutdated ¶
type Bcrypt ¶
type Bcrypt struct {
Cost int // The algorithm will run 2^Cost times
}
Bcrypt's parameters are described in the conference paper. Leave fields unset to use recommended defaults.
func (Bcrypt) ApplyDefaults ¶
func (Bcrypt) IsOutdated ¶
type DecoderFunc ¶
DecoderFunc is a function that:
- Rebuilds the Algorithm used to create the encodedHash
- Extracts the rawHash and salt from the encodedHash
type HashID ¶
type HashID string
HashID is an identifier for an Algorithm that may appear in stored hashes. This is the <id> parameter in the PHC string format and the {identifier} in the modular crypt format. The character '$' is not permitted.
type Scrypt ¶
type Scrypt struct {
Memory int // The number of blocks used (each is 1 kibibyte when r=8). Parameter N in the spec.
Blocksize int // The size (in units of 128 bytes) of each block. Parameter r in the spec.
Parallelism int // The number of instances of the mixing function run. Parameter p in the spec.
KeyLength int // The length (in bytes) of the raw hash. Parameter dkLen in the spec. This value is not used in determining whether a password is outdated.
}
Scrypt is standardized by RFC 7914.
Its parameters are described in the parameters section of the RFC. Leave fields unset to use recommended defaults.