news 2026/3/28 4:23:47

加密模式深度解析:从CBC、ECB到CTR模式的实战对比与Moshi应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
加密模式深度解析:从CBC、ECB到CTR模式的实战对比与Moshi应用


加密模式深度解析:从CBC、ECB到CTR模式的实战对比与Moshi应用

背景痛点:选模式比写代码还难

第一次把 AES 塞进项目时,我盯着Cipher.getInstance("AES/???/PKCS5Padding")里的???发了半天呆。ECB、CBC、CTR 三个缩写像三胞胎,文档都说自己“安全高效”,可一搜社区,全是“ECB 泄露指纹”“CBC 填充攻击”“CTR 不能重复计数器”的警告。到底该选谁?加解密的接口一样,可背后的坑却完全不同,一旦模式选错,性能、安全、甚至合规审计都得返工。。今天这篇笔记,就把三种模式拆成“乐高积木”,用 Moshi 串起完整流程,让你下次不再纠结。

1. ECB:最简单也最容易翻车

ECB(Electronic Codebook)直接把明文切块,每块独立加密。特点一句话:块与块之间毫无关联

  • 优点:实现简单,无初始向量(IV),可并行,出错只影响单块。
  • 隐患:相同明文块 ⇒ 相同密文块,指纹泄露一目了然。下图经典示例——加密企鹅,ECB 后图案依旧可见,安全形象瞬间崩塌。

适用场景:仅用于教学演示或**随机数据(如已加密的密钥)**的二次封装。

2. CBC:老牌“链路”模式

CBC(Cipher Block Chaining)把前一块密文与当前明文异或后再加密,首尾块用随机 IV 拉乱序。

  • 关键细节:
    • IV 必须每次随机,长度 = 块大小(AES 为 16 B),可附在密文前端。
    • 明文需填充到块整数倍,常用 PKCS5Padding / PKCS7Padding。
  • 隐患:若攻击者篡改 IV 可翻转明文某比特(位翻转攻击),需做完整性校验(HMAC/SMAC)。

适用场景:文件、磁盘、即时通信等对顺序 & 完整性要求高的业务。

3. CTR:把分组当流加密用

CTR(Counter)让分组算法变身“流密码”。生成递增计数器块序列,用密钥加密计数器得到密钥流,再与明文异或。

  • 优点:
    • 无填充,明文长度任意字节。
    • 加解密完全对称,可预计算密钥流,延迟低。
    • 天然并行,吞吐量最高。
  • 隐患:计数器不能重复(Nonce+Counter 组合必须唯一),否则“两密文异或 = 两明文异或”直接裸奔。

适用场景:实时音视频、高频 RPC、随机读写数据库字段低延迟+高并发场景。

4. Moshi 实战:一条 JSON 走三遍

下面用同一份数据User(name, age)跑通 ECB/CBC/CTR,密钥长度统一 128 bit,方便对比。代码基于 JDK17 + Moshi 1.15,仅依赖kotlin-stdlibbouncycastle提供的 AES 封装(可替换为 javax.crypto)。

4.1 公共部分:密钥生成与 Moshi 序列化

object CryptoUtil { fun generateKey(): SecretKey = KeyGenerator.getInstance("AES") .apply { init(128) }.generateKey() inline fun <reified T> toJson(model: T): String = Moshi.Builder().build().adapter(T::class.java).toJson(model) inline fun <reified T> fromJson(json: String): T? = Moshi.Builder().build().adapter(T::class.java).fromJson(json) }

4.2 ECB 实现

fun ecbEncrypt(key: SecretKey, json: String): ByteArray { val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding") cipher.init(Cipher.ENCRYPT_MODE, key) return cipher.doFinal(json.toByteArray(StandardCharsets.UTF_8)) } fun ecbDecrypt(key: SecretKey, data: ByteArray): String { val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding") cipher.init(Cipher.DECRYPT_MODE, key) return String(cipher.doFinal(data), StandardCharsets.UTF_8) }

4.3 CBC 实现(带随机 IV)

