解密结果不对?密钥、IV、分段与分隔的排查

2026-11-05约 7 分钟加密解密涉及 3 个工具

加密报错时多数人先怀疑算法,但算法几乎从不出错 —— 出错的是密钥怎么被解析、IV 怎么被重用、分段按哪个长度切、以及摩斯码的分隔约定。

核心要点
  • AES 的密钥只有「纯十六进制、偶数长度且正好等于算法要求」才按字节解释,否则会被当成 UTF-8 文本补零或截断
  • 同一密钥下重复使用同一个 IV 会泄露两段明文的异或值,GCM 模式下还会让认证直接失效
  • RSA 单块明文上限等于密钥字节数减 66,切块必须按实际导入的密钥长度,不能按界面选的位数
  • 摩斯码的国际惯例是字母之间 3 个空格、单词之间 7 个空格,粘进只认单空格的工具必然解错
  • CBC 没有完整性保护,密文被改动时多数只解出乱码而不报错,新项目应当优先选 GCM

#先排除「不是算法的问题」

AES 与 RSA 的实现几万个项目在跑,算错的可能性极低 —— 出错的是参数怎么被解释。 所以排查顺序应该从参数开始,而不是从算法开始。

四类原因,对应四种不同的验证方式:

现象常见原因怎么验证
AES 加密成功但解不开密钥或 IV 被当成文本处理确认密钥是不是纯 hex 且长度正确
换一条消息就解不开IV 复用了检查每条密文是否带自己的 IV
RSA 报长度不对按界面选的位数切块按实际导入的密钥长度算
摩斯码解出来是乱的分隔符约定不匹配检查是单空格还是 3 空格

#AES:密钥是怎么被解析的

密钥的解析规则决定它到底是哪一把钥匙 —— 同一串字符,解释方式不同就是两把完全不同的密钥。 这是「加密成功但对方解不开」最常见的原因。

用 AES / DES 加解密 时,规则是这样的:纯十六进制、偶数长度、且长度正好等于算法要求时,按字节解释;否则一律当作 UTF-8 文本,再补零或截断到目标长度。

各算法要求的字节数:

  • AES-128 密钥 16 字节,AES-256 密钥 32 字节,IV 16 字节
  • AES-GCM 的 IV 固定 12 字节
  • DES 密钥 8 字节,IV 8 字节
注意

一串「看着像 hex 但少一位」的密钥,如果被当成文本处理并补零,加密会「成功」,但得到的是用另一把密钥加密的结果,谁也解不开。所以现在 hex 形态但长度不符会直接报错,而不是静默转换。

#IV 复用:最危险的静默错误

同一个密钥下重复使用同一个 IV,会泄露两段明文的异或值 —— 攻击者不需要破解算法就能还原内容。 这是唯一一个「不报错、不失败、但已经不安全」的错误。

两种模式对 IV 的敏感程度不同:

  • CBC 没有完整性保护。密文被改动时,多数情况只解出乱码而不报错;填充恰好合法时连错都不报
  • GCM 是认证加密,末尾带 16 字节认证标签。密钥或密文错一个字节就直接失败 —— 代价是 GCM 对 IV 更敏感,重复使用同一个 IV 会同时泄露明文关系并让认证失效

新项目优先选 GCM。老系统对接遗留实现时才用 CBC,且必须确保每条消息带独立随机 IV,并与密文一起保存。

要点

输出格式也会造成「解不开」:工具解密时格式是自动判断的 —— 纯 hex 且长度为偶数优先按 Hex 解析,其余按 Base64。所以一段恰好只由 0-9a-f 组成、长度又是偶数的 Base64 密文,会被误判成 Hex。概率不高但确实存在,遇到解不开先换一种输出格式再试。

#RSA:分段长度按密钥算

RSA 单块能加密的明文长度由密钥长度决定,换算方式是「密钥字节数 − 66」。 这个 66 来自 OAEP 填充:SHA-256 摘要占 2×32 字节,再加 2 字节开销。

常用位数对应的上限:

  • 2048 位 → 190 字节
  • 3072 位 → 318 字节
  • 4096 位 → 446 字节

