...
package cipher
import "crypto/internal/subtle"
type cbc struct {
b Block
blockSize int
iv []byte
tmp []byte
}
func newCBC(b Block, iv []byte) *cbc {
return &cbc{
b: b,
blockSize: b.BlockSize(),
iv: dup(iv),
tmp: make([]byte, b.BlockSize()),
}
}
type cbcEncrypter cbc
type cbcEncAble interface {
NewCBCEncrypter(iv []byte) BlockMode
}
func NewCBCEncrypter(b Block, iv []byte) BlockMode {
if len(iv) != b.BlockSize() {
panic("cipher.NewCBCEncrypter: IV length must equal block size")
}
if cbc, ok := b.(cbcEncAble); ok {
return cbc.NewCBCEncrypter(iv)
}
return (*cbcEncrypter)(newCBC(b, iv))
}
func (x *cbcEncrypter) BlockSize() int { return x.blockSize }
func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
if len(src)%x.blockSize != 0 {
panic("crypto/cipher: input not full blocks")
}
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
if subtle.InexactOverlap(dst[:len(src)], src) {
panic("crypto/cipher: invalid buffer overlap")
}
iv := x.iv
for len(src) > 0 {
xorBytes(dst[:x.blockSize], src[:x.blockSize], iv)
x.b.Encrypt(dst[:x.blockSize], dst[:x.blockSize])
iv = dst[:x.blockSize]
src = src[x.blockSize:]
dst = dst[x.blockSize:]
}
copy(x.iv, iv)
}
func (x *cbcEncrypter) SetIV(iv []byte) {
if len(iv) != len(x.iv) {
panic("cipher: incorrect length IV")
}
copy(x.iv, iv)
}
type cbcDecrypter cbc
type cbcDecAble interface {
NewCBCDecrypter(iv []byte) BlockMode
}
func NewCBCDecrypter(b Block, iv []byte) BlockMode {
if len(iv) != b.BlockSize() {
panic("cipher.NewCBCDecrypter: IV length must equal block size")
}
if cbc, ok := b.(cbcDecAble); ok {
return cbc.NewCBCDecrypter(iv)
}
return (*cbcDecrypter)(newCBC(b, iv))
}
func (x *cbcDecrypter) BlockSize() int { return x.blockSize }
func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
if len(src)%x.blockSize != 0 {
panic("crypto/cipher: input not full blocks")
}
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
if subtle.InexactOverlap(dst[:len(src)], src) {
panic("crypto/cipher: invalid buffer overlap")
}
if len(src) == 0 {
return
}
end := len(src)
start := end - x.blockSize
prev := start - x.blockSize
copy(x.tmp, src[start:end])
for start > 0 {
x.b.Decrypt(dst[start:end], src[start:end])
xorBytes(dst[start:end], dst[start:end], src[prev:start])
end = start
start = prev
prev -= x.blockSize
}
x.b.Decrypt(dst[start:end], src[start:end])
xorBytes(dst[start:end], dst[start:end], x.iv)
x.iv, x.tmp = x.tmp, x.iv
}
func (x *cbcDecrypter) SetIV(iv []byte) {
if len(iv) != len(x.iv) {
panic("cipher: incorrect length IV")
}
copy(x.iv, iv)
}
View as plain text