PHC Password Checker
Go to file
Jon Lundy b00783cb2a
Merge pull request #1 from der-lyse/main
Fix typos and improve code blocks
2022-12-08 19:48:03 -07:00
.github Create codeql.yml 2022-12-08 19:47:12 -07:00
pkg tests: add some more testing around IsPreferred 2022-12-07 17:04:46 -07:00
go.mod chore(deps): bump golang.org/x/crypto from 0.3.0 to 0.4.0 2022-12-09 02:46:42 +00:00
go.sum chore(deps): bump golang.org/x/crypto from 0.3.0 to 0.4.0 2022-12-09 02:46:42 +00:00
LICENSE Create LICENSE 2022-12-07 19:00:29 -07:00
passwd_test.go initial commit 2022-12-07 14:19:04 -07:00
passwd.go fix: handle hash without $ prefix 2022-12-07 18:44:58 -07:00
README.md Fix typos and improve code blocks 2022-12-08 07:29:37 +01:00
SECURITY.md Create SECURITY.md 2022-12-08 19:44:53 -07:00

go-passwd

Its a multi password type checker. Using the PHC string format we can identify a password hashing format from the prefix $name$ and then dispatch the hashing or checking to its specific format.

Example

Here is an example of usage:

func Example() {
	pass := "my_pass"
	hash := "my_pass"

	pwd := passwd.New(
		&unix.MD5{}, // first is preferred type.
		&plainPasswd{},
	)

	_, err := pwd.Passwd(pass, hash)
	if err != nil {
		fmt.Println("fail: ", err)
	}

	// Check if we want to update.
	if !pwd.IsPreferred(hash) {
		newHash, err := pwd.Passwd(pass, "")
		if err != nil {
			fmt.Println("fail: ", err)
		}

		fmt.Println("new hash:", newHash)
	}

	// Output:
	//  new hash: $1$81ed91e1131a3a5a50d8a68e8ef85fa0
}

https://github.com/sour-is/go-passwd/blob/main/passwd_test.go#L33-L59

This shows how one would set a preferred hashing type and if the current version of ones password is not the preferred type updates it to enhance the security of the hashed password when someone logs in.

Fallthrough

Hold up now, that example hash doesnt have a $ prefix!

Well for this there is the option for a hash type to set itself as a fall through if a matching hash doesnt exist. This is good for legacy password types that dont follow the convention.

func (p *plainPasswd) ApplyPasswd(passwd *passwd.Passwd) {
	passwd.Register("plain", p)
	passwd.SetFallthrough(p)
}

https://github.com/sour-is/go-passwd/blob/main/passwd_test.go#L28-L31

Custom Preference Checks

Circling back to the IsPreferred method. A hasher can define its own IsPreferred method that will be called to check if the current hash meets the complexity requirements. This is good for updating the password hashes to be more secure over time.

func (p *Passwd) IsPreferred(hash string) bool {
	_, algo := p.getAlgo(hash)
	if algo != nil && algo == p.d {

		// if the algorithm defines its own check for preference.
		if ck, ok := algo.(interface{ IsPreferred(string) bool }); ok {
			return ck.IsPreferred(hash)
		}

		return true
	}
	return false
}

https://github.com/sour-is/go-passwd/blob/main/passwd.go#L62-L74

Example: https://github.com/sour-is/go-passwd/blob/main/pkg/argon2/argon2.go#L104-L133