超出就按这个长度切块,密文再顺序拼接。

用 RSA 公私钥加密 时最容易踩的一条:切块依据是实际导入的密钥长度,而不是界面上选的位数。 粘一把 2048 位公钥却按 3072 位切,加密必然失败;反过来按 384 字节去判密文长度,合法的密文也会被判成「长度不对」。

另外要知道它的能力边界:这个工具只做 RSA-OAEP(SHA-256)加密,公钥加密、私钥解密;签名与验签是另一套用法,这里不提供。对外只认 SPKI 公钥与 PKCS#8 私钥,PKCS#1 格式会被拒绝,需要先用 openssl 转换。

技巧

RSA 不适合直接加密大段数据。工程上的通用做法是混合加密:用 RSA 包一个临时 AES 密钥,正文交给 AES-GCM。既避开切块开销,又拿到完整性保护。

#摩斯密码:分隔符就是信息

摩斯码的字母与单词边界完全靠空格表达,所以分隔约定不匹配时,解出来的东西一定不对 —— 这不是解码 bug,是输入格式不对。 用 摩斯密码转换 之前先确认对方用的是什么约定。

两套约定并存:

  • 本工具:一个空格分隔字母,斜杠(也接受竖线或三个以上空格)分隔单词
  • 国际电报经典:字母之间 3 个空格,单词之间 7 个空格

把 3 空格格式的报文粘进只认单空格的工具,每个空格都会被当成字母边界,结果就是一串破碎的码组。

还有几个常被问到的点:SOS 是一个码组(三点三划三点连续发出),不是三个字母;中文转不了,摩斯只覆盖拉丁字母、数字和标点;未收录的字符会原样保留并在状态栏提示数量,不会悄悄丢掉。

#什么时候该用哪个工具

你想做的事用哪个关键约束
对称加密一段文本AES / DES 加解密密钥按 hex 或文本解释,长度必须精确
用公钥加密、私钥解密RSA 公私钥加密只认 SPKI + PKCS#8,分段按密钥算
编解码摩斯电码摩斯密码转换分隔符约定必须与来源一致
校验文件完整性MD5 加密哈希不可逆,不是加密
生成不重复的标识UUID / GUID 生成v4 随机,v1 含时间与节点

判断顺序很实用:要能解回来选加密(AES / RSA),只要对得上选哈希(MD5 / SHA),只是编码用 Base64。 三者混用是另一个高频错误来源 —— Base64 不是加密,它没有密钥。

#常见问题

#同样的密钥,为什么对方解不开?

最可能是密钥被解释成了不同的字节。同一串 32 个字符,如果你这边按 hex 解析成 16 字节、对方按 UTF-8 文本取前 16 个字符,两边用的就是完全不同的密钥。约定好密钥的表示形式(hex 还是文本)并写进接口文档,比事后排查省事得多。

#加密能成功,解密却报错,是什么原因?

三种常见情况:密钥或 IV 长度不对但被静默补零、密文被截断或拼接顺序错了、以及输出格式被自动判错(Base64 密文恰好只含 0-9a-f 且长度为偶数时会按 Hex 解)。先换一种输出格式试,再逐字节核对密钥。

#IV 可以直接写死成固定值吗?

不能。固定 IV 等于让相同明文产生相同密文,攻击者能看出哪些消息内容重复;对 GCM 来说更严重,重复 IV 会直接破坏认证。正确做法是每条消息生成随机 IV,并把 IV 与密文一起传给对方(IV 不是秘密)。

#RSA 为什么不能加密长文本?

因为它一次只能加密「密钥长度减去填充开销」那么多字节,2048 位只有 190 字节。超出就要切块并顺序拼接,而切块带来额外开销、也只保证机密性没有完整性保护。加密长文本请用混合加密。

#摩斯码能表示中文吗?

不能。摩斯电码的字符集是拉丁字母、数字和一小部分标点,没有汉字。要发中文得先转成拼音,或者用中文电报码(四位数字表示一个汉字)再转摩斯 —— 这层转换需要额外工具,本工具不内置。

本文提到的工具

相关文章