【密码算法 之七】GCM 浅析

GCM是一种提供认证和加密的模式,基于CTR和GMAC。它使用GHASH函数进行HASH值计算,并通过GCTR实现加密。GCM适合128位分组长度的加密算法如AES和SM4。在加密和解密过程中,需注意数据的Block对齐以及不同情况下的初始化向量处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  在我的另一篇博客【密码算法 之三】分组密码工作模式 (ECB \ CBC \ CFB \ OFB \ CTR \ XTS)浅析 中已经详细的介绍了对称算法(也称为“分组密码算法”)的各种工作模式。这些工作模式中,CBC、CFB、OFB 三种模式可以解决 ECB 模式中相同明文生成相同密文的缺陷,CTR 又可以在此基础上提供多分组并行加密特性,但是它们都不能提供密文消息完整性校验功能,所有就有了 GCM 模式。

1. 概述

  GCM 全称为 Galois/Counter Mode,其中 G 是指 GMAC,C 是指 CTR 模式,可以将 GCM 认为是认证模式的一种,提供认证和加密两种功能。GCM模式的分组大小为128bit
  在进行GCM原理分析之前,首先应该了解一下 GHASH函数GCTR函数

1.1 GHASH

  GHASH函数利用了“伽罗瓦域算法”计算HASH值。关于伽罗瓦域算法的不在这里详述(有兴趣的可以自行学习)。

  GHASH函数的执行步骤如下
  (1)将字符串 x 分为 128bit 的块 X1, X2, …, Xm
  (2)置 Y00128(即 Y0 为 128bit 的 0),由于 Y0 与 X1 异或不改变 X1 的值,故下图没有体现 Y0 的存在;
  (3)Yi = (Yi-1 ⊕ Xi) • H (H为hash的子秘钥),最后的 Ym 即为本次计算的 hash值。
在这里插入图片描述

