gopass - Password Utility Library
This Go library, gopass
, provides functions for generating, hashing, validating, and comparing passwords. It prioritizes security by enforcing strong password complexity rules and using Argon2id for password hashing with configurable parameters.
Features:
- Enforces minimum and maximum password length requirements.
- Requires a minimum number of special characters and numeric digits.
- Limits the number of consecutive repeated characters.
- Prevents sequential numeric sequences (e.g., "1234").
- Hashes passwords using the Argon2id algorithm with configurable parameters.
- Generates random passwords.
- Compares plain text passwords against hashed passwords and salts.
- Performs password complexity validation with informative error messages.
Installation:
go get -u github.com/gabbottron/gopass
Usage:
- Import the library:
import (
"fmt"
"github.com/gabbottron/gopass"
)
- Define Password Configuration:
Create a gopass.Config
struct to define your desired password complexity and Argon2 settings:
passSettings := gopass.Config{
MinPassLength: 8, // Minimum password length
MaxPassLength: 22, // Maximum password length
ReqSpecialChars: 1, // Minimum number of special characters
ReqNumbers: 1, // Minimum number of numeric digits
MaxRepeatedChars: 2, // Maximum consecutive repeated characters
MaxNumericSeqLength: 3, // Maximum length of sequential numeric characters
HashTime: 1, // Argon2 iterations (higher is more secure, but slower)
HashMemory: 1024, // Argon2 memory cost in MB
HashThreads: 16, // Argon2 threads (adjust based on CPU cores)
HashKeyLength: 128, // Desired key length from Argon2 (in bytes)
SaltBytes: 128, // Length of random salt for password hashing (in bytes)
}
- Create a gopass Instance:
gp, err := gopass.New(passSettings)
if err != nil {
panic("invalid crypto settings")
}
Password Generation:
// Generate a random URL-safe, base64 encoded password of length 16
newPass, err := gp.GenerateRandomPass(16)
if err != nil {
fmt.Println("Error generating password:", err)
} else {
fmt.Println("New password:", newPass)
}
Password Validation:
userPass := "Pa$$w0rd!" // Example password
err = gp.ValidatePassword(userPass)
if err != nil {
fmt.Println("Invalid password:", err.Error())
} else {
fmt.Println("Password meets complexity requirements")
}
Password Hashing:
hashedPass, salt, err := gp.HashAndSalt(userPass)
if err != nil {
fmt.Println("Error hashing password:", err)
} else {
fmt.Println("Hashed password:", hashedPass)
fmt.Println("Salt:", salt)
}
Password Comparison:
// Assuming hashedPass and salt are obtained from previous hashing
valid := gp.ComparePasswords(hashedPass, salt, userPass)
if valid {
fmt.Println("Password is valid")
} else {
fmt.Println("Password is invalid")
}
Speed Test (Optional):
This function measures the time it takes to hash a specified number of random passwords. It can be helpful for evaluating performance implications of different Argon2 settings.
elapsed := gp.SpeedTest(100, 8, 24) // Test 100 hashes between 8-24 characters
fmt.Printf("Time to hash 100 passwords: %f seconds\n", elapsed)
Important Notes:
- It's crucial to ensure a cryptographically secure random number generator (CSPRNG) is available during library initialization. If unavailable, the program panics to prevent insecure password storage.
- This library is designed for secure password management and should not be used for other purposes where different hashing algorithms might be more suitable.
- Carefully consider the trade-off between security and performance when selecting Argon2 parameters (HashTime, HashMemory, HashThreads).