// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Cipher block chaining (CBC) mode. // CBC provides confidentiality by xoring (chaining) each plaintext block // with the previous ciphertext block before applying the block cipher. // See NIST SP 800-38A, pp 10-11 package block import ( "io" ) type cbcCipher struct { c Cipher blockSize int iv []byte tmp []byte } func newCBC(c Cipher, iv []byte) *cbcCipher { n := c.BlockSize() x := new(cbcCipher) x.c = c x.blockSize = n x.iv = dup(iv) x.tmp = make([]byte, n) return x } func (x *cbcCipher) BlockSize() int { return x.blockSize } func (x *cbcCipher) Encrypt(dst, src []byte) { for i := 0; i < x.blockSize; i++ { x.iv[i] ^= src[i] } x.c.Encrypt(x.iv, x.iv) for i := 0; i < x.blockSize; i++ { dst[i] = x.iv[i] } } func (x *cbcCipher) Decrypt(dst, src []byte) { x.c.Decrypt(x.tmp, src) for i := 0; i < x.blockSize; i++ { x.tmp[i] ^= x.iv[i] x.iv[i] = src[i] dst[i] = x.tmp[i] } } // NewCBCDecrypter returns a reader that reads data from r and decrypts it using c // in cipher block chaining (CBC) mode with the initialization vector iv. // The returned Reader does not buffer or read ahead except // as required by the cipher's block size. func NewCBCDecrypter(c Cipher, iv []byte, r io.Reader) io.Reader { return NewECBDecrypter(newCBC(c, iv), r) } // NewCBCEncrypter returns a writer that encrypts data using c // in cipher block chaining (CBC) mode with the initialization vector iv // and writes the encrypted data to w. // The returned Writer does no buffering except as required // by the cipher's block size, so there is no need for a Flush method. func NewCBCEncrypter(c Cipher, iv []byte, w io.Writer) io.Writer { return NewECBEncrypter(newCBC(c, iv), w) }