当前位置: 首页 > news >正文

AES-128 加密与解密详解

AES-128 加密与解密详解

AES (Advanced Encryption Standard) 是一种对称加密算法,用于保护敏感数据。AES-128 特指使用 128 位密钥长度的 AES 实现。

基本概念

  1. 密钥长度:AES-128 使用 128 位(16 字节)的密钥
  2. 块大小:AES 是分组密码,固定处理 128 位(16 字节)的数据块
  3. 轮数:AES-128 包含 10 轮转换
  4. 状态矩阵:AES 将 16 字节数据组织为 4×4 字节矩阵

AES-128 加密过程

AES-128 加密过程包含以下步骤:

  1. 密钥扩展:从原始 128 位密钥生成 11 个轮密钥(每轮一个,加上初始轮)

    • 原始128位密钥被视为前4个32位字(W[0]到W[3])
    • 通过迭代计算过程生成总共44个字(W[0]到W[43])
    • 每4个字组成一个轮密钥(128位)
    • 密钥扩展算法:
      对于i从4到43:如果(i % 4 == 0):W[i] = W[i-4] ⊕ SubWord(RotWord(W[i-1])) ⊕ Rcon[i/4]否则:W[i] = W[i-4] ⊕ W[i-1]
      
    • SubWord:对4字节进行S盒替换
    • RotWord:字节循环左移
    • Rcon:轮常量,引入非线性
  2. 初始轮:将原始数据与第一个轮密钥进行异或操作

    • 这是一个简单的字节级异或操作
    • 如果明文块为M,初始轮密钥为K₀,则运算为:状态 = M ⊕ K₀
    • 该操作使得加密从一开始就依赖于密钥
  3. 9 个标准轮:每个标准轮包含四个步骤:

    • SubBytes:使用 S 盒(替换表)将每个字节替换为另一个字节

      • 每个字节被视为GF(2⁸)上的元素
      • 先计算乘法逆元(除了0映射到自身)
      • 再进行仿射变换:b’ᵢ = b’ᵢ ⊕ b’(ᵢ+4)mod8 ⊕ b’(ᵢ+5)mod8 ⊕ b’(ᵢ+6)mod8 ⊕ b’(ᵢ+7)mod8 ⊕ c
      • S盒是预先计算好的256字节查找表,提供非线性保护
      • 防御线性密码分析和差分密码分析
    • ShiftRows:对状态矩阵的行进行循环左移

      • 第0行不移动
      • 第1行左移1字节:[r1c0, r1c1, r1c2, r1c3] → [r1c1, r1c2, r1c3, r1c0]
      • 第2行左移2字节:[r2c0, r2c1, r2c2, r2c3] → [r2c2, r2c3, r2c0, r2c1]
      • 第3行左移3字节:[r3c0, r3c1, r3c2, r3c3] → [r3c3, r3c0, r3c1, r3c2]
      • 此步骤提供行间扩散,确保列间的数据混合
    • MixColumns:对状态矩阵的列进行混合操作

      • 将每列视为GF(2⁸)上的多项式
      • 与固定多项式c(x) = 3x³ + x² + x + 2相乘
      • 具体矩阵运算:
        [ 2 3 1 1 ]   [ s₀,c ]    [ s'₀,c ]
        [ 1 2 3 1 ] × [ s₁,c ] = [ s'₁,c ]
        [ 1 1 2 3 ]   [ s₂,c ]    [ s'₂,c ]
        [ 3 1 1 2 ]   [ s₃,c ]    [ s'₃,c ]
        
      • 例如:s’₀,c = (2·s₀,c) ⊕ (3·s₁,c) ⊕ s₂,c ⊕ s₃,c
      • 运算在GF(2⁸)上进行,乘法是多项式乘法模x⁸+x⁴+x³+x+1
      • 此步骤为算法提供列间高扩散性
    • AddRoundKey:将当前轮密钥与状态矩阵进行异或

      • 简单字节级异或操作:状态 = 状态 ⊕ 轮密钥[轮数]
      • 每轮使用不同的轮密钥,增加密码强度
      • 为算法引入密钥依赖性
  4. 最终轮:只执行 SubBytes、ShiftRows 和 AddRoundKey,不包含 MixColumns

    • 省略MixColumns操作可以使加密和解密结构更对称
    • 不影响安全性,因为之前9轮已提供足够扩散
    • 最后轮密钥使状态变为最终密文输出

AES-128 解密过程

AES-128 解密本质上是加密的逆过程:

  1. 密钥扩展:同加密过程,生成相同的轮密钥
  2. 初始轮:将密文与最后一个轮密钥进行异或操作
  3. 9 个标准轮:每个标准轮包含四个反向步骤:
    • InvShiftRows:对状态矩阵的行进行循环右移
    • InvSubBytes:使用逆 S 盒将每个字节替换回原字节
    • AddRoundKey:将当前轮密钥与状态矩阵进行异或
    • InvMixColumns:对状态矩阵的列进行逆混合操作
  4. 最终轮:只执行 InvShiftRows、InvSubBytes 和 AddRoundKey(与第一个轮密钥)

CBC 模式工作原理

在代码中使用的是 AES-CBC 模式(Cipher Block Chaining):

  1. 加密过程
    • 第一个明文块与初始向量 (IV) 进行异或,然后使用 AES 加密
    • 后续明文块与前一个密文块异或后再加密
    • 每个密文块都依赖于前面所有的明文块
    IV  ↓⊕ → AES-Encrypt → 密文块1↗       ↓
明文块1     ⊕ → AES-Encrypt → 密文块2↗       ↓明文块2   ...
  1. 解密过程
    • 对密文块使用 AES 解密,然后与初始向量或前一个密文块异或得到明文
    • 第一个密文块解密后与 IV 异或得到第一个明文块
    • 后续密文块解密后与前一密文块异或得到相应的明文块
    密文块1 → AES-Decrypt → ⊕ → 明文块1↓                    ↑密文块2 → AES-Decrypt → ⊕ → 明文块2↓                    ↑...                  IV

AES-CBC 初始向量(IV)的重要性

在 AES-CBC 模式中,初始向量(IV)扮演着至关重要的角色,它不是可选项,而是安全必需品。以下是初始向量存在的几个关键原因:

1. 打破加密的确定性

如果没有初始向量,相同的明文使用相同密钥加密总会产生相同的密文。这会带来严重安全隐患:

  • 攻击者可以发现重复模式,推断出明文内容的相似性
  • 相同数据的加密结果相同,可能泄露信息模式,尤其是在结构化数据中

初始向量通过与第一个明文块异或操作,引入随机性,即使相同明文和密钥也会产生完全不同的密文。

2. 防止字典攻击

没有IV的CBC模式会使预计算攻击变得可行。攻击者可以构建常见明文块到密文块的映射表(即"字典")。有了IV,即使是预先知道的明文,也会因IV的不同而产生不同密文,使此类攻击无效。

3. 保证语义安全

IV确保了即使加密相同的数据多次,每次产生的密文也完全不同,这是语义安全的基本要求之一。这防止了攻击者从多次加密中推断出任何有关明文的信息。

4. 中和CBC链式特性的首块问题

CBC模式的特点是每个明文块与前一个密文块异或后再加密,但第一个明文块没有"前一个密文块"。IV恰好解决了这个问题,为第一块提供了异或操作所需的输入值。

5. IV的选择原则

IV的使用有几个关键原则:

  • 唯一性:每次加密操作应使用不同的IV
  • 不可预测性:对于需要高安全性的应用,IV应该是随机生成的
  • 公开性:IV一般不需要保密,通常与密文一起存储或传输
  • 固定长度:IV长度必须与加密块大小相同(AES为16字节)
6. 不同应用场景中的IV处理
  1. 通信协议

    • IV通常作为消息头的一部分发送
    • 每个会话或每条消息使用不同IV
  2. 文件加密

    • IV常存储在文件头部
    • 每个文件使用不同IV
  3. 固件加密

    • 在可信固件更新中,IV可以是:
      • 完全随机生成(最安全)
      • 基于版本号派生(便于版本控制)
      • 基于时间戳派生
    • IV需要与加密固件一起传输到设备
7. IV与安全问题实例

如果两次加密使用相同的IV和密钥,会出现严重安全问题:

假设有两个明文块M₁和M₂,使用相同的(Key,IV)加密:

  • C₁ = E(M₁ ⊕ IV, Key)
  • C₂ = E(M₂ ⊕ IV, Key)

如果攻击者知道M₁的内容,他们可以推导出:

  • M₁ ⊕ M₂ = D(C₁, Key) ⊕ D(C₂, Key)

这种"两次使用攻击"(Two-time pad attack)可能导致信息泄露。

在可信固件更新系统中,即使每次使用相同的密钥加密固件,通过使用不同的IV,也能确保每次生成不同的密文,大大增强了系统的安全性。

代码中的实现

IAP_AES_CBC_Decrypt 函数中,AES-CBC 解密是这样实现的:

uint32_t IAP_AES_CBC_Decrypt(const uint8_t *pCiphertext, uint32_t len, const uint8_t *key, const uint8_t *iv, uint8_t *pPlaintext)
{mbedtls_aes_context aes_ctx;unsigned char iv_copy[16]; // 复制IV,因为解密过程会修改IVint ret;// 确保长度是16字节对齐的if (len % 16 != 0)return 1; // 错误:长度必须是16字节的倍数// 初始化AES上下文mbedtls_aes_init(&aes_ctx);// 设置解密密钥 (AES-128是16字节密钥,128位)ret = mbedtls_aes_setkey_dec(&aes_ctx, key, 128);if (ret != 0)return ret;// 复制IV值,因为mbedtls_aes_crypt_cbc会修改iv参数memcpy(iv_copy, iv, 16);// 执行CBC模式解密ret = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, len, iv_copy, pCiphertext, pPlaintext);// 释放上下文mbedtls_aes_free(&aes_ctx);return ret;
}

关键步骤解释:

  1. 创建AES上下文mbedtls_aes_init(&aes_ctx) 初始化一个AES计算环境
  2. 设置解密密钥mbedtls_aes_setkey_dec 函数处理密钥扩展,为解密做准备
  3. IV处理:复制初始向量,因为解密过程会修改它
  4. CBC解密mbedtls_aes_crypt_cbc 执行完整的CBC模式解密
    • 处理每个16字节的块
    • 解密每个块后与前一个密文块或IV异或
    • 将结果输出到明文缓冲区

在固件更新流程中的应用

在固件更新过程中,AES-CBC解密用于确保固件传输的安全性:

  1. 固件在上位机加密并保存到外部Flash
  2. Bootloader读取加密的固件
  3. 使用预设密钥和IV进行解密
  4. 验证解密后固件的SHA-256哈希值
  5. 写入内部Flash

特别注意的是,代码中正确地处理了IV链,确保每个块都使用正确的IV:

// 保存下一个块的IV (当前块的最后16字节密文)
if(remaining > block_size) {  // 如果不是最后一块uint8_t next_iv[16];W25Q128_read(next_iv, APP_SAVE_ADDR + offset + block_size - 16, 16);memcpy(current_iv, next_iv, 16);
}

这确保了能够分块处理大型固件,而不需要一次性将整个固件加载到内存中,这是嵌入式系统中的常见实践。

安全性考虑

  1. 密钥管理:AES-128密钥需要安全存储,避免被提取
  2. IV唯一性:对于每次加密,IV应该是唯一的,以防止重放攻击
  3. 数据完整性:AES只提供保密性,不提供完整性验证,因此需要配合SHA-256等哈希算法
  4. 填充安全:PKCS#7填充需要正确实现以避免填充甲类攻击

代码通过结合AES-CBC加密和SHA-256哈希验证,提供了相对完善的固件安全保护机制。

http://www.xdnf.cn/news/414955.html

相关文章:

  • 分享AI时代数据智能人才定向就业班(暑期班)
  • 【Linux 系统调试】syslog:Linux 系统日志工具详解
  • DAY22kaggle泰坦尼克号
  • 手写 vue 源码 === watch 实现
  • 学习黑客5分钟深入浅出理解系列之Windows compmgmt
  • 配置Hadoop集群-免密登录
  • dfs第二次加训 详细题解 下
  • STM32G474VET6-CAN FD使用经典模式+过滤报文ID
  • ESOP系统如何帮助玩具工厂实现生产数据实时展示
  • rufus+Ubuntu 18.04 镜像
  • Promise/A+ 规范中文解读
  • Matlab基于PSO-MVMD粒子群算法优化多元变分模态分解
  • 【C语言指针超详解(五)】--回调函数,qsort函数的理解和使用,qsort函数的模拟实现
  • 类神经网络训练失败怎么办?
  • 中央处理器(CPU)(概述、指令周期)
  • 阿里云服务器核心用途解析:从基础应用到行业创新​
  • c++刷题便捷函数(类似于stoi的小函数)
  • 超越合并速度(merge speed):AI如何重塑开发者协作
  • Hadoop集群的常用命令
  • axi uart 16550 ip core使用流程
  • 一、HAL库的设计理念详解:从架构到实践
  • 274、H指数
  • StringBuilder,StringJoiner,StringBuffer字符串处理类深度解析
  • 从零到精通:GoFrame 的 garray 模块深度解析与实战经验分享
  • Nacos源码—8.Nacos升级gRPC分析五
  • 【K8S学习之生命周期钩子】详细了解 postStart 和 preStop 生命周期钩子
  • 【日撸 Java 三百行】Day 13(链表)
  • 【AIGC梦幻婚纱美学】:白纱与花卉的浪漫算法融合
  • 2025-5-12 底部埋伏记录
  • Matlab 基于GUI的图像去雾技术GlobalHisteq、LocalHisteq和Retinex