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

     1  // Copyright 2010 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  // CFB (Cipher Feedback) Mode.
     6  
     7  package cipher
     8  
     9  type cfb struct {
    10  	b       Block
    11  	out     []byte
    12  	outUsed int
    13  	decrypt bool
    14  }
    15  
    16  // NewCFBEncrypter returns a Stream which encrypts with cipher feedback mode,
    17  // using the given Block. The iv must be the same length as the Block's block
    18  // size.
    19  func NewCFBEncrypter(block Block, iv []byte) Stream {
    20  	if len(iv) != block.BlockSize() {
    21  		panic("cipher.NewCBFEncrypter: IV length must equal block size")
    22  	}
    23  	return newCFB(block, iv, false)
    24  }
    25  
    26  // NewCFBDecrypter returns a Stream which decrypts with cipher feedback mode,
    27  // using the given Block. The iv must be the same length as the Block's block
    28  // size.
    29  func NewCFBDecrypter(block Block, iv []byte) Stream {
    30  	if len(iv) != block.BlockSize() {
    31  		panic("cipher.NewCBFEncrypter: IV length must equal block size")
    32  	}
    33  	return newCFB(block, iv, true)
    34  }
    35  
    36  func newCFB(block Block, iv []byte, decrypt bool) Stream {
    37  	blockSize := block.BlockSize()
    38  	if len(iv) != blockSize {
    39  		return nil
    40  	}
    41  
    42  	x := &cfb{
    43  		b:       block,
    44  		out:     make([]byte, blockSize),
    45  		outUsed: 0,
    46  		decrypt: decrypt,
    47  	}
    48  	block.Encrypt(x.out, iv)
    49  
    50  	return x
    51  }
    52  
    53  func (x *cfb) XORKeyStream(dst, src []byte) {
    54  	for i := 0; i < len(src); i++ {
    55  		if x.outUsed == len(x.out) {
    56  			x.b.Encrypt(x.out, x.out)
    57  			x.outUsed = 0
    58  		}
    59  
    60  		if x.decrypt {
    61  			t := src[i]
    62  			dst[i] = src[i] ^ x.out[x.outUsed]
    63  			x.out[x.outUsed] = t
    64  		} else {
    65  			x.out[x.outUsed] ^= src[i]
    66  			dst[i] = x.out[x.outUsed]
    67  		}
    68  		x.outUsed++
    69  	}
    70  }