mcf

package
v0.0.0-...-a0901ff Latest Latest
Warning

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

Go to latest
Published: Aug 16, 2015 License: GPL-3.0 Imports: 6 Imported by: 0

README

#Description

mcf is a Go library for creating, verifying, upgrading and managing a variety of hashed password schemes.

mcf provides a simple API for applications to use a variety of password hashing schemes, including bcrypt, scrypt, and pbkdf2 as well a management mechanism to easily and transparently set the default password scheme, change schemes, or change scheme parameters such as work factors, salt length, key length without rewriting the application.

In addition to the separation of usage and policy model of the UNIX password mechanism, mcf borrows the /etc/passwd format and generates passwords in the [Modular Crypt Format (MCF)] (http://pythonhosted.org/passlib/modular_crypt_format.html). ,allows for the simultaneous existence of multiple types and generations of passwords. As a text format, it provides for easy database storage and subsequent verification.

Any application would benefit from the simplicity, ease and secure defaults of this package. Applications and web sites that need to support multiple password hashing mechanisms and/or need to allow for different upgrade policies would find it especially useful.

#Install

mcf can be installed with the command:

go get github.com/gyepisam/mcf

#Example

Here is a simple example on how to use mcf to generate pbkdf2 hashed passwords. Note that the same example would work for any other scheme and multiple schemes can exist concurrently.

import "github.com/gyepisam/mcf"
import "github.com/gyepisam/mcf/pbkdf2"

To create a password, assuming you have the username and plaintext variables from a user signup session:

passwd, err := mcf.Create(plaintext)
// error handling elided
// Store passwd in database

To verify a password, assuming you have the username and plaintext variables from a user login session and have retrieved the stored password from the database into the passwd variable:

isValid, err := mcf.Verify(plaintext, passwd)
// error handling elided.

The verification can be combined with automated password upgrades with code like this:

isValid, err := mcf.Verify(plaintext, passwd)
// error handling elided.

if !isValid {
    // fail -- failed password verification
    return false
}

isCurrent, err := mcf.IsCurrent(passwd) 
// error handling elided

if !isCurrent {
  newPasswd, err := mcf.Create(plaintext)
  // error handling elided
  // Update passwd in database
}

// success!

With this method, user passwords will automatically upgrade to use any new schemes or stronger work factors set by policy through the management API.

#Author

mcf is written by Gyepi Sam self-github@gyepi.com and is released under a BSD license.

I am welcome any and all feedback on this software.

-Gyepi Sam

Documentation

Overview

Package mcf is a Go library for creating, verifying, upgrading and managing bcrypt, scrypt, and pbkdf2 password hashes.

mcf provides a simple API for applications to use a variety of password hashing schemes as well a management mechanism to easily and transparently set the default password scheme, change schemes, or change scheme parameters such as work factors, salt length, key length without rewriting the application.

Usage:

Import the mcf package along with at least one encoder. You can import as many encoders as desired. The first encoder is used to encode all new passwords. Subsequent encoders are used to decode. There's an API to set the default encoder.

Note that once an encoder has been superceded (is no longer the first imported encoding) it must not be removed from the import lists until all existing instances of that encoding have either been converted to a newer encoding or invalidated.

import (
  "github.com/gyepisam/mcf"
  "github.com/gyepisam/mcf/scrypt"
)

// A user provides a password at registration or signup.
username, plaintext := "alibaba", "dfj1A4finbfya9BFDL7d"

// Create an encoding using the default
encoded, err := mcf.Create(plaintext)
// error handling elided

// Insert encoded value and user info in database
user = db.NewUser()
user.Username = username
user.Password = encoded
err = user.Save()
// handle errors

To authenticate the user:

// A user provides a password at login.
username, plaintext := "alibaba", "dfj1A4finbfya9BFDL7d"

user, err := db.FindUser("username = $1", username)
// error handling elided

isValid, err := mcf.Verify(plaintext, user.Password)
// error handling elided

When authentication succeeds, it is a useful practice to re-encode the password if it is out of date with respect to current security policy. It is the best possible time (also, the only possible time) to do this, since the plaintext password is available. The final part changes to something like:

if isValid {
  go func(plaintext, encoded, username string) {
        isCurrent, err := mcf.IsCurrent(encoded)
        // error handling elided but assumed to return.
        if !isCurrent {
          encoded, err := mcf.Create(plaintext)
         // Update encoded value in database
        }
  } (plaintext, encoded, user.username)

  // Success
}

The update is handled by a go routine since it would have the least impact on the user experience. However, given its non-interactivity it is especially important to log errors that might occur.

Changing work factors or implementing other policy changes is similarly simple:

func init() {
    config := scrypt.GetConfig()
    config.LgN++ // double the default work factor
    scrypt.SetConfig(config)
}

Later, if you decide to switch to pbkdf2, just import it

_ "github.com/gyepisam/mcf/pbkdf2"

and make sure it is the current encoder.

mcf.SetDefault(mcf.PBKDF2)

All subsequently created password will use the new scheme. If you also use the auto upgrade mechanism, then users will be upgraded upon login as well.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Create

func Create(plaintext string) (encoded string, err error)

Create takes a plaintext password and uses the default encoder to create an encoded password in Modular Crypt Format, which it returns. The application is expected to store this password in order to subsequently verify the plaintext password.

func IsCurrent

func IsCurrent(encoded string) (isCurrent bool, err error)

IsCurrent returns true if the encoded password was generated by the current encoder with the current parameters. If it returns false, then the encoded password should be regenerated and replaced. Assuming that policy changes are always to increase security by using stronger hashes or increasing work factors, IsCurrent presents a mechanism to query an encoded password and determine whether it needs to be re-created.

func Register

func Register(encoding Encoding, enc encoder.Encoder) error

Register adds an encoder implementation to the list. It is expected that each encoder will call Register from an init() function. The first encoder imported becomes the default and is used to create new passwords. Subsequent imported encoders, if any, are used for decoding, where necessary. See SetDefault() to set the default encoder manually.

func Salt

func Salt(size int, minerFn SaltMiner) (salt []byte, err error)

Salt produces the specified number of random bytes. If minerFn is nil, the function generates bytes from rand.Reader. Otherwise minerFn is called and its results validated and returned.

func SetDefault

func SetDefault(encoding Encoding) error

SetDefault sets the default encoding used to create passwords. Since the first registered encoder is used as the default encoder, it is not necessary to call this routine unless you have multiple encoders imported, in which case, it is advisable to call this routine to avoid a dependency on the order of import statements.

func Verify

func Verify(plaintext, encoded string) (isValid bool, err error)

Verify takes a plaintext password and a encoded password and returns true if the password, when encoded by the same encoder, using the same parameters, matches the encoded password.

Types

type Encoding

type Encoding uint8

An Encoding is a number for an encoder and is used to disambiguate amongst the various encoders. Not all encoders will be implemented, installed, or used in any given system.

const (
	BCRYPT Encoding = iota // import "github.com/gyepisam/mcf/bcrypt"
	SCRYPT                 // import "github.com/gyepisam/mcf/scrypt"
	PBKDF2                 // import "github.com/gyepisam/mcf/pbkdf2"

)

List of known encodings.

func (Encoding) IsValid

func (e Encoding) IsValid() bool

IsValid returns true if the encoding is known.

func (Encoding) String

func (e Encoding) String() string

type ErrInvalidEncoding

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

ErrInvalidEncoding is returned when an invalid encoding is encountered.

func (*ErrInvalidEncoding) Error

func (e *ErrInvalidEncoding) Error() string

type ErrNoEncoder

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

ErrNoEncoder is returned if an encoded password does not match any known encoders. The encoded password is appended to the error message to aid in resolving the problem.

func (*ErrNoEncoder) Error

func (e *ErrNoEncoder) Error() string

type ErrUnregisteredEncoding

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

ErrUnregisteredEncoding is returned when an unregistered encoding is encountered.

func (*ErrUnregisteredEncoding) Error

func (e *ErrUnregisteredEncoding) Error() string

type SaltMiner

type SaltMiner func(int) ([]byte, error)

A SaltMiner is function that takes an int and produces that many random bytes. It exists to allow variation in the source of salt.

Directories

Path Synopsis
Package bcrypt implements a password encoding mechanism for the mcf framework
Package bcrypt implements a password encoding mechanism for the mcf framework
Package encoder represents an interface that MCF password encoders must implement
Package encoder represents an interface that MCF password encoders must implement
Package password manipulates passwords stored in Modular Crypt Format.
Package password manipulates passwords stored in Modular Crypt Format.
Package pbkdf2 implements a password encoding mechanism for the mcf framework
Package pbkdf2 implements a password encoding mechanism for the mcf framework
Package scrypt implements a password encoding mechanism for the mcf framework
Package scrypt implements a password encoding mechanism for the mcf framework

Jump to

Keyboard shortcuts

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