// Package fernet takes a user-provided message (an arbitrary
// sequence of bytes), a key (256 bits), and the current time,
// and produces a token, which contains the message in a form
// that can't be read or altered without the key.
//
// For more information and background, see the Fernet spec
// at https://github.com/fernet/spec.
//
// Subdirectories in this package provide command-line tools
// for working with Fernet keys and tokens.
package fernet

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/rand"
	"crypto/sha256"
	"crypto/subtle"
	"encoding/base64"
	"encoding/binary"
	"io"
	"time"
)

const (
	version      byte = 0x80
	tsOffset          = 1
	ivOffset          = tsOffset + 8
	payOffset         = ivOffset + aes.BlockSize
	overhead          = 1 + 8 + aes.BlockSize + sha256.Size // ver + ts + iv + hmac
	maxClockSkew      = 60 * time.Second
)

var encoding = base64.URLEncoding

// generates a token from msg, writes it into tok, and returns the
// number of bytes generated, which is encodedLen(msg).
// len(tok) must be >= encodedLen(len(msg))
func gen(tok, msg, iv []byte, ts time.Time, k *Key) int {
	tok[0] = version
	binary.BigEndian.PutUint64(tok[tsOffset:], uint64(ts.Unix()))
	copy(tok[ivOffset:], iv)
	p := tok[payOffset:]
	n := pad(p, msg, aes.BlockSize)
	bc, _ := aes.NewCipher(k.cryptBytes())
	cipher.NewCBCEncrypter(bc, iv).CryptBlocks(p[:n], p[:n])
	genhmac(p[n:n], tok[:payOffset+n], k.signBytes())
	return payOffset + n + sha256.Size
}

// token length for input msg of length n, not including base64
func encodedLen(n int) int {
	const k = aes.BlockSize
	return n/k*k + k + overhead
}

// max msg length for tok of length n, for binary token (no base64)
// upper bound; not exact
func decodedLen(n int) int {
	return n - overhead
}

// if msg is nil, decrypts in place and returns a slice of tok.
func verify(msg, tok []byte, ttl time.Duration, now time.Time, k *Key) []byte {
	if len(tok) < 1 || tok[0] != version {
		return nil
	}
	ts := time.Unix(int64(binary.BigEndian.Uint64(tok[1:])), 0)
	if ttl >= 0 && (now.After(ts.Add(ttl)) || ts.After(now.Add(maxClockSkew))) {
		return nil
	}
	n := len(tok) - sha256.Size
	var hmac [sha256.Size]byte
	genhmac(hmac[:0], tok[:n], k.signBytes())
	if subtle.ConstantTimeCompare(tok[n:], hmac[:]) != 1 {
		return nil
	}
	pay := tok[payOffset : len(tok)-sha256.Size]
	if len(pay)%aes.BlockSize != 0 {
		return nil
	}
	if msg != nil {
		copy(msg, pay)
		pay = msg
	}
	bc, _ := aes.NewCipher(k.cryptBytes())
	iv := tok[9:][:aes.BlockSize]
	cipher.NewCBCDecrypter(bc, iv).CryptBlocks(pay, pay)
	return unpad(pay)
}

// Pads p to a multiple of k using PKCS #7 standard block padding.
// See http://tools.ietf.org/html/rfc5652#section-6.3.
func pad(q, p []byte, k int) int {
	n := len(p)/k*k + k
	copy(q, p)
	c := byte(n - len(p))
	for i := len(p); i < n; i++ {
		q[i] = c
	}
	return n
}

// Removes PKCS #7 standard block padding from p.
// See http://tools.ietf.org/html/rfc5652#section-6.3.
// This function is the inverse of pad.
// If the padding is not well-formed, unpad returns nil.
func unpad(p []byte) []byte {
	c := p[len(p)-1]
	for i := len(p) - int(c); i < len(p); i++ {
		if i < 0 || p[i] != c {
			return nil
		}
	}
	return p[:len(p)-int(c)]
}

func b64enc(src []byte) []byte {
	dst := make([]byte, encoding.EncodedLen(len(src)))
	encoding.Encode(dst, src)
	return dst
}

func b64dec(src []byte) []byte {
	dst := make([]byte, encoding.DecodedLen(len(src)))
	n, err := encoding.Decode(dst, src)
	if err != nil {
		return nil
	}
	return dst[:n]
}

func genhmac(q, p, k []byte) {
	h := hmac.New(sha256.New, k)
	h.Write(p)
	h.Sum(q)
}

// EncryptAndSign encrypts and signs msg with key k and returns the resulting
// fernet token. If msg contains text, the text should be encoded
// with UTF-8 to follow fernet convention.
func EncryptAndSign(msg []byte, k *Key) (tok []byte, err error) {
	iv := make([]byte, aes.BlockSize)
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		return nil, err
	}
	b := make([]byte, encodedLen(len(msg)))
	n := gen(b, msg, iv, time.Now(), k)
	tok = make([]byte, encoding.EncodedLen(n))
	encoding.Encode(tok, b[:n])
	return tok, nil
}

// VerifyAndDecrypt verifies that tok is a valid fernet token that was signed
// with a key in k at most ttl time ago only if ttl is greater than zero.
// Returns the message contained in tok if tok is valid, otherwise nil.
func VerifyAndDecrypt(tok []byte, ttl time.Duration, k []*Key) (msg []byte) {
	b := make([]byte, encoding.DecodedLen(len(tok)))
	n, _ := encoding.Decode(b, tok)
	for _, k1 := range k {
		msg = verify(nil, b[:n], ttl, time.Now(), k1)
		if msg != nil {
			return msg
		}
	}
	return nil
}
