gosecure

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Oct 22, 2019 License: MIT Imports: 10 Imported by: 0

README

Go Secure

Build Issues Pull Requests Go Doc License

Auth and hashing functions for Go/Gorilla.

Documentation

Overview

Package gosecure provides hashing, checking and associated functions for passphrases and JWT tokens. Tokens allow for session data to be passed in by a client having been encoded earlier. With both hashes and tokens secure cryptographic functions are used. All functions can be called in a time boxed fashion with guarantees about minimum execution time using the Timebox function.

Index

Examples

Constants

View Source
const AuthHeader = "Authorization"

AuthHeader is the header used to store the bearer token.

View Source
const SessionKey = "session"

SessionKey is used to store a session in a Gorilla context.

Variables

View Source
var (
	// ErrEmptyPassphrase is returned if an attempt is made to hash an empty
	// passphrase.
	ErrEmptyPassphrase = errors.New("security: passphrase cannot be empty")

	// ErrMismatchedPassphrase is returned if the passphrase does not match the
	// provided hash.
	ErrMismatchedPassphrase = errors.New("security: passphrase does not match hash")
)
View Source
var DefaultAlgorithm = Bcrypt{Cost: bcrypt.DefaultCost}

DefaultAlgorithm is the algorithm used by Hash and Compare.

View Source
var ErrNoCredentialsFound = errors.New("no credentials found")

ErrNoCredentialsFound is returned if an attempt is made to validate an empty bearer token.

View Source
var Fuse = 100000

Fuse is used to limit the number of hits stored against an action. If the fuse is trigger the action is thrown away. While it's theoretically possible to game the limited by carefully constructing the number of hits vs the limit and TTL in reality the Fuse will only be blown when a DOS style attack is happening and should be well over the limits set on the limiter.

Theoretical max memory usage is Fuse * size * ~60bytes.

Functions

func Compare

func Compare(passphrase string, hash []byte) error

Compare a passphrase to a previously hashed passphrase using the default crypto algorithm. If the passphrase matches the hash then this function will return nil. A mismatched passphrase will result in ErrMismatchedPassphrase. All other errors indicate something went wrong comparing the hash and passphrase.

Example
package main

import (
	"fmt"

	"bitbucket.org/idomdavis/gosecure"
)

func main() {
	b := []byte{
		36, 50, 97, 36, 49, 48, 36, 100, 117, 66, 70, 85, 103, 120, 51, 68,
		80, 106, 103, 108, 90, 74, 84, 51, 101, 56, 57, 122, 79, 87, 122,
		74, 122, 51, 46, 108, 82, 73, 106, 56, 115, 101, 88, 112, 85, 46,
		68, 67, 112, 78, 48, 121, 67, 97, 57, 109, 74, 98, 114, 67}

	if err := gosecure.Compare("passphrase", b); err != nil {
		fmt.Println("invalid passphrase")
	} else {
		fmt.Println("passphrase accepted")
	}

}
Output:

passphrase accepted

func Hash

func Hash(passphrase string) ([]byte, error)

Hash a passphrase using the default crypto algorithm.

Example
package main

import (
	"fmt"

	"bitbucket.org/idomdavis/gosecure"
)

func main() {
	if h, err := gosecure.Hash("passphrase"); err == nil {
		fmt.Println(len(h))
	}

}
Output:

60

func Timebox

func Timebox(duration time.Duration, task func())

Timebox will run the provided function, taking at least the given duration.

Example
package main

import (
	"fmt"
	"os"
	"time"

	"bitbucket.org/idomdavis/gosecure"
)

func main() {
	// Duration wants to be longer than the expected maximum of the provided
	// function.
	duration := time.Millisecond * 50
	start := time.Now()

	// Use closures to send and retrieve values
	var err error
	msg := "running..."

	gosecure.Timebox(duration, func() {
		_, err = fmt.Fprintln(os.Stdout, msg)
	})

	if err != nil {
		fmt.Printf("unexpected error running timeboxed function: %s\n", err)
	}

	end := time.Now()
	if (end.Sub(start)) > duration {
		fmt.Println("time boxed")
	}

}
Output:

