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 ¶
- func Create(plaintext string) (encoded string, err error)
- func IsCurrent(encoded string) (isCurrent bool, err error)
- func Register(encoding Encoding, enc encoder.Encoder) error
- func Salt(size int, minerFn SaltMiner) (salt []byte, err error)
- func SetDefault(encoding Encoding) error
- func Verify(plaintext, encoded string) (isValid bool, err error)
- type Encoding
- type ErrInvalidEncoding
- type ErrNoEncoder
- type ErrUnregisteredEncoding
- type SaltMiner
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Create ¶
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 ¶
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 ¶
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 ¶
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 ¶
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.
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.
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
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 |