AE:Authenticated encryption
AD:Associated-Data
CBC、各种加密模式在TLS协议中的运用 1、CTR模式
与Mac-then-Encrypt不同,AEAD是整个算法流程,同时保证了数据的私密性和完整性。回想MtE和EtM模式, mac和和cipher都是分别计算的;
CCM其实是Encrypt-and-Mac的变种
密码学相关的书籍是这样的定义CCM的:
其中,CMAC是这么定义的
RFC3610中定义了其具体实现,我们先看RFC中的描述,然后回过头再看流程图。
流程图中,Nonse+ADD+Plain,然后划分成不同的block,送入进行CMAC。
RFC3610中,详细描述了各个block是如何组成的。
The first block B_0 is formatted as follows, where l(m) is encoded in
most-significant-byte first order:
Octet Number Contents
------------ ---------
0 Flags
1 ... 15-L Nonce N
16-L ... 15 l(m)
Within the first block B_0, the Flags field is formatted as follows:
Bit Number Contents
---------- ----------------------
7 Reserved (always zero)
6 Adata
5 ... 3 M'
2 ... 0 L'
上面的描述,翻译成人话就是,首先,一个block是16字节
block0[0] = flag
block0[1 - ivlen-1] = iv
block0[:15] = len(input)
在说仔细点,就是block0的第一个字节是一个flag。第二个字节及其之后的至是IV,RFC规定,AEAD算法中,IV_len是12字节(4+8)。剩余字节,填写input的长度。input长度从最后面开始填。
举个例子,如果input是0xff字节,那么,block[15]就是0xff,如果input是0x1234字节,那么block0[14]=0x12, block[15]=0x34。
至于flag,
bit7保留,写死是0,bit6表示为1,表示有add,为0表示没有add。bit5-3,3个bit,
rfc上这么描述The M' field is set to (M-2)/2
。
套用mbedtls源码描述,block0[0]是这么生成的,详细为什么这么搞,去看RFC3610。
b[0] = 0;
b[0] |= ( add_len > 0 ) << 6;
b[0] |= ( ( tag_len - 2 ) / 2 ) << 3;
b[0] |= (16 - 1 - iv_len) - 1;
至此,block0构造完成了。我们把block0送入AES进行加密。
至此入参IV被处理了。
接着处理add,TLS协议中,add为13字节的header,header的内容和上篇文章描述的相同,具体参考上篇文章。
If 0 < l(a) < (2^16 - 2^8), then the length field is encoded as two
octets which contain the value l(a) in most-significant-byte first
order.
If (2^16 - 2^8) <= l(a) < 2^32, then the length field is encoded as
six octets consisting of the octets 0xff, 0xfe, and four octets
encoding l(a) in most-significant-byte-first order.
If 2^32 <= l(a) < 2^64, then the length field is encoded as ten
octets consisting of the octets 0xff, 0xff, and eight octets encoding
l(a) in most-significant-byte-first order.
由于TLS协议送入的add是13字节,我们遵守第一条If 0 < l(a) < (2^16 - 2^8)
的规矩和即可,即需要构造特殊的2字节的值来描述add长度。
我们定义block1[16]
block1[0] = ( add_len >> 8 ) & 0xFF ;
block1[1] = ( add_len ) & 0xFF ;
block1[2:15]填写add的值即可,然后block1以CBC模式接着送入AES,换句话说,block1需要先与block0被加密后的结果亦或之后,再送入AES。
当然,如果add不止13字节,那么接着把剩余的add拷贝到blockx[0:15]中,进行CBC加密,后面的这些block不需要构造特殊的2字节的值了,直接每16字节送入AES-CBC处理,处理完成为止。只是TLS协议中,不会出现这种情况。
至此,入参add被处理完了。
接着处理input,input的处理比上面都简单,直接按照16字节分块,进行AES-CBC模式处理。
至此,Tag计算完成。
cipher text分为两部分,
(1):第一部分是把plain text送入ctr模式进行AES计算
(2):第二部分就是Tag = ctr(Tag)。
plain txt的ctr模式的counter是这么组成了
Octet Number Contents
------------ ---------
0 Flags
1 ... 15-L Nonce N
16-L ... 15 Counter i
The Flags field is formatted as follows:
Bit Number Contents
---------- ----------------------
7 Reserved (always zero)
6 Reserved (always zero)
5 ... 3 Zero
2 ... 0 L'
Another way say the same thing is: Flags = L'.
换成c语言描述 ctr是这么组成的
q = 16 - 1 - iv_len;
ctr[0] = q - 1;
memcpy( ctr + 1, iv, iv_len );
memset( ctr + 1 + iv_len, 0, q );
ctr[15] = 1;
最后,TAG在进行一次CTR模式加密,由于Tag长度是16,所以计算其实只需要一次,ctr的counter是0,秘钥也就是加密秘钥。
至此,CCM模式加密完成。
CCM模式中,我们依稀还能看到类似AES-HMAC这样的形式,其中CCM模式中的Tag计算,和AES-HMAC的mac计算行为是相似的,只是CCM种是CBC模式的AES计算。这个TAG计算和我们的平时的AES-CBC是基本一样的,唯一不同的是,Tag只取最后一个block,而普通的AES-CBC看到是每个块都保留。所以由此可见,Tag的计算是不可逆的,从而,使得它有了mac的功能。