crunchy

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Apr 10, 2020 License: MIT Imports: 16 Imported by: 40

README

crunchy

Latest Release GoDoc Build Status Coverage Status Go ReportCard

Finds common flaws in passwords. Like cracklib, but written in Go.

Detects:

  • ErrEmpty: Empty passwords
  • ErrTooShort: Too short passwords
  • ErrTooFewChars: Too few different characters, like "aabbccdd"
  • ErrTooSystematic: Systematic passwords, like "abcdefgh" or "87654321"
  • ErrDictionary: Passwords from a dictionary / wordlist
  • ErrMangledDictionary: Mangled / reversed passwords, like "p@ssw0rd" or "drowssap"
  • ErrHashedDictionary: Hashed dictionary words, like "5f4dcc3b5aa765d61d8327deb882cf99" (the md5sum of "password")
  • ErrFoundHIBP: Optional hash checks against the haveibeenpwned.com database

Your system dictionaries from /usr/share/dict will be indexed. If no dictionaries were found, crunchy only relies on the regular sanity checks (ErrEmpty, ErrTooShort, ErrTooFewChars and ErrTooSystematic). On Ubuntu it is recommended to install the wordlists distributed with cracklib-runtime, on macOS you can install cracklib-words from brew. You could also install various other language dictionaries or wordlists, e.g. from skullsecurity.org.

crunchy uses the WagnerFischer algorithm to find mangled passwords in your dictionaries.

Installation

Make sure you have a working Go environment (Go 1.2 or higher is required). See the install instructions.

To install crunchy, simply run:

go get github.com/muesli/crunchy

Example

package main

import (
	"github.com/muesli/crunchy"
	"fmt"
)

func main() {
    validator := crunchy.NewValidator()

    err := validator.Check("12345678")
    if err != nil {
        fmt.Printf("The password '12345678' is considered unsafe: %v\n", err)
    }

    err = validator.Check("p@ssw0rd")
    if dicterr, ok := err.(*crunchy.DictionaryError); ok {
        fmt.Printf("The password 'p@ssw0rd' is too similar to dictionary word '%s' (distance %d)\n",
            dicterr.Word, dicterr.Distance)
    }

    err = validator.Check("d1924ce3d0510b2b2b4604c99453e2e1")
    if err == nil {
        // Password is considered acceptable
        ...
    }
}

Custom Options

package main

import (
	"github.com/muesli/crunchy"
	"fmt"
)

func main() {
    validator := crunchy.NewValidatorWithOpts(crunchy.Options{
        // MinLength is the minimum length required for a valid password
        // (must be >= 1, default is 8)
        MinLength: 10,

        // MinDiff is the minimum amount of unique characters required for a valid password
        // (must be >= 1, default is 5)
        MinDiff: 8,

        // MinDist is the minimum WagnerFischer distance for mangled password dictionary lookups
        // (must be >= 0, default is 3)
        MinDist: 4,

        // Hashers will be used to find hashed passwords in dictionaries
        Hashers: []hash.Hash{md5.New(), sha1.New(), sha256.New(), sha512.New()},

        // DictionaryPath contains all the dictionaries that will be parsed
        // (default is /usr/share/dict)
        DictionaryPath: "/var/my/own/dicts",

	// Check haveibeenpwned.com database
	// Default is false
	CheckHIBP: true,
    })
    ...
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrEmpty gets returned when the password is empty or all whitespace
	ErrEmpty = errors.New("Password is empty or all whitespace")
	// ErrTooShort gets returned when the password is not long enough
	ErrTooShort = errors.New("Password is too short")
	// ErrTooFewChars gets returned when the password does not contain enough unique characters
	ErrTooFewChars = errors.New("Password does not contain enough different/unique characters")
	// ErrTooSystematic gets returned when the password is too systematic (e.g. 123456, abcdef)
	ErrTooSystematic = errors.New("Password is too systematic")
	// ErrDictionary gets returned when the password is found in a dictionary
	ErrDictionary = errors.New("Password is too common / from a dictionary")
	// ErrMangledDictionary gets returned when the password is mangled, but found in a dictionary
	ErrMangledDictionary = errors.New("Password is mangled, but too common / from a dictionary")
	// ErrHashedDictionary gets returned when the password is hashed, but found in a dictionary
	ErrHashedDictionary = errors.New("Password is hashed, but too common / from a dictionary")
	// ErrFoundHIBP gets returned when the password has been found on https://haveibeenpwned.com
	ErrFoundHIBP = errors.New("Password has been found inside haveibeenpwned.com database")
)
View Source
var HttpClient = &http.Client{
	Transport: &http.Transport{
		Dial: (&net.Dialer{
			Timeout: 30 * time.Second,
		}).Dial,
		ResponseHeaderTimeout: 10 * time.Second,
	},
}

Functions

This section is empty.

Types

type DictionaryError

type DictionaryError struct {
	Err      error
	Word     string
	Distance int
}

DictionaryError wraps an ErrMangledDictionary with contextual information

func (*DictionaryError) Error

func (e *DictionaryError) Error() string

type HashedDictionaryError

type HashedDictionaryError struct {
	Err  error
	Word string
}

HashedDictionaryError wraps an ErrHashedDictionary with contextual information

func (*HashedDictionaryError) Error

func (e *HashedDictionaryError) Error() string

type Options

type Options struct {
	// MinLength is the minimum length required for a valid password (>=1, default is 8)
	MinLength int
	// MinDiff is the minimum amount of unique characters required for a valid password (>=1, default is 5)
	MinDiff int
	// MinDist is the minimum WagnerFischer distance for mangled password dictionary lookups (>=0, default is 3)
	MinDist int
	// Hashers will be used to find hashed passwords in dictionaries
	Hashers []hash.Hash
	// DictionaryPath contains all the dictionaries that will be parsed (default is /usr/share/dict)
	DictionaryPath string
	// Check haveibeenpwned.com database
	CheckHIBP bool
}

Options contains all the settings for a Validator

type Validator

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

Validator is used to setup a new password validator with options and dictionaries

func NewValidator

func NewValidator() *Validator

NewValidator returns a new password validator with default settings

func NewValidatorWithOpts

func NewValidatorWithOpts(options Options) *Validator

NewValidatorWithOpts returns a new password validator with custom settings

func (*Validator) Check

func (v *Validator) Check(password string) error

Check validates a password for common flaws It returns nil if the password is considered acceptable.

func (*Validator) Rate added in v0.2.0

func (v *Validator) Rate(password string) (uint, error)

Rate grades a password's strength from 0 (weak) to 100 (strong).

Jump to

Keyboard shortcuts

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