Skip to content

godeh/passgo

Repository files navigation

passgo

passgo is a zero-dependency Go library for password validation with a small API, predictable performance, estimated entropy, reusable blacklists, and optional user-context checks with prepared reuse support.

Design goals

  • zero external dependencies
  • fast path for ASCII passwords
  • configurable password policies
  • detailed validation output when needed
  • concurrency-safe validator instances

Architecture

The library is intentionally small and split into a few focused pieces:

  • Policy: declarative password requirements
  • Context: optional user-specific data such as name, email, or domain
  • PreparedContext: reusable compiled form of Context for hot paths
  • Validator: compiled, immutable validator that can be reused across goroutines
  • Violation: bitmask for the fast validation path
  • Result: detailed output with counts, estimated entropy, patterns, and human-readable issues
  • Entropy: helper for standalone entropy estimation
  • Blacklist: reusable compiled blacklist
  • Option: optional features such as attaching a blacklist

Validation works in one scan of the password. For ASCII-only passwords it stays on a byte-oriented fast path; if non-ASCII bytes are found it falls back to rune-aware scanning using the standard library only.

Check only computes the analyses required by the active policy. Analyze always computes the full detailed result. Validate is kept as a convenience alias for Analyze.

Supported rules

  • minimum and maximum length
  • minimum lowercase letters
  • minimum uppercase letters
  • minimum digits
  • minimum symbols
  • minimum estimated entropy
  • maximum repeated-character run
  • maximum sequential run for ASCII letters and digits
  • maximum keyboard-pattern run for rows such as qwerty, asdf, zxcvbn, and !@#$
  • whitespace policies: deny any, deny leading/trailing, ignore for entropy
  • optional case-insensitive exact blacklist
  • optional rejection of substrings derived from Context.UserData
  • optional ASCII-only enforcement

Install

go get github.com/godeh/passgo

Usage

package main

import (
	"fmt"

	"github.com/godeh/passgo"
)

func main() {
	blacklist := passgo.NewBlacklist("password123!", "admin123!")

	validator := passgo.Must(passgo.Policy{
		MinLength:             12,
		MinLower:              2,
		MinUpper:              1,
		MinDigits:             2,
		MinSymbols:            1,
		MinEntropyBits:        45,
		MaxRepeatedRun:        2,
		MaxSequentialRun:      3,
		MaxKeyboardPatternRun: 3,
		WhitespacePolicy:      passgo.WhitespaceDenyLeadingOrTrailing | passgo.WhitespaceIgnoreForEntropy,
		RejectUserData:        true,
	}, passgo.WithCompiledBlacklist(blacklist))

	result := validator.AnalyzeWithContext("S7r!xQ2#Lm9$", passgo.Context{
		UserData: []string{"raul", "raul@example.com"},
	})

	fmt.Println(result.Valid)
	fmt.Println(result.EstimatedEntropyBits)
	fmt.Println(result.Violations)
	fmt.Println(result.HasCode(passgo.CodeContainsUserData))
}

Use Check when you only need the bitmask:

mask := validator.CheckWithContext("S7r!xQ2#Lm9$", passgo.Context{
	UserData: []string{"raul"},
})
if mask.Has(passgo.ViolationMissingSymbols) {
	// handle error
}

When the same user data is reused many times, prepare it once:

prepared := validator.PrepareContext(passgo.Context{
	UserData: []string{"raul", "raul@example.com"},
})

mask := validator.CheckWithPreparedContext("S7r!xQ2#Lm9$", prepared)
result := validator.AnalyzeWithPreparedContext("S7r!xQ2#Lm9$", prepared)

_ = mask
_ = result

Use Analyze when you want the full report explicitly:

result := validator.Analyze("pass 123!")
for _, issue := range result.Issues() {
	fmt.Println(issue.Code, issue.Message)
}

Entropy model

passgo estimates entropy from the observed character classes and applies lightweight penalties for low uniqueness, repeated runs, sequential runs, and keyboard patterns. The result is intentionally lightweight and deterministic, suitable for policy checks and coarse strength scoring.

It is an estimate, not a promise about real-world crack resistance.

Whitespace can optionally be ignored for entropy calculations via WhitespaceIgnoreForEntropy.

Stable issue codes

Every human-readable issue also carries a stable machine-readable IssueCode, for example:

  • too_short
  • missing_upper
  • keyboard_pattern_too_long
  • whitespace_not_allowed
  • contains_user_data

This makes it easier to integrate passgo with APIs and frontends without relying on free-form error messages.

Examples

See the practical examples in:

  • examples/basic
  • examples/entropy
  • examples/blacklist
  • examples/context
  • examples/http
  • examples/issues
  • examples/patterns
  • examples/presets
  • examples/whitespace

Roadmap ideas

  • localized issue messages
  • custom rule hooks outside the hot path

About

passgo is a zero-dependency Go library for password validation with a small API, predictable performance, estimated entropy, reusable blacklists, and optional user-context checks with prepared reuse support.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages