| // 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 ( |
| "crypto/block"; |
| "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); |
| } |
| |