func (c *Cipher) XORKeyStream(dst, src []byte) {
	if len(dst) < len(src) {
		src = src[:len(dst)]
	}
	for remaining := len(src); remaining > 0; {
		if c.off == BlockSize {
			nrBlocks := remaining / BlockSize
			directBytes := nrBlocks * BlockSize
			if nrBlocks > 0 {
				blocksFn(&c.state, src, dst, nrBlocks, c.ietf)
				remaining -= directBytes
				if remaining == 0 {
					return
				}
				dst = dst[directBytes:]
				src = src[directBytes:]
			}
			blocksFn(&c.state, nil, c.buf[:], 1, c.ietf)
			c.off = 0
		}
		toXor := BlockSize - c.off
		if remaining < toXor {
			toXor = remaining
		}
		if toXor > 0 {
			for i, v := range src[:toXor] {
				dst[i] = v ^ c.buf[c.off+i]
			}
			dst = dst[toXor:]
			src = src[toXor:]
			remaining -= toXor
			c.off += toXor
		}
	}
}
XORKeyStream sets dst to the result of XORing src with the key stream.  Dst
and src may be the same slice but otherwise should not overlap.
package chacha20
import (
	"crypto/cipher"
	"encoding/binary"
	"errors"
	"math"
	"runtime"
)
const (
	KeySize = 32
	NonceSize = 8
	INonceSize = 12
	XNonceSize = 24
	HNonceSize = 16
	BlockSize = 64
	stateSize    = 16
	chachaRounds = 20
	sigma0 = uint32(0x61707865)
	sigma1 = uint32(0x3320646e)
	sigma2 = uint32(0x79622d32)
	sigma3 = uint32(0x6b206574)
)
var (
	ErrInvalidKey = errors.New("key length must be KeySize bytes")
	ErrInvalidNonce = errors.New("nonce length must be NonceSize/INonceSize/XNonceSize bytes")
	ErrInvalidCounter = errors.New("block counter is invalid (out of range)")
	useUnsafe    = false
	usingVectors = false
	blocksFn     = blocksRef
)
type Cipher struct {
	state [stateSize]uint32
	buf  [BlockSize]byte
	off  int
	ietf bool
}
func (c *Cipher) Reset() {
	for i := range c.state {
		c.state[i] = 0
	}
	for i := range c.buf {
		c.buf[i] = 0
	}
}