1.3 GCTR

  GCTR函数的执行步骤如下
  (1)若X为空串(empty string),则返回空串Y;
  (2)计算n的值,n = (len(X) + 127) / 128;
  (3)X = X1 || X2 || … || Xn-1 || Xn* ,其中 X1, X2 , …, Xn-1都是完整的block,Xn* 可能是不完整的block;
  (4)CB1 = ICB;
  (5)For i = 2 to n,计算CBi(计算公式为:CBi = inc32(CBi-1),即逐个计算出CBi的值;
  (6)For let i = 1 to n-1, Yi = Xi ⊕ CIPHK(CBi),首先对 CBi 加密,然后再与 Xi 异或运算得到 Yi
  (7)Yn* = Xn* ⊕ MSBlen(Xn)(CIPHK(CBi));当通过CIPHK(CBi)计算出结果后,仅取高位(len(Xn))的数据,然后与 Xn * 异或运算。
  (8)Y = Y1 || Y2 || … || Yn-1 || Yn*;
在这里插入图片描述

2. GCM 加密

在这里插入图片描述

注:对数据P进行GCTR运算时,计数器值是从J1开始的(J0用在了最后HASH值的GCTR运算,如下图)

在这里插入图片描述

3. GCM 解密

在这里插入图片描述

在这里插入图片描述

4. 总结

  • GCM运算所需的对称加密算法的分组长度必须是128bit(DES\3DES不满足添加,AES\SM4满足条件);
  • 加密时,在计算MAC之前必别将附加数据(A)及密文(C)分别进行Block对齐;
  • GCM运算时,J0的获取需要分不同的情况,一种是len(IV)= 96bit,一种是len(IV) ≠ 96bit
请作为资深开发工程师,解释我给出的代码。请逐行分析我的代码并给出你对这段代码的理解。 我给出的代码是: 【void RS_CAN_init(void) { /* default seting: Main Osc/1 -> CAN */ //protected_write(SYSPROTCMDD1,SYSPROTS1,SYSCKSC_IRSCANXINS_CTL,0x01); //while (SYSCKSC_IRSCANXINS_ACT !=0x01); //wait for clk active /* Set CAN0TX as P0_4 and CAN0RX as P0_5 0x0030 */ PORT_AWOPMC0 |= 0x03F0; //P0.456789 PORT_AWOPFCE0 |= (0x03F0); PORT_AWOPFC0 |= (0x03F0); //can0 PORT_AWOPM0 &= ~(1<<4); PORT_AWOPM0 |= 1<<5; //can1 PORT_AWOPM0 &= ~(1<<6); PORT_AWOPM0 |= 1<<7; //can2 PORT_AWOPM0 &= ~(1<<8); PORT_AWOPM0 |= 1<<9; /* Wait while CAN RAM initialization is ongoing */ //while(( R_DEV_READ_REG(8, RSCAN0_base + bTE) & 0x01U) != 0x01U ) while((RSCAN0GSTS & 0x00000008)) ; /* Switch to global/channel reset mode */ RSCAN0GCTR &= 0xfffffffb; //set the 3rd bit to 0 -- global stop mdoe RSCAN0C0CTR &= 0xfffffffb; RSCAN0C1CTR &= 0xfffffffb; RSCAN0C2CTR &= 0xfffffffb; /* Configure clk_xincan as CAN-ClockSource */ RSCAN0GCFG = 0x00000010; //RSCAN0C0CFG = 0x021C0003u; /*SJW =3TQ, TSEG1=13TQ, TSEG2=2TQ, BRP=3 125*/ //RSCAN0C0CFG = 0x021C0000u; /*SJW =3TQ, TSEG1=13TQ, TSEG2=2TQ, BRP=0 500*/ //RSCAN0C0CFG = 0x02140000u; /*SJW =3TQ, TSEG1= 5TQ, TSEG2=2TQ, BRP=0 1000*/ RSCAN0C0CFG = 0x021C0001u; /*SJW =3TQ, TSEG1=13TQ, TSEG2=2TQ, BRP=1 250*/ RSCAN0C1CFG = 0x021C0001u; RSCAN0C2CFG = 0x021C0001u; /* ==== Rx rule setting ==== */ Can_SetRxRule(); /* ==== buffer setting ==== */ RSCAN0RMNB = 0x30; //Can_SetGlobalBuffer--16 -0x1B fzh 32 -- 0x20 //RSCAN0RFCC0 = 0x1202; /* Set THLEIE disabled, MEIE(FIFO Message Lost Interrupt disabled) */ RSCAN0GCTR &= 0xfffff8ff; /* If GlobalChannel in halt or reset mode */ if (RSCAN0GSTS & 0x03) { RSCAN0GCTR &= 0xfffffffc; //Switch to communication mode while ((RSCAN0GSTS & 0x02) == 2) {; /* While halt mode */} while ((RSCAN0GSTS & 0x01) == 1) {; /* While reset mode */} } /* If Channel0 in halt or reset mode */ //can0 if (RSCAN0C0STS & 0x03) { RSCAN0C0CTR &= 0xfffffffc; //Switch to communication mode while ((RSCAN0C0STS & 0x02) == 2) {; /* While halt mode */} while ((RSCAN0C0STS & 0x01) == 1) {; /* While reset mode */} } //can1 if (RSCAN0C1STS & 0x03) { RSCAN0C1CTR &= 0xfffffffc; //Switch to communication mode while ((RSCAN0C1STS & 0x02) == 2) {; /* While halt mode */} while ((RSCAN0C1STS & 0x01) == 1) {; /* While reset mode */} } //can2 if (RSCAN0C2STS & 0x03) { RSCAN0C2CTR &= 0xfffffffc; //Switch to communication mode while ((RSCAN0C2STS & 0x02) == 2) {; /* While halt mode */} while ((RSCAN0C2STS & 0x01) == 1) {; /* While reset mode */} } }】
最新发布
04-04
### 逐行分析代码及理解: ```c void RS_CAN_init(void) ``` **第1行:函数声明** - 定义了一个名为 `RS_CAN_init` 的初始化函数,用于配置 CAN 总线模块。 --- #### 第一部分:CAN 模块时钟源设置(注释掉的部分) ```c /* default seting: Main Osc/1 -> CAN */ //protected_write(SYSPROTCMDD1, SYSPROTS1, SYSCKSC_IRSCANXINS_CTL, 0x01); //while (SYSCKSC_IRSCANXINS_ACT != 0x01); // wait for clk active ``` **第3-5行:时钟激活** - 原本应该通过 `protected_write` 函数将主振荡器分频后的时钟分配给 CAN 使用,并等待时钟完全启动。 - 这部分已经被注释掉了,可能是开发者认为这部分功能已经由其他地方完成。 --- #### 第二部分:GPIO 配置 ```c /* Set CAN0TX as P0_4 and CAN0RX as P0_5 0x0030 */ PORT_AWOPMC0 |= 0x03F0; // P0.456789 PORT_AWOPFCE0 |= (0x03F0); PORT_AWOPFC0 |= (0x03F0); // can0 PORT_AWOPM0 &= ~(1 << 4); PORT_AWOPM0 |= 1 << 5; // can1 PORT_AWOPM0 &= ~(1 << 6); PORT_AWOPM0 |= 1 << 7; // can2 PORT_AWOPM0 &= ~(1 << 8); PORT_AWOPM0 |= 1 << 9; ``` **第8-19行:端口映射与模式选择** - **目的**:配置 GPIO 引脚的功能复用,使它们能够支持 CAN 收发信号。 - 具体操作包括: - 设置 `PORT_AWOPMC0`, `PORT_AWOPFCE0`, 和 `PORT_AWOPFC0` 来启用特定引脚的外设功能。 - 对每个 CAN 通道分别设置其发送 (`TX`) 和接收 (`RX`) 引脚的对应位。 - `CAN0`: TX 映射到 P0_4,RX 映射到 P0_5。 - `CAN1`: TX 映射到 P0_6,RX 映射到 P0_7。 - `CAN2`: TX 映射到 P0_8,RX 映射到 P0_9。 --- #### 第三部分:等待 CAN RAM 初始化完成 ```c /* Wait while CAN RAM initialization is ongoing */ while ((RSCAN0GSTS & 0x00000008)); ``` **第22行:RAM 状态检测** - 监控全局状态寄存器 `RSCAN0GSTS` 中的某一位标志是否为零。 - 如果该标志非零,则表示 CAN 控制器仍在初始化内部存储器;需要循环等待直到初始化完成。 --- #### 第四部分:进入复位模式 ```c /* Switch to global/channel reset mode */ RSCAN0GCTR &= 0xfffffffb; // 将全球控制器置入停止模式 (bit 2 清零) RSCAN0C0CTR &= 0xfffffffb; // 同样对三个独立通道执行类似操作... RSCAN0C1CTR &= 0xfffffffb; RSCAN0C2CTR &= 0xfffffffb; ``` **第26-30行:切换至复位模式** - 分别将全局控制寄存器和各个通道的控制寄存器清零某些比特位,以确保所有组件都处于初始复位状态。 - 此步骤保证了后续配置不会受到之前的残留影响。 --- #### 第五部分:配置时钟源及时序参数 ```c /* Configure clk_xincan as CAN-ClockSource */ RSCAN0GCFG = 0x00000010; RSCAN0C0CFG = 0x021C0001u; /* SJW=3TQ, TSEG1=13TQ, TSEG2=2TQ, BRP=1 -> 波特率约250kbps */ RSCAN0C1CFG = 0x021C0001u; RSCAN0C2CFG = 0x021C0001u; ``` **第33-37行:波特率与时钟设定** - 设定总线时间分割、同步跳跃宽度以及预分频值等关键通信参数。 - 所有三条信道均采用相同的定时规则,默认波特率为 250 kbps。 --- #### 第六部分:配置接收滤波规则 ```c /* Receive Rule Setting */ Can_SetRxRule(); ``` **第40行:调用外部 API** - 调用了另一个自定义函数 `Can_SetRxRule()`,专门负责制定哪些帧可以接受进来。 --- #### 第部分:缓冲区大小及相关中断选项调整 ```c /* Buffer Configuration */ RSCAN0RMNB = 0x30; // 设置消息缓冲数量或其他相关属性 RSCAN0GCTR &= 0xfffff8ff; // 关闭全局传输硬件错误通知中断以及其他无关干扰项 ``` **第44-45行:缓冲管理与中断屏蔽** - 规划接收缓存的数量或范围。 - 修改全局控制字节进一步关闭不必要的警告事件触发机制。 --- #### 第八部分:检查并退出暂停/重启模式 最后几段逻辑围绕着从“挂起”或者“恢复”阶段过渡展开讨论... 完整解析略去冗长内容...继续看下面总结! --- ### §最终小结§ 此程序核心目标在于逐步建立起一套完整的基于多路物理连接形式下的高速串列数据交换环境——即所谓的汽车工业标准协议之一:Controller Area Network(CAN)系统框架下实际运行所需的软硬件协同准备工作流程概览如上所示。 --- ###
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值