fun cbcEncrypt(key: SecretKey, json: String): Pair<ByteArray, ByteArray> { val iv = ByteArray(16).apply { SecureRandom().nextBytes(this) } val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") cipher.init(Cipher.ENCRYPT_MODE, key, IvParameterSpec(iv)) val cipherText = cipher.doFinal(json.toByteArray(StandardCharsets.UTF_8)) return iv to cipherText // 返回 IV 与密文,方便拼接 } fun cbcDecrypt(key: SecretKey, iv: ByteArray, cipherText: ByteArray): String { val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") cipher.init(Cipher.DECRYPT_MODE, key, IvParameterSpec(iv)) return String(cipher.doFinal(cipherText), StandardCharsets.UTF_8) }

4.4 CTR 实现(无填充)

fun ctrEncrypt(key: SecretKey, json: String): Pair<ByteArray, ByteArray> { val iv = ByteArray(16).apply { SecureRandom().nextBytes(this) } // 当作Nonce val cipher = Cipher.getInstance("AES/CTR/NoPadding") cipher.init(Cipher.ENCRYPT_MODE, key, IvParameterSpec(iv)) val cipherText = cipher.doFinal(json.toByteArray(StandardCharsets.UTF_8)) return iv to cipherText } fun ctrDecrypt(key: SecretKey, iv: ByteArray, cipherText: ByteArray): String { val cipher = Cipher.getInstance("AES/CTR/NoPadding") cipher.init(Cipher.DECRYPT_MODE, key, IvParameterSpec(iv)) return String(cipher.doFinal(cipherText), StandardCharsets.UTF_8) }

4.5 调用示例

val user = User("Alice", 29) val key = CryptoUtil.generateKey() // ECB val ecbBytes = ecbEncrypt(key, toJson(user)) val userEcb = fromJson<User>(ecbDecrypt(key, ecbBytes)) // CBC val (ivCbc, cbcBytes) = cbcEncrypt(key, toJson(user)) val userCbc = fromJson<User>(cbcDecrypt(key, ivCbc, cbcBytes)) // CTR val (ivCtr, ctrBytes) = ctrEncrypt(key, toJson(user)) val userCtr = fromJson<User>(ctrDecrypt(key, ivCtr, ctrBytes))

4.6 异常处理最佳实践

  • 捕获BadPaddingException→ 立即返回统一“解密失败”文案,避免旁道攻击。
  • 捕获AEADBadTagException(若启用 GCM)→ 同样不区分原因,直接拒绝。
  • 日志只记录调用 ID,绝不打印密钥、IV 或密文片段

5. 性能横评:跑 1 GB 随机数据

本地 Mac M2 单线程,AES-128,16 KB chunk 平均结果:

  • ECB:1.35 GB/s(无额外计算,纯并行)
  • CBC:1.10 GB/s(串行链依赖,略慢)
  • CTR:1.40 GB/s(可预计算密钥流,最快)

内存占用三者持平;CTR 在多核下优势更明显,适合高并发网关。

6. 安全配置速查表

  • ECB:生产环境禁用;若必须兼容老协议,外层再套 HMAC-SHA256。
  • CBC:
    • IV 用SecureRandom每次刷新;
    • 密文末尾追加HMAC(key, iv+cipher),防篡改;
    • 拒绝旧版SSL3填充,用PKCS5Padding即可。
  • CTR:
    • Nonce 可用12 B 随机 + 4 B 计数器8 B 随机 + 8 B 序号,保证(Nonce, Counter)对不重复;
    • 多设备共享密钥时,用分布式序号生成器时间戳 + 随机
    • 同样建议加 MAC(如 AES-GCM 内置 TAG)。

7. 那些年我踩过的坑

  1. “IV 固定写死 16 个 0”→ 明文前缀相同,CBC 也成 ECB。
  2. CTR 计数器回卷→ 32 位计数器上限 4 GB,大文件溢出后密钥流重复。
  3. 密文直接new String(cipherBytes)→ 默认 UTF-8 把随机字节解码成�,再编码就永久丢失。
  4. 忘记填充NoPadding下明文长度非 16 整倍直接抛异常。
  5. 复用 Cipher 实例→ 多线程并发下计数器/IV 状态错乱,务必ThreadLocal或每次getInstance

8. 思考题:你的业务选谁?

假设你在做离线批量加密用户头像文件(平均 2 MB),同时提供在线解密预览接口,QPS 约 5 k,延迟要求 < 20 ms。你会选哪种模式?为什么?(提示:并发、填充、完整性、随机读写)

欢迎在评论区留下你的方案,我们一起 review!

9. 把“豆包”也拉进实时通话

写完这篇,我最大的感受是:“把数据塞进 AES 盒子”只是第一步,真正的挑战是让算法在业务节奏里跑顺。如果你也迷恋“边说话边加密”的实时场景,可以试试从0打造个人豆包实时通话AI动手实验——里面把 ASR→LLM→TTS 整条链路拆成可插拔模块,CTR 加密正好用在语音流低延迟通道,代码里还顺手示范了如何给音频数据加 MAC 校验。整套实验对新手很友好,我跟着跑通只花了不到一小时,推荐你也玩一下,把“加密模式”与“实时通话”两个技能点一次点亮。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/19 12:59:35

跨平台游戏引擎:如何突破设备限制畅玩主机游戏?

跨平台游戏引擎&#xff1a;如何突破设备限制畅玩主机游戏&#xff1f; 【免费下载链接】sudachi Sudachi is a Nintendo Switch emulator for Android, Linux, macOS and Windows, written in C 项目地址: https://gitcode.com/GitHub_Trending/suda/sudachi 作为一名忠…

作者头像 李华
网站建设 2026/3/24 9:38:09

2024权威评测:数据库性能优化指南——从技术原理到实战突围

2024权威评测&#xff1a;数据库性能优化指南——从技术原理到实战突围 【免费下载链接】ClickHouse ClickHouse 是一个免费的大数据分析型数据库管理系统。 项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse 在大数据时代&#xff0c;企业面临着数据量爆…

作者头像 李华
网站建设 2026/3/24 20:18:12

Dify Workflow零代码探险:从界面小白到流程大师的技术之旅

Dify Workflow零代码探险&#xff1a;从界面小白到流程大师的技术之旅 【免费下载链接】Awesome-Dify-Workflow 分享一些好用的 Dify DSL 工作流程&#xff0c;自用、学习两相宜。 Sharing some Dify workflows. 项目地址: https://gitcode.com/GitHub_Trending/aw/Awesome-D…

作者头像 李华
网站建设 2026/3/24 17:19:31

5步自制专属阅读器:开源电子书制作完全指南

5步自制专属阅读器&#xff1a;开源电子书制作完全指南 【免费下载链接】The-Open-Book 项目地址: https://gitcode.com/gh_mirrors/th/The-Open-Book 在数字阅读日益普及的今天&#xff0c;拥有一款真正属于自己的阅读器是什么体验&#xff1f;The Open Book开源电子书…

作者头像 李华
网站建设 2026/3/20 10:42:24

AI语音克隆开源工具零基础教程:30分钟从零构建专属语音模型

AI语音克隆开源工具零基础教程&#xff1a;30分钟从零构建专属语音模型 【免费下载链接】GPT-SoVITS 项目地址: https://gitcode.com/GitHub_Trending/gp/GPT-SoVITS 你是否曾想拥有一个能模仿自己声音的AI助手&#xff1f;现在&#xff0c;借助开源语音合成工具GPT-So…

作者头像 李华
网站建设 2026/3/25 0:55:03

3大颠覆认知的模块化设计:为何传统架构都错了?

3大颠覆认知的模块化设计&#xff1a;为何传统架构都错了&#xff1f; 【免费下载链接】Auto-Claude Autonomous multi-session AI coding 项目地址: https://gitcode.com/gh_mirrors/au/Auto-Claude 问题解构&#xff1a;当AI编码遭遇架构瓶颈 ⚡ 传统单体架构在AI编码…

作者头像 李华