Glossary

AES-CFB

AES-CFB is the Cipher Feedback mode of AES, which turns the block cipher into a self-synchronizing stream cipher by feeding each ciphertext segment back into the next input. CFB is defined in NIST SP 800-38A. It needs no padding, and the segment size s can be anything from 1 bit to the full 128-bit block.

How it works

The first input block is the IV. AES encrypts the input block, and the leftmost s bits of the output are XORed with the next s bits of plaintext to make a ciphertext segment. The next input block is the previous one shifted left by s bits, with that ciphertext segment placed in the low s bits. Decryption builds the same input blocks from ciphertext, so it also uses only the AES encrypt direction.

  • Segment size: the standard names CFB1 (1 bit), CFB8 (8 bits) and CFB128 (128 bits). OpenSSL has aes-128-cfb1, aes-128-cfb8 and aes-128-cfb, where the plain name means 128-bit segments.
  • Cost: every segment costs one AES call, so CFB8 does 16 times the AES work of CFB128 on the same data.
  • IV: 16 bytes. SP 800-38A requires it to be unpredictable, a stricter rule than the unique-nonce rule for OFB.
  • Parallelism: encryption is serial. Decryption can run in parallel once the input blocks are built from the ciphertext.

The script below corrupts one bit of the first ciphertext block of four.

import warnings; warnings.simplefilter("ignore")
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
key = bytes(range(16))
iv = bytes(range(16))
msg = b"AAAAAAAAAAAAAAAA" b"BBBBBBBBBBBBBBBB" b"CCCCCCCCCCCCCCCC" b"DDDDDDDDDDDDDDDD"
c = bytearray(Cipher(algorithms.AES(key), modes.CFB(iv)).encryptor().update(msg))
c[0] ^= 0x01
p = Cipher(algorithms.AES(key), modes.CFB(iv)).decryptor().update(bytes(c))
for i in range(4):
    print(i + 1, p[16 * i:16 * i + 16])
1 b'@AAAAAAAAAAAAAAA'
2 b'\xbadg\xb5\xc9\xca\xca0\x86\x8et\xc3\x1f\x7f\xb1|'
3 b'CCCCCCCCCCCCCCCC'
4 b'DDDDDDDDDDDDDDDD'

Block 1 has exactly the one flipped bit, block 2 is random bytes, and blocks 3 and 4 are fine. The five bytes "hello" under the same key and IV encrypt to 62f167d92e with CFB128 and 62bfe8a32e with CFB8, and openssl and Node matched both.

How far does a CFB error spread?

A bit error in a ciphertext segment damages that segment in the same bit position and then randomizes the next b/s segments, rounded up, where b is the block size of 128 bits. With 128-bit segments that is one extra block, as shown above. With CFB8 it is 16 extra bytes. SP 800-38A calls this the self-synchronizing property, and Appendix D lists it as the main error difference from OFB and CTR.

Is the AES-CFB IV allowed to repeat?

No. A repeated IV with the same key and first plaintext segment produces the same first ciphertext segment, which leaks that the data starts the same way. SP 800-38A requires an unpredictable IV, so use 16 random bytes per message.

Common pitfalls

  • Mismatched segment sizes: one side using CFB8 and the other CFB128 decrypts to garbage with no error. Check which variant a library means by "CFB".
  • No authentication: the demo changed plaintext with no error. Add HMAC or use AES-GCM.
  • Predictable IVs: a counter or timestamp IV breaks the requirement. Use random bytes.
  • Using CFB1 or CFB8 for bulk data: they are slow, since each bit or byte needs a full AES call.
  • Deprecation warnings: Python cryptography 48 prints "CFB has been moved to cryptography.hazmat.decrepit.ciphers.modes.CFB", and the old import path is removed in 49.0.0. Plan a move to AES-GCM.

Related terms

  • AES — the block cipher CFB wraps.
  • AES-OFB — the sibling feedback mode that feeds back cipher output instead.
  • AES-CTR — a stream mode with parallel encryption and no error spreading.
  • AES-CBC — the chained block mode that needs padding.
  • AES-GCM — authenticated encryption for new designs.
  • HMAC — supplies the integrity check CFB lacks.

See also