github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/crypto/cipher/cbc.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Cipher block chaining (CBC) mode.
     6  
     7  // CBC provides confidentiality by xoring (chaining) each plaintext block
     8  // with the previous ciphertext block before applying the block cipher.
     9  
    10  // See NIST SP 800-38A, pp 10-11
    11  
    12  package cipher
    13  
    14  type cbc struct {
    15  	b         Block
    16  	blockSize int
    17  	iv        []byte
    18  	tmp       []byte
    19  }
    20  
    21  func newCBC(b Block, iv []byte) *cbc {
    22  	return &cbc{
    23  		b:         b,
    24  		blockSize: b.BlockSize(),
    25  		iv:        dup(iv),
    26  		tmp:       make([]byte, b.BlockSize()),
    27  	}
    28  }
    29  
    30  type cbcEncrypter cbc
    31  
    32  // NewCBCEncrypter returns a BlockMode which encrypts in cipher block chaining
    33  // mode, using the given Block. The length of iv must be the same as the
    34  // Block's block size.
    35  func NewCBCEncrypter(b Block, iv []byte) BlockMode {
    36  	if len(iv) != b.BlockSize() {
    37  		panic("cipher.NewCBCEncrypter: IV length must equal block size")
    38  	}
    39  	return (*cbcEncrypter)(newCBC(b, iv))
    40  }
    41  
    42  func (x *cbcEncrypter) BlockSize() int { return x.blockSize }
    43  
    44  func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
    45  	if len(src)%x.blockSize != 0 {
    46  		panic("crypto/cipher: input not full blocks")
    47  	}
    48  	if len(dst) < len(src) {
    49  		panic("crypto/cipher: output smaller than input")
    50  	}
    51  	for len(src) > 0 {
    52  		for i := 0; i < x.blockSize; i++ {
    53  			x.iv[i] ^= src[i]
    54  		}
    55  		x.b.Encrypt(x.iv, x.iv)
    56  		for i := 0; i < x.blockSize; i++ {
    57  			dst[i] = x.iv[i]
    58  		}
    59  		src = src[x.blockSize:]
    60  		dst = dst[x.blockSize:]
    61  	}
    62  }
    63  
    64  func (x *cbcEncrypter) SetIV(iv []byte) {
    65  	if len(iv) != len(x.iv) {
    66  		panic("cipher: incorrect length IV")
    67  	}
    68  	copy(x.iv, iv)
    69  }
    70  
    71  type cbcDecrypter cbc
    72  
    73  // NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining
    74  // mode, using the given Block. The length of iv must be the same as the
    75  // Block's block size and must match the iv used to encrypt the data.
    76  func NewCBCDecrypter(b Block, iv []byte) BlockMode {
    77  	if len(iv) != b.BlockSize() {
    78  		panic("cipher.NewCBCDecrypter: IV length must equal block size")
    79  	}
    80  	return (*cbcDecrypter)(newCBC(b, iv))
    81  }
    82  
    83  func (x *cbcDecrypter) BlockSize() int { return x.blockSize }
    84  
    85  func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
    86  	if len(src)%x.blockSize != 0 {
    87  		panic("crypto/cipher: input not full blocks")
    88  	}
    89  	if len(dst) < len(src) {
    90  		panic("crypto/cipher: output smaller than input")
    91  	}
    92  	for len(src) > 0 {
    93  		x.b.Decrypt(x.tmp, src[:x.blockSize])
    94  		for i := 0; i < x.blockSize; i++ {
    95  			x.tmp[i] ^= x.iv[i]
    96  			x.iv[i] = src[i]
    97  			dst[i] = x.tmp[i]
    98  		}
    99  
   100  		src = src[x.blockSize:]
   101  		dst = dst[x.blockSize:]
   102  	}
   103  }
   104  
   105  func (x *cbcDecrypter) SetIV(iv []byte) {
   106  	if len(iv) != len(x.iv) {
   107  		panic("cipher: incorrect length IV")
   108  	}
   109  	copy(x.iv, iv)
   110  }