passlib

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2020 License: BSD-3-Clause Imports: 10 Imported by: 0

README

passlib for go

GoDoc Build Status

Python's passlib is quite an amazing library. I'm not sure there's a password library in existence with more thought put into it, or with more support for obscure password formats.

This is a skeleton of a port of passlib to Go. It dogmatically adopts the modular crypt format, which passlib has excellent documentation for.

Currently, it supports:

  • Argon2i
  • scrypt-sha256
  • sha512-crypt
  • sha256-crypt
  • bcrypt
  • passlib's bcrypt-sha256 variant
  • pbkdf2-sha512 (in passlib format)
  • pbkdf2-sha256 (in passlib format)
  • pbkdf2-sha1 (in passlib format)

By default, it will hash using scrypt-sha256 and verify existing hashes using any of these schemes.

Example Usage

There's a default context for ease of use. Most people need only concern themselves with the functions Hash and Verify:

// Hash a plaintext, UTF-8 password.
func Hash(password string) (hash string, err error)

// Verifies a plaintext, UTF-8 password using a previously derived hash.
// Returns non-nil err if verification fails.
//
// Also returns an upgraded password hash if the hash provided is
// deprecated.
func Verify(password, hash string) (newHash string, err error)

Here's a rough skeleton of typical usage.

import "github.com/al45tair/passlib"

func RegisterUser() {
  (...)

  password := get a (UTF-8, plaintext) password from somewhere

  hash, err := passlib.Hash(password)
  if err != nil {
    // couldn't hash password for some reason
    return
  }

  (store hash in database, etc.)
}

func CheckPassword() bool {
  password := get the password the user entered
  hash := the hash you stored from the call to Hash()

  newHash, err := passlib.Verify(password, hash)
  if err != nil {
    // incorrect password, malformed hash, etc.
    // either way, reject
    return false
  }

  // The context has decided, as per its policy, that
  // the hash which was used to validate the password
  // should be changed. It has upgraded the hash using
  // the verified password.
  if newHash != "" {
    (store newHash in database, replacing old hash)
  }

  return true
}

scrypt Modular Crypt Format

Since scrypt does not have a pre-existing modular crypt format standard, I made one. It's as follows:

$s2$N$r$p$salt$hash

...where N, r and p are the respective difficulty parameters to scrypt as positive decimal integers without leading zeroes, and salt and hash are base64-encoded binary strings. Note that the RFC 4648 base64 encoding is used (not the one used by sha256-crypt and sha512-crypt).

Licence

passlib is partially derived from Python's passlib and so maintains its BSD license. This version of passlib was forked from Hugo Landau's by Alastair Houghton.

© 2008-2012 Assurance Technologies LLC.  (Python passlib) - BSD License
© 2014 Hugo Landau <hlandau@devever.net> - BSD License
© 2020 Alastair Houghton <alastair@alastairs-place.net> - BSD License
© 2020 World Programming Limited - BSD License

Documentation

Overview

Package passlib provides a simple password hashing and verification interface abstracting multiple password hashing schemes.

After initialisation, most people need concern themselves only with the functions Hash and Verify, which uses the default context and sensible defaults.

Library Initialization

You should initialise the library before using it with the following line.

// Call this at application startup.
passlib.UseDefaults(passlib.Defaults20180601)

See func UseDefaults for details.

Index

Examples

Constants

View Source
const Defaults20160922 = "20160922"

This is the first and default set of defaults used by passlib. It prefers scrypt-sha256. It is now obsolete.

View Source
const Defaults20180601 = "20180601"

This is the most up-to-date set of defaults preferred by passlib. It prefers Argon2i. You must opt into it by calling UseDefaults at startup.

View Source
const DefaultsLatest = "latest"

This value, when passed to UseDefaults, causes passlib to always use the very latest set of defaults. DO NOT use this unless you are sure that opportunistic hash upgrades will not cause breakage for your application when future versions of passlib are released. See func UseDefaults.

