Home | History | Annotate | Download | only in cipher
      1 // Copyright 2011 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 // OFB (Output Feedback) Mode.
      6 
      7 package cipher
      8 
      9 type ofb struct {
     10 	b       Block
     11 	cipher  []byte
     12 	out     []byte
     13 	outUsed int
     14 }
     15 
     16 // NewOFB returns a Stream that encrypts or decrypts using the block cipher b
     17 // in output feedback mode. The initialization vector iv's length must be equal
     18 // to b's block size.
     19 func NewOFB(b Block, iv []byte) Stream {
     20 	blockSize := b.BlockSize()
     21 	if len(iv) != blockSize {
     22 		panic("cipher.NewOFB: IV length must equal block size")
     23 	}
     24 	bufSize := streamBufferSize
     25 	if bufSize < blockSize {
     26 		bufSize = blockSize
     27 	}
     28 	x := &ofb{
     29 		b:       b,
     30 		cipher:  make([]byte, blockSize),
     31 		out:     make([]byte, 0, bufSize),
     32 		outUsed: 0,
     33 	}
     34 
     35 	copy(x.cipher, iv)
     36 	return x
     37 }
     38 
     39 func (x *ofb) refill() {
     40 	bs := x.b.BlockSize()
     41 	remain := len(x.out) - x.outUsed
     42 	if remain > x.outUsed {
     43 		return
     44 	}
     45 	copy(x.out, x.out[x.outUsed:])
     46 	x.out = x.out[:cap(x.out)]
     47 	for remain < len(x.out)-bs {
     48 		x.b.Encrypt(x.cipher, x.cipher)
     49 		copy(x.out[remain:], x.cipher)
     50 		remain += bs
     51 	}
     52 	x.out = x.out[:remain]
     53 	x.outUsed = 0
     54 }
     55 
     56 func (x *ofb) XORKeyStream(dst, src []byte) {
     57 	for len(src) > 0 {
     58 		if x.outUsed >= len(x.out)-x.b.BlockSize() {
     59 			x.refill()
     60 		}
     61 		n := xorBytes(dst, src, x.out[x.outUsed:])
     62 		dst = dst[n:]
     63 		src = src[n:]
     64 		x.outUsed += n
     65 	}
     66 }
     67