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