Note: CTR mode (CM) is also known as
integer counter mode
(ICM) and
segmented integer counter
(SIC) mode
Like OFB, counter mode turns a
block cipher
into a
stream cipher
. It generates the next
keystream
block by encrypting successive values of a "counter". The counter can be any function which produces a sequence which is guaranteed not to repeat for a long time, although an actual increment-by-one counter is the simplest and most popular. The usage of a simple deterministic input function used to be controversial; critics argued that "deliberately exposing a cryptosystem to a known systematic input represents an unnecessary risk." By now, CTR mode is widely accepted, and problems resulting from the input function are recognized as a weakness of the underlying block cipher instead of the CTR mode. Along with CBC, CTR mode is one of two block cipher modes recommended by Niels Ferguson and Bruce Schneier.
CTR mode has similar characteristics to OFB, but also allows a random access property during decryption. CTR mode is well suited to operate on a multi-processor machine where blocks can be encrypted in parallel. Furthermore, it does not suffer from the short-cycle problem that can affect OFB.
Note that the
nonce
in this diagram is the same thing as the
initialization vector
(IV) in the other diagrams. The IV/nonce and the counter can be combined together using any lossless operation (concatenation, addition, or XOR) to produce the actual unique counter block for encryption.
中文:(简单解释一下)
计数模式也被称为整数计数模式以及分段块模式。
计数模式和OFB有点相似,它将分块密文转行为流密码。计数模式通过对连续递增的counter加密产生keystream,counter可以被任意函数产生,但是必须保证它在相当长的一段时间内不重复,通常情况下,使用的是加1的方式(即操作一个block后counter加1)。
下图中的nonce和IV具有相同的语义,即nonce=IV,
计数模式可以用下图描述:
用key将counter加密后得到ecounter,然后counter=counter+1,将明文与ecounter做异或运算.
将递增后的counter作为下一次的counter,
用key将counter加密后得到ecounter,然后counter=counter+1,将明文与ecounter做异或运算.
重复以上操作。
实现code:
AES_encrypt是一次ecb encrypt过程。
GETU32(p)已大端方式将一个4字节的char buffer的内容转为int
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
# define GETU32(p) SWAP(*((u32 *)(p)))
# define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
#else
# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
#endif
static void AES_ctr128_inc(unsigned char *counter) {
unsigned long c;
#ifdef L_ENDIAN
c = GETU32(counter + 8);
PUTU32(counter + 8, c);
#else
c = GETU32(counter + 4);
PUTU32(counter + 4, c);
#endif
if (c)
return;
#ifdef L_ENDIAN
c = GETU32(counter + 12);
PUTU32(counter + 12, c);
#else
c = GETU32(counter + 0);
PUTU32(counter + 0, c);
#endif
Ubuntu20.4安装QT6
fredhurui: