Laucher
2025年 01月 09日
解决前端crypto-js库解密失败的错误
最近我在处理一个项目时遇到了一个比较棘手的问题:我成功接收到了后端加密的数据,使用crypto-js库进行解密时却总是报错“Error: Malformed UTF-8 data”,无法正确对密文codestr解密。
问题的起因
事情的开始是这样的:我正在开发一个前端项目,需要从后端获取加密数据进行解密。后端返回的数据是经过加密的,前端需要使用一个密钥进行解密。按照正常流程,我在请求接口时也进行了加签(签名),并且使用了后端提供的密钥。
// 接口返回的数据
{
"code": -1,
"msg": "404 not found",
"data": {
"codestr": "ph0XVuDhyFNj6R2P7enH9A=="
}
}
这部分其实没有问题,因为加签的过程是正常的,数据也顺利返回到前端。问题出现在解密数据的时候,前端无法成功解密,总是抛出错误:
Error: Malformed UTF-8 data
乍一看,错误提示和UTF-8编码有关,我本能地怀疑是不是编码转换出了问题。我尝试了很多方法去排查问题,但都无果,刚好后端同事正在休假。问了后端是不是跟之前项目的加密方式一样,后端同事表示肯定,但我用同样的解密方式却始终无法正确解密。最终通过一番调查,我发现了一个非常简单但容易被忽视的原因——后端加密时使用的密钥长度不符合解密算法的要求。今天我就来分享一下这个我遇到的问题,希望您遇到同样问题时能快速解决。
排查过程
1. 确认加密解密流程
我首先检查了前端的解密逻辑。解密部分使用的是常见的AES算法,ECB加密模式,填充方式为AES通常默认的PKCS#7,我确认了前后端使用相同的加密标准和解密方式(不要问我为什么能确认后端的加密方式,因为我有后端代码:))。数据返回后,我试着按照常规的方式进行解密,每次都会在解密这一步失败。
2. 检查密钥和签名
由于我已经确认了加密时使用了后端提供的密钥,最初我并没有怀疑这个密钥长度是否是问题的根源。毕竟,后端提供的密钥在加签过程中是没问题的,这让我觉得解密时出错应该是其他因素引起的。
于是,我继续排查其他可能的原因,检查了加密数据的完整性和传输过程中是否有丢失,甚至对加密方式做了反复验证,但问题始终没有解决。
3. 问题的根源
幸运的是,找到了一个非常关键的问题——后端给我的密钥是一个15字节的。而这实际上违反了AES算法对于密钥长度的要求。问题的本质终于明朗了。后端使用的是15字节的密钥,而AES加密算法要求密钥长度为16、24或32字节。
如果密钥长度不符合规范,解密时就会导致数据无法正确解析,最终引发UTF-8编码错误。这也解释了为什么加签的过程没有问题——加签时虽然密钥长度为15字节,但签名只是对数据的完整性进行验证,不涉及复杂的加解密运算。而在解密时,由于AES算法要求的密钥长度严格,15字节的密钥直接导致了问题。
解决方案
1. 修正密钥长度
最简单直接的解决方案是要求后端修正密钥的长度,确保它符合AES的要求。16字节的密钥是最常见的选择。修改后,前端就可以正常解密数据,问题迎刃而解。
反思与总结
这个问题让我意识到,作为开发者,我们应该始终保持对细节的敏感。
如果你在项目中也遇到类似的加解密问题,不妨从密钥长度和编码格式入手排查问题,可能会让你少走很多弯路。
最后,希望这篇Blog能给您带来帮助。