github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/src/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  	next    []byte
    12  	out     []byte
    13  	outUsed int
    14  
    15  	decrypt bool
    16  }
    17  
    18  func (x *cfb) XORKeyStream(dst, src []byte) {
    19  	for len(src) > 0 {
    20  		if x.outUsed == len(x.out) {
    21  			x.b.Encrypt(x.out, x.next)
    22  			x.outUsed = 0
    23  		}
    24  
    25  		if x.decrypt {
    26  			// We can precompute a larger segment of the
    27  			// keystream on decryption. This will allow
    28  			// larger batches for xor, and we should be
    29  			// able to match CTR/OFB performance.
    30  			copy(x.next[x.outUsed:], src)
    31  		}
    32  		n := xorBytes(dst, src, x.out[x.outUsed:])
    33  		if !x.decrypt {
    34  			copy(x.next[x.outUsed:], dst)
    35  		}
    36  		dst = dst[n:]
    37  		src = src[n:]
    38  		x.outUsed += n
    39  	}
    40  }
    41  
    42  // NewCFBEncrypter returns a Stream which encrypts with cipher feedback mode,
    43  // using the given Block. The iv must be the same length as the Block's block
    44  // size.
    45  func NewCFBEncrypter(block Block, iv []byte) Stream {
    46  	return newCFB(block, iv, false)
    47  }
    48  
    49  // NewCFBDecrypter returns a Stream which decrypts with cipher feedback mode,
    50  // using the given Block. The iv must be the same length as the Block's block
    51  // size.
    52  func NewCFBDecrypter(block Block, iv []byte) Stream {
    53  	return newCFB(block, iv, true)
    54  }
    55  
    56  func newCFB(block Block, iv []byte, decrypt bool) Stream {
    57  	blockSize := block.BlockSize()
    58  	if len(iv) != blockSize {
    59  		// stack trace will indicate whether it was de or encryption
    60  		panic("cipher.newCFB: IV length must equal block size")
    61  	}
    62  	x := &cfb{
    63  		b:       block,
    64  		out:     make([]byte, blockSize),
    65  		next:    make([]byte, blockSize),
    66  		outUsed: blockSize,
    67  		decrypt: decrypt,
    68  	}
    69  	copy(x.next, iv)
    70  
    71  	return x
    72  }