itsdangerous

package module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Apr 30, 2024 License: MIT Imports: 7 Imported by: 1

README

Version Built with GoLang License Go Report Card Tests Go Coverage

It's Dangerous

itsdangerous is a Go package which provides

  • Methods to create and verify MAC signatures of data
  • Ability to add timestamps to signed tokens and use custom epoch if needed.
  • BLAKE3 signatures and Base58 time encoding provides outstanding performance and security.
  • A very simple to use API with good documentation and 100% test coverage.
  • Various helper methods for parsing tokens

BLAKE3 support is provided by blake3.

Installation

Go get the package in the usual way:

go get -u github.com/tsawler/itsdangerous

Usage

A simple example:

package main

import (
	"fmt"
	"github.com/tsawler/itsdangerous"
	"log"
	"time"
)

func main() {
	// Create a secret; typically, make this 32 characters long.
	var secret = []byte("some-very-good-secret")

	// The data to be signed.
	var data = []byte("https://example.com?id=10")

	// Create a new instance of itsdangerous.
	s := itsdangerous.New(secret)

	// Sign the data; we get back a byte array with the signature appended.
	token := s.Sign(data)

	// Unsign the token to verify it. If successful the data portion of the
	// token is returned. If unsuccessful then d will be nil, and an error
	// is returned.
	d, err := s.Unsign(token)
	if err != nil {
		// The signature is not valid. The token was tampered with, forged, or maybe it's
		// not even a token at all. It's not safe to use it.
		log.Println("Invalid signature error:", err)
	} else {
		// The signature is valid, so it is safe to use the data.
		fmt.Println("Unsigned:", string(d))
		fmt.Println("Signed:", string(token))
		fmt.Println("Valid signature!")
	}

	// Create a new signer, this time with a timestamp.
	s2 := itsdangerous.New(secret, itsdangerous.Timestamp)
	token = s2.Sign(data)

	// print out new signed data
	fmt.Println("Signed with timestamp:", string(token))

	// Parse the token.
	ts := s2.Parse(token)

	// The token should be not expired at this point.
	if time.Since(ts.Timestamp) < time.Second {
		fmt.Println("Token with timestamp has not expired!")
	}

	// Wait two seconds to expire the token.
	time.Sleep(2 * time.Second)

	// The token should be expired at this point.
	if time.Since(ts.Timestamp) > time.Second {
		fmt.Println("Token with timestamp is expired!")
	}
}

The output of this program is something like:

tcs@Grendel example-itsdangerous % go run .
Unsigned: https://example.com?id=10
Signed: https://example.com?id=10.eoaZ-lDxxuZ-BK5PFmbZlVps0Htqi6NILs0HR47Dvs0
Valid signature!
Signed with timestamp: https://example.com?id=10.3yzzW5.fuoQr38zm2rQdbwFdXtU1BOeRmp1HDmyNhOM3ZTXfCY
Token with timestamp has not expired!
Token with timestamp is expired!

Tests

To run all tests, execute this command:

go test -v .

Benchmarks

To run benchmarks, execute this command:

go test -v -bench=.

Credit

This code is an updated version of go-alone. Major changes include updating to use go modules, and moving from BLAKE2b to BLAKE3.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidSignature = errors.New("invalid signature")

ErrInvalidSignature is returned by Unsign when the provided token's signature is not valid.

View Source
var ErrShortToken = errors.New("token is too small to be valid")

ErrShortToken is returned by Unsign when the provided token's length is too short to be a valid token.

Functions

func Epoch

func Epoch(e int64) func(*Sword)

Epoch is a functional option that can be passed to New() to set the Epoch to be used.

func Timestamp

func Timestamp(s *Sword)

Timestamp is a functional option that can be passed to New() to add a timestamp to signatures.

Types

type Sword

type Sword struct {
	sync.Mutex
	// contains filtered or unexported fields
}

Sword is the main struct used to sign and unsign data using this package.

func New

func New(key []byte, options ...func(*Sword)) *Sword

New takes a secret key and returns a new Sword. If no Options are provided then minimal defaults will be used. NOTE: The key must be 32 bytes. If a key < 32 bytes is provided, it will be padded to 32 bytes. If a larger key is provided it will be truncated to 64 bytes. func New(key []byte, o *Options) *Sword {

func (*Sword) Parse

func (s *Sword) Parse(t []byte) Token

Parse will parse the []byte token returned from Sign based on the Sword Options into a Token struct. For this to work correctly the Sword Options need to match that of what was used when the token was initially created.

func (*Sword) Sign

func (s *Sword) Sign(data []byte) []byte

Sign signs data and returns []byte in the format `data.signature`. Optionally add a timestamp and return in the format `data.timestamp.signature`

func (*Sword) Unsign

func (s *Sword) Unsign(token []byte) ([]byte, error)

Unsign validates a signature and if successful returns the data portion of the []byte. If unsuccessful it will return an error and nil for the data.

type Token

type Token struct {
	Payload   []byte
	Timestamp time.Time
}

Token is used to parse out a []byte token provided by Sign().

Jump to

Keyboard shortcuts

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