AES CTR原理

来源:互联网 发布:1.12魔兽世界数据库 编辑:程序博客网 时间:2024/06/04 00:23

AES CTR原理

AES CTR加解密相关描述:(摘自wiki,下面的原理图比较直观)

Counter (CTR)

CTRCounterEncryption parallelizable:YesDecryption parallelizable:Yes
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做异或运算.

重复以上操作。


CTR encryption 2.svg


实现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


/* NOTE: CTR mode is big-endian.  The rest of the AES code * is endian-neutral. *//* increment counter (128-bit int) by 2^64 */static void AES_ctr128_inc(unsigned char *counter) {unsigned long c;/* Grab 3rd dword of counter and increment */#ifdef L_ENDIANc = GETU32(counter + 8);c++;PUTU32(counter + 8, c);#elsec = GETU32(counter + 4);c++;PUTU32(counter + 4, c);#endif/* if no overflow, we're done */if (c)return;/* Grab top dword of counter and increment */#ifdef L_ENDIANc = GETU32(counter + 12);c++;PUTU32(counter + 12, c);#elsec = GETU32(counter +  0);c++;PUTU32(counter +  0, c);#endif}/* The input encrypted as though 128bit counter mode is being * used.  The extra state information to record how much of the * 128bit block we have used is contained in *num, and the * encrypted counter is kept in ecount_buf.  Both *num and * ecount_buf must be initialised with zeros before the first * call to AES_ctr128_encrypt(). */void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,const unsigned long length, const AES_KEY *key,unsigned char counter[AES_BLOCK_SIZE],unsigned char ecount_buf[AES_BLOCK_SIZE],unsigned int *num) {unsigned int n;unsigned long l=length;assert(in && out && key && counter && num);assert(*num < AES_BLOCK_SIZE);n = *num;while (l--) {if (n == 0) {AES_encrypt(counter, ecount_buf, key);AES_ctr128_inc(counter);}*(out++) = *(in++) ^ ecount_buf[n];n = (n+1) % AES_BLOCK_SIZE;}*num=n;}


如果你的程序需要支持decypt的第一个block不是从0开始,即void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
const unsigned long length, const AES_KEY *key,
unsigned char counter[AES_BLOCK_SIZE],
unsigned char ecount_buf[AES_BLOCK_SIZE],
unsigned int *num)中的num>0,  num<AES_BLOCK_SIZE,

此时就需要对AES_ctr128_encrypt做一次封装


void AES_ctr128_encrypt_with_offset(const unsigned char *in, unsigned char *out,
const unsigned long length, const AES_KEY *key,
unsigned char iv[AES_BLOCK_SIZE],
unsigned int  block_offset)

{

       if(block_offset <0 || block_offset >= AES_BLOCK_SIZE)

      {

return;

       }

       unsigned char ecount_buf[AES_BLOCK_SIZE];

      unsigned char counter[AES_BLOCK_SIZE];

       memset(ecount_buf,0,AES_BLOCK_SIZE);

      memcpy(counter,iv,AES_BLOCK_SIZE)

        if(block_offset >0 && block_offset < AES_BLOCK_SIZE )

       {

AES_encrypt(counter, ecount_buf, key);
AES_ctr128_inc(counter);

      }

      int block_offset_cur = block_offset ;

     AES_ctr128_encrypt(in,out,length,key,&block_offset );

}

参考文献:http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation

http://www.opensource.apple.com/source/OpenSSL/OpenSSL-22/openssl/crypto/aes/aes_ctr.c


原创粉丝点击