github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/src/crypto/cipher/ofb.go (about)

     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  }