func (p *Params) Validate(id, token string) error {
	data, err := base64.URLEncoding.DecodeString(token)
	if err != nil || len(data) < dataSize+macSize {
		return ErrInvalidToken
	}
	mac := data[dataSize:][:macSize]
	data = data[:dataSize]
	if !hmac.Equal(hmacSHA256(p.key, data, id), mac) {
		return ErrInvalidToken
	}
	t := time.Unix(int64(binary.BigEndian.Uint32(data)), 0)
	if p.timer().Sub(t) > p.MaxAge {
		return ErrInvalidToken
	}
	return nil
}
Validate validates the given token for the given user.
package charlie
import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/binary"
	"errors"
	"time"
)
var (
	ErrInvalidToken = errors.New("invalid token")
)
type Params struct {
	key   []byte
	timer func() time.Time
	MaxAge time.Duration  
}
func New(key []byte) *Params {
	k := make([]byte, len(key))
	copy(k, key)
	return &Params{
		key:    k,
		timer:  time.Now,
		MaxAge: 10 * time.Minute,
	}
}
func (p *Params) Generate(id string) string {
	buf := make([]byte, dataSize, dataSize+macSize)
	binary.BigEndian.PutUint32(buf, uint32(p.timer().Unix()))
	token := append(buf, hmacSHA256(p.key, buf, id)...)
	return base64.URLEncoding.EncodeToString(token)
}