passgen

package module
v1.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 25, 2026 License: MIT Imports: 11 Imported by: 0

README

passgen

A deterministic password generator: the same passphrase + salt always produces the same password. Instead of storing passwords, you remember simple passphrases and derive site-specific passwords on demand.

Install

brew install jhot21/tap/passgen

Or with Go:

go install github.com/jhot21/passgen/cmd/passgen@latest

Setup

Set a personal salt. This makes your passwords unique to you — even a trivial passphrase like github produces a completely different result than it would for anyone else.

Generate one with passgen itself:

passgen --no-specials -l 80 somerandomstring
# E9Fz0Fxs1JTND8E6HxJvcLjMJK6ZaH2DjzY8Pmot85mtLwX8Z1QaCCo6sUWrHlP7gavv9aBs3MQ9WPQ1

Then set it in your shell profile (~/.zshrc, ~/.bashrc, etc.):

export PASSGEN_SALT="your-long-random-string-here"

On Windows, set PASSGEN_SALT in System → Advanced System Settings → Environment Variables.

Usage

passgen [passphrase]

Arguments:
    passphrase              input passphrase (prompted if omitted)

Options:
    -v, --version           algorithm version (default: 3)
    -s, --salt              salt, overrides $PASSGEN_SALT
    -l, --length            output length (default: 40, or $PASSGEN_LENGTH)
    -p, --print             print to terminal instead of copying to clipboard
        --no-uppers         exclude uppercase letters
        --no-numbers        exclude digits
        --no-specials       exclude special characters
        --custom-specials   use a custom set of special characters
        --no-ambiguous      exclude visually ambiguous characters (Il1O05S)
        --custom-ambiguous  use a custom set of ambiguous characters to exclude

By default the generated password is copied to the clipboard using the OSC 52 terminal escape sequence. This works over SSH and regardless of display server (X11, Wayland), but requires a supported terminal emulator:

  • Supported: kitty, WezTerm, Ghostty, foot, Alacritty, Windows Terminal, iTerm2 (enable in Preferences → General → "Applications in terminal may access clipboard"), xterm (requires -allow flag or XTerm.allowWindowOps: true)
  • tmux: add set -g set-clipboard on to ~/.tmux.conf
  • Not supported: macOS Terminal.app, GNOME Terminal, and other VTE-based terminals (Terminator, XFCE Terminal, MATE Terminal)

Note this list is not exhaustive or updated regularly, see https://can-i-use-terminal.github.io/features/osc52copy.html for a more up to date list

If your terminal is not supported, use --print and pipe the output instead:

passgen --print github | pbcopy    # macOS
passgen --print github | xclip -selection clipboard  # Linux X11

Examples:

# Generate a password for GitHub (copied to clipboard)
passgen github

# Print instead of copy
passgen --print github

# Site that only allows alphanumeric passwords
passgen --no-specials github

# Site with a restricted special character set
passgen --custom-specials '!@#$' github

# Shorter password
passgen --length 16 github

Algorithms

v3 (default)

passphrase + salt → SHA-256 → 32-byte ChaCha20 key → unlimited deterministic byte stream → output generated in cycles of N characters (where N = number of enabled classes). At the start of each cycle, the class order is shuffled via Fisher-Yates using bytes from the ChaCha20 stream, then one character is sampled from each class using rejection sampling for uniform distribution. Guarantees each enabled class (uppercase, lowercase, digits, specials) appears exactly once per cycle with no modulo bias and no predictable positional pattern.

v2 (legacy)

passphrase + salt → SHA-256 → basex-encoded using the active character set. If the output is too short or missing a required character class, the process repeats with an extended passphrase and the results are concatenated. Use --version 2 to select it.

v1 (legacy)

passphrase + salt → UTF-16 LE → Skein-512 → hex → base91-encoded → substring at a hash-derived offset. Compatible with node-passgen-cli. Use --version 1 to select it.

Environment variables

Variable Description
PASSGEN_SALT Default salt appended to every passphrase
PASSGEN_LENGTH Default output length (overrides the built-in default of 40)

Documentation

Overview

Package passgen generates deterministic passwords from a passphrase and salt. The same passphrase + salt + options always produces the same password.

Example:

pass, err := passgen.New("mypassphrase").WithSalt("mysalt").WithLength(32).Generate()
if err != nil {
    log.Fatal(err)
}
fmt.Println(pass)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

Builder constructs a deterministic password generation request. Use New to create a Builder with sensible defaults.

Builder methods return a new Builder (copy), so a base Builder can be reused safely without mutation:

base := passgen.New("mypassphrase").WithSalt("mysalt")
pass16, _ := base.WithLength(16).Generate()
pass32, _ := base.WithLength(32).Generate()

func New

func New(passphrase string) *Builder

New returns a Builder for the given passphrase with defaults: v3 algorithm, length 40, all character classes enabled, specials = !@#$%^&*. No environment variables are read.

func (*Builder) Generate

func (b *Builder) Generate() (string, error)

Generate produces a deterministic password from the passphrase provided to New.

Returns an error if:

  • The passphrase is empty.
  • The length is less than 1.
  • The version is not 1, 2, or 3.
  • All character classes are disabled (leaving no characters to sample from).
  • (v2) The character set has fewer than 2 characters.
  • (v2) A required character class is filtered away entirely (e.g. by ambiguous-character exclusion).
  • (v2) The length is shorter than the number of required character classes.
  • (v3) A character class is longer than 256 characters.

func (*Builder) NoAmbiguous

func (b *Builder) NoAmbiguous() *Builder

NoAmbiguous excludes the default ambiguous characters (Il1O05S) from the generated password. Use [WithAmbiguousChars] to supply a custom set.

func (*Builder) NoNumbers

func (b *Builder) NoNumbers() *Builder

NoNumbers disables numeric characters in the generated password.

func (*Builder) NoSpecials

func (b *Builder) NoSpecials() *Builder

NoSpecials disables special characters in the generated password entirely.

func (*Builder) NoUppers

func (b *Builder) NoUppers() *Builder

NoUppers disables uppercase letters in the generated password.

func (*Builder) WithAmbiguousChars

func (b *Builder) WithAmbiguousChars(chars string) *Builder

WithAmbiguousChars sets a custom set of characters to exclude as visually ambiguous. Calling this implicitly enables ambiguous filtering. The default ambiguous set (used by [NoAmbiguous]) is "Il1O05S".

func (*Builder) WithLength

func (b *Builder) WithLength(n int) *Builder

WithLength sets the output password length. Must be at least 1. Default: 40.

func (*Builder) WithSalt

func (b *Builder) WithSalt(salt string) *Builder

WithSalt appends a salt to the passphrase before hashing. A unique salt makes passwords specific to a user or context.

func (*Builder) WithSpecials

func (b *Builder) WithSpecials(chars string) *Builder

WithSpecials sets a custom special character set to use instead of the default (!@#$%^&*). Has no effect if [NoSpecials] has been called.

func (*Builder) WithVersion

func (b *Builder) WithVersion(v int) *Builder

WithVersion selects the algorithm version. Valid values: 1, 2, 3. The default (0 or unset) maps to version 3.

Directories

Path Synopsis
cmd
passgen command
internal
goldengen command
Command goldengen prints golden test vectors for ports of passgen v2/v3.
Command goldengen prints golden test vectors for ports of passgen v2/v3.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL