Go package to facilitate the use of the Argon2id password hashing algorithm from the "crypto/argon2" package. This package is tested compatibilities with PHP, Python and C implementations.
Note
As of v1.6.0, the library defaults use the RFC 9106 SECOND RECOMMENDED parameters (Argon2id, t=3, m=64 MiB, p=4, salt=16 bytes, key=32 bytes).
- For details see issue #69
# Install the module go get "github.com/KEINOS/go-argonize"// Import the package import "github.com/KEINOS/go-argonize"func Example_basic() { // Your strong and unpredictable password password := []byte("my password") // Password-hash your password. // // By default it uses RFC 9106 SECOND RECOMMENDED parameters with // cryptographically random SALT. // The `Hash` function will produce different hashes. If you need // a static output, use `HashCustom` function with a fixed salt. hashedObj, err := argonize.Hash(password) if err != nil { log.Fatal(err) } // View the hashed password fmt.Println("Passwd to save:", hashedObj.String()) // Verify password (golden case) if hashedObj.IsValidPassword([]byte("my password")) { fmt.Println("the password is valid") } else { fmt.Println("the password is invalid") } // Verify password (wrong case) if hashedObj.IsValidPassword([]byte("wrong password")) { fmt.Println("the password is valid") } else { fmt.Println("the password is invalid") } // // Output: // Passwd to save: $argon2id$v=19$m=65536,t=3,p=4$ek6ZYdlRm2D5AsGV98TWKA$QAIDZEdIgwohrNX678mHc448LOmD7jGR4BGw/9YMMVU // the password is valid // the password is invalid }func Example_from_saved_password() { // Load the hashed password from a file, DB or etc. // Note that once hashed, passwords cannot be recovered from it and can only // be used to verify. savedPasswd := "$argon2id$v=19$m=65536,t=1,p=2$iuIIXq4foOhcGUH1BjE08w$kA+XOAMls8hzWg3J1sYxkeuK/lkU4HDRBf0zchdyllY" // Decode the saved password to an `argonize.Hashed` object. hashObj, err := argonize.DecodeHashStr(savedPasswd) if err != nil { log.Fatal(err) } // Validate the password against the hashed password. if hashObj.IsValidPassword([]byte("my password")) { fmt.Println("the password is valid") } else { fmt.Println("the password is invalid") } if hashObj.IsValidPassword([]byte("wrong password")) { fmt.Println("the password is valid") } else { fmt.Println("the password is invalid") } // // Output: // the password is valid // the password is invalid }By default, the library uses the RFC 9106 SECOND RECOMMENDED parameters (argonize.RFC9106SecondRecommended preset).
This example uses the RFC 9106 FIRST RECOMMENDED preset for hashing. Which uses less iteration but requires more memory.
func Example_hashcustom_firstrecommended() { // Your strong and unpredictable password password := []byte("my password") // Use the RFC 9106 FIRST RECOMMENDED preset for hashing. // Note that this preset requires more memory than the default // parameters. params := argonize.RFC9106FirstRecommended // Generate a salt with the preset's salt length. // // HashCustom requires a random salt to prevent rainbow table attacks and to // ensure that users with the same password cannot be distinguished. // For consistency during testing, use a fixed salt value. salt, err := argonize.NewSalt(params.SaltLength) if err != nil { log.Fatal(err) } // Hash using the preset parameters. hashedObj := argonize.HashCustom(password, salt, params) // Validate the password against the hashed password. if hashedObj.IsValidPassword([]byte("my password")) { fmt.Println("the password is valid") } else { fmt.Println("the password is invalid") } if hashedObj.IsValidPassword([]byte("wrong password")) { fmt.Println("the password is valid") } else { fmt.Println("the password is invalid") } // // Output: // the password is valid // the password is invalid }This example shows how to tweak parameters starting from defaults and use argonize.HashCustom with user-defined Params.
func Example_custom_user_defined_params() { password := []byte("my password") // Start from defaults and tweak values for this example. params := argonize.NewParams() params.Iterations = 2 params.KeyLength = 32 params.MemoryCost = 32 * 1024 // 32 MiB in KiB params.SaltLength = 16 params.Parallelism = 2 // HashCustom requires a random salt to prevent rainbow table attacks and to // ensure that users with the same password cannot be distinguished. salt, err := argonize.NewSalt(params.SaltLength) if err != nil { log.Fatal(err) } hashedObj := argonize.HashCustom(password, salt, params) if hashedObj.IsValidPassword([]byte("my password")) { fmt.Println("the password is valid") } else { fmt.Println("the password is invalid") } if hashedObj.IsValidPassword([]byte("wrong password")) { fmt.Println("the password is valid") } else { fmt.Println("the password is invalid") } // // Output: // the password is valid // the password is invalid }- View more examples and advanced usages @ pkg.go.dev
- Q: Can I recover the original password from the hashed password?
- A: No. Note that once hashed, passwords cannot be recovered and can only be used to verify.
Any Pull-Request for improvement is welcome!
- Branch to PR:
main - CIs on PR/Push:
- unit-tests
- Inclues compatibility tests against PHP, Python and C implementations
- golangci-lint
- platform-tests
- Tests on Win, macOS and Linux
- codeQL-analysis
- unit-tests
- Our Security Policy
- MIT, Copyright (c) 2022 KEINOS and the go-Argonize contributors.
- This Go package is strongly influenced by an article by Alex Edwards.