func (r *AESReader) Read(b []byte) (n int, err error) {
	if cap(b) <= 0 {
		return 0, nil
	}
	roundSize := ((len(b) - r.nRem) / aes.BlockSize) * aes.BlockSize
	if ((len(b) - r.nRem) % aes.BlockSize) > 0 {
		roundSize += aes.BlockSize
	}
	nr := copy(b, r.rem[0:r.nRem])
	copy(r.rem, r.rem[nr:])
	r.nRem -= nr
	if roundSize > 0 {	 
		buf := make([]byte, roundSize)
		n, err = io.ReadFull(r.ds, buf)
		if err == io.ErrUnexpectedEOF && n > 0 {
			err = nil	 
		} else if (err == io.EOF && n == 0) {
			return nr, err  
		} else if err != nil {
			return nr, err  
		}
		if n % aes.BlockSize != 0 {
			return nr, errors.New("Stream is not a valid AESRW stream.")
		}
		r.mode.CryptBlocks(buf[0:n], buf[0:n])
		_, err = r.ds.Peek(1)
		if err != nil {
			nPad := int(buf[n - 1])
			n -= nPad
		}
		if n > len(buf) || n < 0 {
			return nr, errors.New("Stream is not a valid AESRW stream.")
		}
		buf = buf[0:n]
		ar := copy(b[nr:], buf)
		nr += ar
		r.nRem = copy(r.rem, buf[ar:])
		if r.nRem > 0 {
			err = nil
		}
	}
	return nr, err
}
Read and decrypt data from the underlying io.Reader that was
encrypted using an AESWriter.
package aesrw
import (
	"crypto/aes"
	"bufio"
	"bytes"
	"crypto/cipher"
	"errors"
	"crypto/rand"
	"io"
)
type AESReader struct {
	ds *bufio.Reader
	nRem int
	rem []byte
	block cipher.Block
	mode cipher.BlockMode
}
type AESWriter struct {
	ds io.Writer
	nRem int
	rem []byte
	block cipher.Block
	mode cipher.BlockMode
}
func Encrypt(b, key []byte) ([]byte, error) {
	buf := bytes.NewBuffer(b)
	outBuf := new(bytes.Buffer)
	aw, err := NewWriter(outBuf, key)
	if err != nil {
		return nil, err
	}
	_, err = io.Copy(aw, buf)
	if err != nil {
		return nil, err
	}
	aw.Close()
	return outBuf.Bytes(), nil
}
func EncryptString(s string, key []byte) (string, error) {
	buf := bytes.NewBufferString(s)
	outBuf := new(bytes.Buffer)
	aw, err := NewWriter(outBuf, key)
	if err != nil {
		return "", err
	}
	_, err = io.Copy(aw, buf)
	if err != nil {
		return "", err
	}
	aw.Close()
	return outBuf.String(), nil
}
func Decrypt(b, key []byte) ([]byte, error) {
	buf := bytes.NewBuffer(b)
	ar, err := NewReader(buf, key)
	if err != nil {
		return nil, err
	}
	outBuf := new(bytes.Buffer)
	bw := bufio.NewWriter(outBuf)
	_, err = io.Copy(bw, ar)
	if err != nil {
		return nil, err
	}
	return outBuf.Bytes(), nil
}
func DecryptString(s string, key []byte) (string, error) {
	buf := bytes.NewBufferString(s)
	ar, err := NewReader(buf, key)
	if err != nil {
		return "", err
	}
	outBuf := new(bytes.Buffer)
	_, err = io.Copy(outBuf, ar)
	if err != nil {
		return "", err
	}
	return outBuf.String(), nil
}
func NewWriter(w io.Writer, k []byte) (*AESWriter, error) {
	if len(k) != 16 && len(k) != 24 && len(k) != 32 {
		return nil, errors.New("Key must be of length 16, 24, or 32.")
	}
	tmpBlock := make([]byte, aes.BlockSize)
	_, err := rand.Reader.Read(tmpBlock)
	if err != nil {
		return nil, err
	}
	_, err = w.Write(tmpBlock)
	if err != nil {
		return nil, err
	}
	blk, err := aes.NewCipher(k)
	mde := cipher.NewCBCEncrypter(blk, tmpBlock)
	return &AESWriter{ds: w, rem: make([]byte, aes.BlockSize), block: blk, mode: mde}, nil
}
func (w *AESWriter) Close() error {
	nPad := aes.BlockSize - w.nRem
	for i := w.nRem; i < cap(w.rem); i++ {
		w.rem[i] = byte(nPad)
	}
	w.mode.CryptBlocks(w.rem, w.rem)
	w.ds.Write(w.rem)
	w.nRem = 0
	return nil
}
func (w *AESWriter) Write(b []byte) (nw int, err error) {
	if len(b) <= 0 {
		return 0, nil
	}
	roundSize := ((len(b) + w.nRem) / aes.BlockSize) * aes.BlockSize
	nbw := Max(roundSize - w.nRem, 0)
	if roundSize > 0 {	 
		buf := make([]byte, roundSize)
		copy(buf, w.rem[0:w.nRem])
		copy(buf[w.nRem:], b[0:nbw])
		w.nRem = 0
		w.mode.CryptBlocks(buf, buf)
		w.ds.Write(buf)
	}
	copy(w.rem[w.nRem:], b[nbw:])
	w.nRem += (len(b) - nbw)
	return len(b), nil
}
func NewReader(r io.Reader, k []byte) (*AESReader, error) {
	if len(k) != 16 && len(k) != 24 && len(k) != 32 {
		return nil, errors.New("Key must be of length 16, 24, or 32.")
	}
	tmpBlock := make([]byte, aes.BlockSize)
	br := bufio.NewReader(r)
	nr, err := io.ReadFull(br, tmpBlock)
	if nr != aes.BlockSize || err != nil {
		return nil, err
	}
	blk, err := aes.NewCipher(k)
	mde := cipher.NewCBCDecrypter(blk, tmpBlock)
	return &AESReader{ds: br, rem: make([]byte, aes.BlockSize), block: blk, mode: mde}, nil
}