password: github.com/klauspost/password Index | Examples | Files | Directories

package password

import "github.com/klauspost/password"

Dictionary Password Validation for Go

For usage and examples see: https://github.com/klauspost/password (or open the README.md)

This library will help you import a password dictionary and will allow you to validate new/changed passwords against the dictionary.

You are able to use your own database and password dictionary. Currently the package supports importing dictionaries similar to CrackStation's Password Cracking Dictionary: https://crackstation.net/buy-crackstation-wordlist-password-cracking-dictionary.htm

It and has "drivers" for various backends, see the "drivers" directory, where there are implementations and a test framework that will help you test your own drivers.

Index

Examples

Package Files

bulk.go password.go

Variables

var BulkMax = 1000

BulkMax is the maximum number of passwords sent at once to the writer. You can change this before starting an import.

var ErrInvalidString = errors.New("invalid utf8 sequence")

ErrInvalidString is returned by the default sanitizer if the string contains an invalid utf8 character sequence.

var ErrPasswordInDB = errors.New("password found in database")

ErrPasswordInDB is returedn by Check, if the password is in the database.

var ErrSanitizeTooShort = errors.New("password too short")

ErrSanitizeTooShort is returned by the default sanitizer, if the input password is less than 8 runes.

var Logger = log.New(os.Stdout, "", log.LstdFlags)

Logger used for output during Import. This can be exchanged with your own.

func Check Uses

func Check(password string, db DB, san Sanitizer) error

Check a password against the database. It will return an error if:

- Sanitazition fails.
- DB lookup returns an error
- Password is in database (ErrPasswordInDB)

If nil is passed as Sanitizer, DefaultSanitizer will be used.

func Import Uses

func Import(in Tokenizer, out DbWriter, san Sanitizer) (err error)

Import will populate a database with common passwords.

You must supply a Tokenizer (see tokenizer package for default tokenizers) that will deliver the passwords, a DbWriter, where the passwords will be sent, and finally a Sanitizer to clean up the passwords - - if you send nil DefaultSanitizer will be used.

Code:

r, err := os.Open("./testdata/testdata.txt.gz")
if err != nil {
    panic("cannot open file")
}
// Create a database to write to
mem := testdb.NewMemDBBulk()

// The input is gzipped text file with
// one input per line, so we choose a tokenizer
// that matches.
in, err := tokenizer.NewGzLine(r)
if err != nil {
    panic(err)
}
// Import using the default sanitizer
err = Import(in, mem, nil)
if err != nil {
    panic(err)
}
// Data is now imported, let's do a check
// Check a password that is in the sample data
err = Check("tl1992rell", mem, nil)
fmt.Println(err)

Output:

password found in database

Open a xz compressed archive and import it. Uses the "xi2.org/x/xz" package to read xz files.

Code:

r, err := os.Open("rockyou.txt.xz")
if err != nil {
    // Fake it
    fmt.Println("Imported", 9341543, "items")
    return
}
xzr, err := xz.NewReader(r, 0)
if err != nil {
    panic(err)
}
mem := testdb.NewMemDBBulk()
in := tokenizer.NewLine(xzr)
err = Import(in, mem, nil)
if err != nil {
    panic(err)
}
fmt.Println("Imported", len(*mem), "items")

Output:

Imported 9341543 items

func Sanitize Uses

func Sanitize(password string, san Sanitizer) (string, error)

Sanitize will sanitize a password, useful before hashing and storing it.

If the sanitizer is nil, DefaultSanitizer will be used.

func SanitizeOK Uses

func SanitizeOK(password string, san Sanitizer) error

SanitizeOK can be used to check if a password passes the sanitizer.

If the sanitizer is nil, DefaultSanitizer will be used.

type BulkWriter Uses

type BulkWriter interface {
    AddMultiple([]string) error
}

If your DbWriter implements this, input will be sent in batches instead of using Add.

type DB Uses

type DB interface {
    Has(string) (bool, error)
}

A DB should check the database for the supplied password. The password sent to the interface has always been sanitized.

type DbWriter Uses

type DbWriter interface {
    Add(string) error
}

A DbWriter is used for adding passwords to a database. Items sent to Add has always been sanitized, however the same passwords can be sent multiple times.

type Sanitizer Uses

type Sanitizer interface {
    Sanitize(string) (string, error)
}

A Sanitizer should prepare a password, and check the basic properties that should be satisfied. For an example, see DefaultSanitizer

var DefaultSanitizer Sanitizer

DefaultSanitizer should be used for adding passwords to the database. Assumes input is UTF8.

DefaultSanitizer performs the following sanitazion:

- Trim space, tab and newlines from start+end of input
- Check that there is at least 8 runes. Return ErrSanitizeTooShort if not.
- Check that the input is valid utf8. Return ErrInvalidString if not.
- Normalize input using Unicode Normalization Form KD

If input is less than 8 runes ErrSanitizeTooShort is returned.

This example shows how to create a custom sanitizer that checks if the password matches the username or email.

CustomSanitizer is defined as:

type CustomSanitizer struct {
    email string
    username string
}

func (c CustomSanitizer) Sanitize(s string) (string, error) {
    s, err := DefaultSanitizer.Sanitize(s)
    if err != nil {
        return "", err
    }
    if strings.EqualFold(s, c.email) {
        return "", errors.New("password cannot be the same as email")
    }
    if strings.EqualFold(s, c.username) {
        return "", errors.New("password cannot be the same as user name")
    }
    return s, nil
}

Code:

// Create a custom sanitizer.
san := CustomSanitizer{email: "john@doe.com", username: "johndoe73"}

// Check some passwords
err := SanitizeOK("john@doe.com", san)
fmt.Println(err)

err = SanitizeOK("JohnDoe73", san)
fmt.Println(err)

err = SanitizeOK("MyP/|$$W0rd", san)
fmt.Println(err)

Output:

password cannot be the same as email
password cannot be the same as user name
<nil>

type Tokenizer Uses

type Tokenizer interface {
    Next() (string, error)
}

Tokenizer delivers input tokens (passwords). Calling Next() should return the next password, and when finished io.EOF should be returned.

It is ok for the Tokenizer to send empty strings and duplicate values.

Directories

PathSynopsis
driversProvides a standard test library for drivers.
drivers/bloompwA bitset Bloom filter for a reduced memory password representation.
drivers/boltpwDriver for BoltDB
drivers/cassandraPackage cassandra is a driver for Apache Cassandra
drivers/mgopwDriver for MongoDB
drivers/sqlpwWrapper for an SQL database backend
drivers/testdbAn in-memory database for testing
tokenizerTokenizers for various formats, that satisfies the password.Tokenizer interface.

Package password imports 8 packages (graph) and is imported by 1 packages. Updated 2016-07-21. Refresh now. Tools for package owners.