• CCM加密学习


    这几天终于搞定了AES硬件加密工具的使用,几种简单的加密模式也都实验通过了,比较麻烦的一种是CCM模式的加密,它是CTR加密模式和CMAC认证算法的混合使用。本文先介绍CCM模式的原理与基本实现,然后结合OpenSSL的加密库,了解一下具体过程,最后,在AES硬件加密引擎上实现。

    CCM介绍

    CCM是CTR加密模式和CMAC认证算法的混合使用,常用在需要同时加密和认证的领域,比如WiFi安全中的WPE协议,它就使用了AES-CCM模式。

    CCM首先使用CBC-MAC模式来认证传输帧,然后使用CTR模式来加密帧。在这里,用于加密的初始化向量IV构成结构如下:

    image

    sequence counter表示在一个帧中16个字节块的数目. Flags域结构如下:

    image

    Bit7设置为0,Adata为1的话,表示此帧有额外的认证数据,为0则表示没有额外的认证数据。M为认证域长度经过转换后的结果.L固定为1. 在不同的安全模式下,初始化向量中的Flags值不同。image从上表可以看出,只要有MIC的存在,那么Adata就必须为1.

    首先引入两个CCM模式下的两个参数:

    L : 长度域,取值为2~8, OpenSSL中缺省为8

    M  :  tag的长度,可选范围为4,6,8,10,12,14,16.OpenSSL中缺省为12

    接下来,将详细描述如何在硬件加密模块上实现CCM模式的认证和加密。

    在硬件AES加密引擎上面,没有完整的实现CCM模式的加密,需要软硬件一起配合,才能实现CCM模式。

    在CCM模式下CBC-MAC

    对于待加密数据中的前数据块,采用CBC-MAC模式加密生成认证域,对于最后一个数据块,需要改为使用CBC模式加密。当最后一个数据块载入AES硬件加密引擎后,从AES读出的就是消息的MAC校验码。

    在CCM模式下CTR

    以下是认证执行的步骤。

    1. 载入加密密钥

    2. 载入全0的初始化向量

    3. 构建一个16个字节的数组B,其第一个元素B[0]需要有如下的构造。

    image

    其中,Flag的值和安全级别有关系,具体关系间下表。

    image

    其他内容元素按规则来填充。

    4. 按照16字节加密块来划分,第一个块填充初始化向量,第二个块填充Adata相关内容,第三个块(或者更多块)填充明文内容

    5. 先按照CBC_MAC模式加密前N-1个块,最后一个数据块使用CBC模式来加密.当认证域长度为16时,CBC_MAC加密后的内容是不变的,如果不为16,则高M字节内容保持不变,其余字节变为0.

    6. 等待加密完成后,从结果中,读出Mval个字节到Cstate就可以了。

    函数头说明:

    void Test_SSP_CCM_Auth (uint8 Mval,     // 认证域字节长度 [0,4,8,16]

                                         uint8 *N,       // N 指向13字节的随机数

                                         uint8 *M,   // M 指向明文的指针

                                         uint16 len_m, // len_m 明文长度

                                         uint8 *A,       // A 指向Adata的指针
                                              uint16 len_a,  // len_a 数据长度

                                         uint8 *AesKey,  //AesKey 指向密钥的指针

                                         uint8 *Cstate)   //输出Cstate 缓存

    加密步骤:

    CCM模式下的加密,需要使用前面生产的Cstate值,具体使用步骤如下:

    加密也需要初始化向量,其构成如下:

    image

    当在OFB模式,将认证域加密生产U时,CTR的值必须为0,当在CTR模式,CTR的值必须不为0

    1. 创建A块,并按照规则来填充A[0],当做后的IV

    2. 创建T块,将Cstate的前Mval填充到T中。

    3.分配缓存,用于填充输入明文,不足16字节的补0.

    4. 以OFB模式,将明文T加密输出到Cstate[也叫做U]。当认证域长度为16时,上传缓存内容保持不变,如果不为16,则上传内容的高M位保持不变,其余字节变为0.结果为U.

    5. 以CTR模式,将IV最高字节设置为1,重新载入IV,然后加密明文缓存块

    6. 最后的结果,是输出的密文块加上U,都是16字节对齐的。

    void Test_SSP_CCM_Encrypt (uint8 Mval,   //认证域字节长度 [0,4,8,16]

                                             uint8 *N,     //指向13个字节的随机数指针

                                             uint8 *M,    //指向待加密明文 (明文输出也在这里,多加16个字节的空间)

                                             uint16 len_m,    //待加密明文长度
                                                  uint8 *AesKey,  //AekKey密钥指针

                                             uint8 *Cstate)   //明文的认证域内容

    从目前浅显的理解上来看,CCM的认证和加密好像是相互独立设置的,从逻辑上,一段明文进来,先通过认证,产生一个tag,在后续加密时使用此Tag和IV生成一个新的校验U.原负载明文填充满后,通过CTR模式来加密数据,在密文的后面附上新的校验码U,这样,就完成了校验和加密的过程。

    ---------------今天就先介绍到这里,还有解密过程和代码没贴上来,周一来了再贴-----------------------

    -------------------周一来了,整理剩下的代码---------------------------------------------------

    解密的过程和加密的相反,先解密,再解认证。

    void Test_SSP_CCM_Decrypt (uint8 Mval,     //认证域长度

                    uint8 *N,       //随机数

                    uint8 *C,      //待解密密文指针

                    uint16 len_c,    //待解密密文长度
                                                   uint8 *AesKey,        //解密密钥

                    uint8 *Cstate)         //认证域内容

    解密流程:

    1. 先利用随机数,构造A向量

    2.   从待解密密文中提取最后Mval字节(补全16个字节)到U向量中

    3. 通过OFB模式,来将U解密成T

    4.   通过CTR模式,将密文解密成明文

    5. 最后,将T附加在明文后

    鉴权的过程是利用上述解密出来的明文,全场为len_c,认证域长度位为Mval,位置在字节的尾端,鉴权就是把解密的明文,通过(len_c-Mval)长度鉴权计算,把得到的结果和解密输出的结果进行对比,如果相同,则鉴权成功,否则,鉴权失败。

    参考资料:openssl学习之ccm,gcm 模式

  • 相关阅读:
    Caused by: org.xml.sax.SAXParseException: The content of elements must consist of well-formed charac
    java反射方法
    错误解决:There is no getter for property named 'id' in class 'java.lang.String'
    java的AOP
    Java预置的注解
    mysql 数据库自动备份
    微信小程序
    关于 IOC和spring基本配置详解
    关于Spring配置的一些东西
    关于Spring的一点东西
  • 原文地址:https://www.cnblogs.com/cherishui/p/4031834.html
Copyright © 2020-2023  润新知