Variables

View Source
var DefaultSchemes []abstract.Scheme

The default schemes, most preferred first. The first scheme will be used to hash passwords, and any of the schemes may be used to verify existing passwords. The contents of this value may change with subsequent releases.

If you want to change this, set DefaultSchemes to a slice to an abstract.Scheme array of your own construction, rather than mutating the array the slice points to.

To see the default schemes used in the current release of passlib, see default.go. See also the UseDefaults function for more information on how the list of default schemes is determined. The default value of DefaultSchemes (the default defaults) won't change; you need to call UseDefaults to allow your application to upgrade to newer hashing schemes (or set DefaultSchemes manually, or create a custom context with its own schemes set).

Functions

func DefaultSchemesFromDate added in v1.1.0

func DefaultSchemesFromDate(date string) ([]abstract.Scheme, error)

Return the schemes corresponding to the specified date string

func Hash

func Hash(password string) (hash string, err error)

Hashes a UTF-8 plaintext password using the default context and produces a password hash. Chooses the preferred password hashing scheme based on the configured policy. The default policy is sensible.

Example (Signup)

User signup example.

// User signup example.
// NOTE: Call UseDefaults at application initialisation time to initialise
// passlib before using Hash() or Verify(). See func UseDefaults.

// ... signup code ...

// Get the password the user chose by whatever means.
password := getSignupPassword()
username := getSignupUsername()

hash, err := Hash(password)
if err != nil {
	// couldn't hash password for some reason
	return
}

// hash now contains a hash in modular crypt form.
// Store hash in database, etc.
storeHashInDatabase(username, hash)
Output:

func NeedsUpdate

func NeedsUpdate(stub string) bool

Uses the default context to determine whether a stub or hash needs updating.

func SchemeFromName added in v1.1.0

func SchemeFromName(schemeName string) abstract.Scheme

Convert a scheme name into a scheme

func SchemesFromNames added in v1.1.0

func SchemesFromNames(schemeNames []string) ([]abstract.Scheme, error)

Convert a list of scheme names into a list of schemes

func UseDefaultSchemes added in v1.1.0

func UseDefaultSchemes(schemeNames []string) error

Set the default schemes using a list of scheme names, rather than a date

func UseDefaults added in v1.0.10

func UseDefaults(date string) error

It is strongly recommended that you DO NOT use this function, and that you instead always create a passlib.Context and call the methods of that struct, because the latter does not involve global behaviour.

func Verify

func Verify(password, hash string) (newHash string, err error)

Verifies a UTF-8 plaintext password using a previously derived password hash and the default context. Returns nil err only if the password is valid.

If the hash is determined to be deprecated based on policy, and the password is valid, the password is hashed using the preferred password hashing scheme and returned in newHash. You should use this to upgrade any stored password hash in your database.

newHash is empty if the password was invalid or no upgrade is required.

You should treat any non-nil err as a password verification error.

Example (Login)

User login example.

// User login example.
// NOTE: Call UseDefaults at application initialisation time to initialise
// passlib before using Hash() or Verify(). See func UseDefaults.

// Get the password for the user we have stored in the database.
hash := getUserHashFromDatabase()

// Get the plaintext password the user tried to login with.
password := getLoginPassword()

newHash, err := Verify(password, hash)
if err != nil {
	// Incorrect password, malformed hash, etc.
	return
}

if newHash != "" {
	// passlib thinks we should upgrade to a new stronger hash.
	// ... store the new hash in the database ...
}

// ... log the user in ...
Output:

func VerifyNoUpgrade added in v1.0.7

func VerifyNoUpgrade(password, hash string) error

Like Verify, but never upgrades.

Types

type Context

type Context struct {
	// Slice of schemes to use, most preferred first.
	//
	// If left uninitialized, a sensible default set of schemes will be used.
	//
	// An upgrade hash (see the newHash return value of the Verify method of the
	// abstract.Scheme interface) will be issued whenever a password is validated
	// using a scheme which is not the first scheme in this slice.
	Schemes []abstract.Scheme
}

