Skip to content

Instantly share code, notes, and snippets.

@tmm1
Last active April 30, 2019 16:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tmm1/5b4d2d449653f980fd2dda2a7318be26 to your computer and use it in GitHub Desktop.
Save tmm1/5b4d2d449653f980fd2dda2a7318be26 to your computer and use it in GitHub Desktop.
Golang AES CBC PKCS7 io.Reader
package hls
import (
"crypto/aes"
"crypto/cipher"
"io"
"github.com/Sonelli/gojuice/crypto/pkcs7"
)
type aesReader struct {
src io.Reader
cbc cipher.BlockMode
bsize int
peek []byte
buf []byte
}
func NewAesReader(src io.Reader, key []byte, iv []byte) (*aesReader, error) {
cipherBlock, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
cbc := cipher.NewCBCDecrypter(cipherBlock, iv)
return &aesReader{
src: src,
cbc: cbc,
bsize: cbc.BlockSize(),
peek: make([]byte, cbc.BlockSize()),
}, nil
}
func (a *aesReader) Read(out []byte) (int, error) {
if a.buf == nil {
a.buf = make([]byte, len(out))
}
decoded := 0
copy(a.buf, a.peek)
n, err := a.src.Read(a.buf[len(a.peek):])
if len(a.peek) > 0 {
n += len(a.peek)
a.peek = a.peek[:0]
}
if n > 0 {
o := 0
for o = 0; o < n; o += a.bsize {
if o+a.bsize > n {
break
}
a.cbc.CryptBlocks(out[decoded:], a.buf[o:o+a.bsize])
decoded += a.bsize
}
a.peek = a.peek[:n-o]
copy(a.peek, a.buf[o:n])
if len(a.peek) == 0 {
a.peek = a.peek[0:1]
_, err = a.src.Read(a.peek)
if err == io.EOF {
a.peek = a.peek[:0]
depad, err := pkcs7.UnpadPKCS7(out[decoded-a.bsize:decoded], a.bsize)
if err != nil {
return decoded, err
}
padding := a.bsize - len(depad)
decoded -= padding
}
}
}
return decoded, err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment