passwd

package module
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: May 3, 2019 License: BSD-3-Clause Imports: 12 Imported by: 0

README

Documentation Go Report Card License

passwd

A simple golang password hashing package

Description

New "password hashing" algorithms (PHC) have emerged in order to counter the increase in hardware assets available to crack passwords easily when they are stolen.

Those new algorithms increase the cost of an attack and slow down the discovery of the original password. Unfortunately they requires various non-trivial parameters to be used properly.

This package attempts to provide a safe and easy interface to produce/verify a hashed password, while giving the ability to tune for specific/custom needs if necessary.

3 algorithms are implemented:

  • bcrypt (using x/crypto/bcrypt, FOR LEGACY reasons)
  • scrypt (using x/crypto/scrypt)
  • argon2id (using x/crypto/argon2)

(to keep things simple and to avoid a user to shoot himself in the foot) Parameters choices are limited and translated into static "profiles":

  • Default
  • Paranoid (as it is WIP, it might switch to 3 profiles based on usage needs like : interactive, default, paranoid)

How to Use the package

Public vs Masked parameters

Commonly password hashing includes hashing parameters in order to make it easy for interoperability.

But you might decide you don't interoperate with other systems and you control your authentication mechanism, as such you might be willing to make things slightly more annoying for an attacker reaching your stored password by "masking" your parameters (instead of embedding them in the resulting hash)

Public parameters allows you to use the hashed password to directly provide a simple passwd.Compare() function. Masked parameters requires you to say what parameters you use AND to call the (p *Profile).Compare() method of the profile.

Attacker would have to not only grab the stored password, but also to guess the parameters you use with your key derivation in order to attack it offline.

example basic usage with public parameters:

Instanciate a password hashing profile:

   p := passwd.New(passwd.Argon2idDefault)

Hash your password:

   hashed, err := p.Hash( []byte("mypassword") )

done, that's it, now you store hashed

   hashed: '$2id$GlQX3F.KSYw1JLVv.LKDT.$1$65536$8$32$97DO7W9m/I8CTEQFKDa.VvEBTX1WepVv4qaWlt0OqH6'

example password check/comparison :

check a hash against a password:

   err := passwd.Compare(hashedpassword, []byte("password"))

done.

example basic usage with masked parameters:

Instanciate a password hashing profile:

   p := passwd.NewMasked(passwd.Argon2idDefault)

Hash your password:

   hashed, err := p.Hash( []byte("mypassword") )

done, that's it, now you store hashed

   hashed: $2id$ihFFCGUfBHTqUfvUIos6X.$AmClxc.3uj6LsxjVGqpOZggyqIL.wQJ9zjY23ztsETK

example masked parameters password check/comparison :

check a hash against a password:

   p := passwd.NewMasked(passwd.Argon2idDefault)
   err := p.Compare(hashedpassword, []byte("password"))

done.

Important Notes

bcrypt() is just a wrapper to x/crypto/bcrypt, only scrypt and argon support MaskedParameters. bcrypt() is implemented for migration ease purposes, Compare will works perfectly with bcrypt while encrypting new password and changing old ones can use the new "profile".

Changelog

  • v0.1.0: initial release
  • v0.1.1: fix /issues/1

Status

This package exclusively uses crypto algorithm implementations shipped in go extended crypto packages (located in x/crypto/)

This is work in progress and the default are still being worked out. Feedback is welcome.

An example tool/usage lies in cmd/pcrypt in this repository, hopefully it helps understanding how to use this package.

Featuring (because there is always a star in your production..)

  • Argon2 for today key stretching.
  • Scrypt for key stretching.
  • Go because it works.

Documentation

Overview

Package passwd provides simple primitives for hashing and verifying password.

Index

Examples

Constants

View Source
const (
	// Argon2id constant is to select the argon flavor in Argon2Params version field
	Argon2id = iota // default
	// Argon2i constant is to select argon flavor in Argon2Params version field
	Argon2i
)
View Source
const (
	ErrParse       = Error("parse error")
	ErrUnsupported = Error("unsupported")
	ErrMismatch    = Error("mismatch")
	ErrUnsafe      = Error("unsafe parameters")
)
View Source
const (
	Argon2idDefault = iota
	Argon2idParanoid
	ScryptDefault
	ScryptParanoid
	BcryptDefault
	BcryptParanoid
)

Password hashing profiles available

Variables

This section is empty.

Functions

func Compare

func Compare(hashed, password []byte) error

Compare verify a non masked hash values against a plaintext password.

Example
hashedPassword := "$2id$aiOE.rPFUFkkehxc6utWY.$1$65536$8$32$Wv1IMP6xwaqVaQGOX6Oxe.eSEbozeRJLzln8ZlthZfS"
err := Compare(hashedpassword, []byte("prout"))
fmt.Printf("Compare err: %v", err)
Output:

Types

type Argon2Params

type Argon2Params struct {
	Version int
	Time    uint32
	Memory  uint32
	Thread  uint8
	Saltlen uint32
	Keylen  uint32
	// contains filtered or unexported fields
}

Argon2Params are the parameters for the argon2 key derivation.

type BcryptParams

type BcryptParams struct {
	Cost int
}

BcryptParams are the parameters for the bcrypt key derivation.

type Error

type Error string

func (Error) Error

func (e Error) Error() string

type Profile

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

Profile define the hashing profile you have select and is created using New() / NewMasked() / NewCustom()

func New

func New(profile int) *Profile

New instanciate a new Profile

Example
p := New(Argon2idDefault)
h, err := p.Hash([]byte("mylamepass!!"))
if err != nil {
	panic(err)
}
fmt.Printf("hashed('mylamepass!!'): %s\n", h)
Output:

hashed('mylamepass!!'): $2id$params$*password_hash*

func NewCustom

func NewCustom(params interface{}) *Profile

NewCustom instanciates a new Profile using user defined hash parameters

func NewMasked

func NewMasked(profile int) *Profile

New instanciates a new masked Profile. Masked translate to the fact that no hash parameters will be provided.

Example
p := NewMasked(Argon2idDefault)
h, err := p.Hash([]byte("mylamepass!!"))
if err != nil {
	panic(err)
}
fmt.Printf("hashed('mylamepass!!'): %s\n", h)
Output:

func (*Profile) Compare

func (p *Profile) Compare(hashed, password []byte) error

Compare method compared a computed hash against a plaintext password for the associated profile. This function is mainly here to allow to work with "masked" hashes where we don't provide the Hash parameters in the hashed values.

Example
hashedPassword := "$2id$PEKC7uef8j09Tx8WHKrpwu$e1ZINFSkJz4/hM0mytQCjrEmVRRb6VtkXwAZibZhgYm"
p := NewMasked(Argon2idDefault)
err := p.Compare(hashedpassword, []byte("prout"))
fmt.Printf("Masked Compare err: %v", err)
Output:

func (*Profile) Hash

func (p *Profile) Hash(password []byte) ([]byte, error)

Hash is the Profile method for computing the hash value respective of the selected profile. it takes the plaintext password to hash and output its hashed value ready for storage

type ScryptParams

type ScryptParams struct {
	N       uint32 // cpu memory cost must be > 1 && %2 == 0
	R       uint32 // parallelization cost param -> r*p < 2^30 (go implementation specific)
	P       uint32 // parallelization cost param -> r*p < 2^30 (go implementation specific)
	Saltlen uint32 // 128 bits min.
	Keylen  uint32 // 128 bits min.
	// contains filtered or unexported fields
}

ScryptParams are the parameters for the scrypt key derivation.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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