A password hashing context, that uses a given set of schemes to hash and verify passwords.

var DefaultContext Context

The default context, which uses sensible defaults. Most users should not reconfigure this. The defaults may change over time, so you may wish to reconfigure the context or use a custom context if you want precise control over the hashes used.

func (*Context) Hash

func (ctx *Context) Hash(password string) (hash string, err error)

Hashes a UTF-8 plaintext password using the context and produces a password hash.

If stub is "", one is generated automaticaly for the preferred password hashing scheme; you should specify stub as "" in almost all cases.

The provided or randomly generated stub is used to deterministically hash the password. The returned hash is in modular crypt format.

If the context has not been specifically configured, a sensible default policy is used. See the fields of Context.

func (*Context) NeedsUpdate

func (ctx *Context) NeedsUpdate(stub string) bool

Determines whether a stub or hash needs updating according to the policy of the context.

func (*Context) Verify

func (ctx *Context) Verify(password, hash string) (newHash string, err error)

Verifies a UTF-8 plaintext password using a previously derived password hash and the default context. Returns nil err only if the password is valid.

If the hash is determined to be deprecated based on the context policy, and the password is valid, the password is hashed using the preferred password hashing scheme and returned in newHash. You should use this to upgrade any stored password hash in your database.

newHash is empty if the password was not valid or if no upgrade is required.

You should treat any non-nil err as a password verification error.

func (*Context) VerifyNoUpgrade added in v1.0.7

func (ctx *Context) VerifyNoUpgrade(password, hash string) error

Like Verify, but does not hash an upgrade password when upgrade is required.

Directories

Path Synopsis
Package abstract contains the abstract description of the Scheme interface, plus supporting error definitions.
Package abstract contains the abstract description of the Scheme interface, plus supporting error definitions.
hash
argon2
Package argon2 implements the argon2 password hashing mechanism, wrapped in the argon2 encoded format.
Package argon2 implements the argon2 password hashing mechanism, wrapped in the argon2 encoded format.
argon2/raw
Package raw provides a raw implementation of the modular-crypt-wrapped Argon2i primitive.
Package raw provides a raw implementation of the modular-crypt-wrapped Argon2i primitive.
bcrypt
Package bcrypt implements the bcrypt password hashing mechanism.
Package bcrypt implements the bcrypt password hashing mechanism.
bcryptsha256
Package bcryptsha256 implements bcrypt with a SHA256 prehash in a format that is compatible with Python passlib's equivalent bcrypt-sha256 scheme.
Package bcryptsha256 implements bcrypt with a SHA256 prehash in a format that is compatible with Python passlib's equivalent bcrypt-sha256 scheme.
pbkdf2
Package pbkdf2 implements a modular crypt format for PBKDF2-SHA1, PBKDF2-SHA256 and PBKDF-SHA512.
Package pbkdf2 implements a modular crypt format for PBKDF2-SHA1, PBKDF2-SHA256 and PBKDF-SHA512.
scrypt
Package scrypt implements the scrypt password hashing mechanism, wrapped in the modular crypt format.
Package scrypt implements the scrypt password hashing mechanism, wrapped in the modular crypt format.
scrypt/raw
Package raw provides a raw implementation of the modular-crypt-wrapped scrypt primitive.
Package raw provides a raw implementation of the modular-crypt-wrapped scrypt primitive.
sha2crypt
Package sha2crypt implements sha256-crypt and sha512-crypt.
Package sha2crypt implements sha256-crypt and sha512-crypt.
sha2crypt/raw
Package raw provides a raw implementation of the sha256-crypt and sha512-crypt primitives.
Package raw provides a raw implementation of the sha256-crypt and sha512-crypt primitives.

Jump to

Keyboard shortcuts

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