AES CCM详解

AES CCM是一种对数据进行加密及完整性检查的算法,主要用到AES中的CBC(完整性检查)和CTR(对明文进行加密),除此之外,还涉及到对数据的格式化(本文着重阐述)

加密过程

在这里插入图片描述

STEPS

在这里插入图片描述
从图中可以观察到,在加密开始时需要传入的有Nonce, AAD(associated data),P(Payload或者叫明文),而从CCM加密流程出来后得到结果C,由加密后的密文和加密后的TAG(或者叫MAC)组成,具体的CBC和CTR是怎么回事在此文不做具体介绍,需要了解的可以看这里

解密及校验过程

在这里插入图片描述

STEPS

在这里插入图片描述
理解了加密过程后,看这个解密过程和校验MAC的过程就会简单不少,对于知道CBC和CTR的同学来说,上方的图不难理解,唯一的盲点在于如何将[N, A, P]这三者格式化成B0, B1, B2,…, Br,下面就详细谈谈这点

格式化

B0的构成

在这里插入图片描述
Flags的组成:
在这里插入图片描述
Flags由以下四部分组成:

  • bit7 Reserved预留为以后扩展,设定为0
  • Adata标记是否有无associated data,1代表有,0代表无
  • bit3-bit5用于编码TAG(或者叫MAC)的长度,比如最终需要8字节的TAG,那么t=8,bit3-bit5被编码为011
  • bit0-bit2用于编码明文长度所占据的字节数,比如q=2,即bit0-bit2编码为001,此时Q占据2字节,Q就是明文的长度,可表示范围0-65535

图中的N代表Nonce,可以发现Nonce的长度和Q的长度相加等于15,这就代表Nonce的数据如果越少,那么可表示明文长度的范围越大,值得注意的是,000编码在Flags的bit3-bit5和bit0-bit2均是不被允许的,即需要满足t >= 4, q >= 2, Len(Nonce) <= 13,CCM中各个长度需要满足的条件如下:

在这里插入图片描述

B0解析举例

在这里插入图片描述

AAD的格式化

在B0之后紧跟着的就是格式化后的AAD(如果B0 Flags中Adata存在) , 由AAD的长度AAD数据补0构成
假设AAD的长度为a字节,对a的格式化如下:
在这里插入图片描述
如果a=2^16,那么编码为11111111 11111110 00000000 00000001 00000000 000000000,在此之后再连接AAD,连接完成后需要补0,补到啥效果呢?即补最少的0,达到格式化后的AAD长度是Block长度(16B)的倍数。也就是说,格式化后的AAD可能会占据多个Block。

Payload的格式化

这个相对而言就比较简单了,就是在Payload后面补最少的0,使得格式化后的Payload长度是Block长度(16字节)的倍数

最终格式化后的数据为B0 || format(AAD) || format(Payload), 明显这最终的数据长度肯定是按Block长度对齐的,满足了CBC加密的要求,那CTR加密过程中的Ctr0, Ctr1,…是怎么构成的呢?

CTRn的组成

在这里插入图片描述
在这里插入图片描述
q是前面B0中的那个q,代表Payload(明文)的长度所占据的空间,i就是Ctrn中的n,从0不断加1,即0,1,2,3…, N就是Nonce


例子

好了,到目前为止应该已经将AES CCM中的细节讲得差不多了,下面举个例子,可以对照着看是否理解上方的流程,如果需要更详细的资料,可以参考这里

在这里插入图片描述

Python验证

from Crypto.Cipher import AES

def aes_ccm_encrypt(key, plaintext, nonce, associated_data):
    cipher = AES.new(key, AES.MODE_CCM, nonce=nonce, mac_len=4)
    cipher.update(associated_data)
    ciphertext, tag = cipher.encrypt_and_digest(plaintext)
    return ciphertext, tag

def aes_ccm_decrypt(key, ciphertext, tag, nonce, associated_data):
    cipher = AES.new(key, AES.MODE_CCM, nonce=nonce, mac_len=4)
    cipher.update(associated_data)
    plaintext = cipher.decrypt_and_verify(ciphertext, tag)
    return plaintext

key = bytes([0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f])
nonce = bytes([0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16])
associated_data = bytes([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07])
plaintext = bytes([0x20, 0x21, 0x22, 0x23])

if __name__ == '__main__':
    # 加密
    ciphertext, tag = aes_ccm_encrypt(key, plaintext, nonce, associated_data)
	print("Ciphertext:", ' '.join('{:02x}'.format(i) for i in ciphertext))
	print("Tag:", ' '.join('{:02x}'.format(i) for i in tag))

    # 解密及验证
    try:
    	decrypted_plaintext = aes_ccm_decrypt(key, ciphertext, tag, nonce, associated_data)
    	print("Decrypted_plaintext:", ' '.join('{:02x}'.format(i) for i in decrypted_plaintext))
	except (ValueError, KeyError) as e:
    	print("Decryption failed:", e)
    	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值