| // 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 = copy(iv) | |
| x.tmp = make([]byte, n) | |
| return x | |
| } | |
| func (x *cbcCipher) BlockSize() int { return x.blockSize } | |
| func (x *cbcCipher) Encrypt(src, dst []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(src, dst []byte) { | |
| x.c.Decrypt(src, x.tmp) | |
| 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) | |
| } |