running...
time boxed

Types

type Authenticator

type Authenticator interface {
	// Authenticate returns a handler function used to authenticate requests.
	Authenticate(next http.Handler) http.Handler
}

Authenticator types provide middleware that will authenticate requests.

func NewAuthenticator

func NewAuthenticator(signatory Signatory) Authenticator

NewAuthenticator returns a type that can be used for authentication middleware.

type Bcrypt

type Bcrypt struct {
	Cost int
}

Bcrypt hashing algorithm. Should be all you need.

func (Bcrypt) Compare

func (Bcrypt) Compare(passphrase string, hash []byte) error

Compare a passphrase to a previously hashed passphrase. If the passphrase matches the hash then this function will return nil. A mismatched passphrase will result in ErrMismatchedPassphrase. All other errors indicate something went wrong comparing the hash and passphrase.

func (Bcrypt) Hash

func (b Bcrypt) Hash(passphrase string) ([]byte, error)

Hash a passphrase. If the passphrase is empty an error will be returned.

type Crypto

type Crypto interface {
	Hash(passphrase string) ([]byte, error)
	Compare(passphrase string, hash []byte) error
}

Crypto defines a type that can cryptographically hash and compare a passphrase. Implementations of Crypto want to implement strong hashing functions such as bcrypt. Implementing this for things like MD5 is a stunningly bad idea.

type Limiter

type Limiter interface {
	// Limit checks if the action provided should be limited, returning true if
	// it should.
	Limit(action string) bool
}

A Limiter is used to indicate if an action has occurred too often and should be limited.

func NewLimiter

func NewLimiter(size, limit int, ttl time.Duration) Limiter

NewLimiter returns a limiter that uses a lazy LRU backing cache. The limiter prunes expired hits for an action on a call to Limit, and will drop the least recently used item from the cache if it exceeds the defined size.

TTL sizes want to be small (in the 1 second to 1 minute range) to avoid the number of hits in the cache getting too large in case of a DOS style attack. A Fuse value is used to prevent runaway memory consumption in this case.

type RateLimiter

type RateLimiter interface {
	// Limit returns a handler function used to rate limit requests.
	Limit(next http.Handler) http.Handler
}

RateLimiter defines Gorilla middleware to be used to rate limit requests. If a limiter is triggered it returns "429 Too Many Requests".

func NewSourceLimiter

func NewSourceLimiter(limiter Limiter) RateLimiter

NewSourceLimiter returns middleware that will limit requests based on the remote address, or the source of the request.

func NewUserLimiter

func NewUserLimiter(limiter Limiter) RateLimiter

NewUserLimiter returns middleware that will limit requests based on the user in the basic auth header. If no user is set this limiter is skipped.

type Session

type Session map[string]string

Session stores session claims encoded in the JWT.

type Signatory

type Signatory interface {
	// Generate a bearer token, embedding the given Session in the token.
	Generate(data Session) (string, error)

	// Validate a bearer token, returning the associated Session embedded in the
	// token. An error is returned if there is a problem validating the token.
	Validate(bearer string) (Session, error)
}

A Signatory is used to sign and validate sessions via the use of JWT bearer tokens.

func NewSignatory

func NewSignatory(secret string, ttl time.Duration) Signatory

NewSignatory constructs a signatory using the given secret string. If tokens are going to be shared between signatories they must use the same secret.

Example
package main

import (
	"fmt"
	"time"

	"bitbucket.org/idomdavis/gosecure"
)

const secret = "secretString"

func main() {
	// Use the default TTL
	_ = gosecure.NewSignatory(secret, 0)

	// Specify TTL, generate, then validate a token.
	sig := gosecure.NewSignatory(secret, time.Hour)
	token, _ := sig.Generate(gosecure.Session{"key": "value"})
	session, _ := sig.Validate(token)

	fmt.Println(session["key"])

}
Output:

value

Jump to

Keyboard shortcuts

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