文章目录
- 常见加密算法特征总结
-
- 一、先建立逆向判断思路
- 二、按类型总览
- [三、哈希 / 消息摘要类](#三、哈希 / 消息摘要类)
-
- [1. MD5](#1. MD5)
- [2. SHA1](#2. SHA1)
- [3. SHA256](#3. SHA256)
- [4. SHA384 / SHA512](#4. SHA384 / SHA512)
- [5. SM3](#5. SM3)
- [哈希 / 摘要类统一特征](#哈希 / 摘要类统一特征)
- 四、摘要类的一个特殊分支:HMAC
-
- [HMAC 识别特征](#HMAC 识别特征)
- 五、对称加密类
-
- 对称加密先记四个参数
- [1. AES](#1. AES)
- [2. DES / 3DES](#2. DES / 3DES)
- [3. SM4](#3. SM4)
- [4. RC4](#4. RC4)
- 对称加密类统一特征
- 六、非对称加密类
-
- [1. RSA](#1. RSA)
- [2. SM2](#2. SM2)
- 非对称类统一特征
- 七、编码类:最容易被误当成"加密"
-
- [1. Base64](#1. Base64)
- [2. Hex](#2. Hex)
- 编码类统一特征
- [八、逆向里最实用的"长度 + 动态性"速判表](#八、逆向里最实用的“长度 + 动态性”速判表)
- [九、JS 逆向中常见代码特征](#九、JS 逆向中常见代码特征)
-
- [1. 哈希 / HMAC 常见样子](#1. 哈希 / HMAC 常见样子)
- [2. AES / DES 常见样子](#2. AES / DES 常见样子)
- [3. RSA 常见样子](#3. RSA 常见样子)
- 十、实战里最容易误判的点
-
- [1. `Base64` 不是加密](#1.
Base64不是加密) - [2. 有 `key` 不一定是对称加密](#2. 有
key不一定是对称加密) - [3. 输出变了,不一定就是"加密算法变了"](#3. 输出变了,不一定就是“加密算法变了”)
- [4. 看到 `AES` 还不够](#4. 看到
AES还不够) - [5. 固定长度不代表一定是哈希](#5. 固定长度不代表一定是哈希)
- [1. `Base64` 不是加密](#1.
- [十一、面向 JS 逆向的最终分类记忆](#十一、面向 JS 逆向的最终分类记忆)
- 十二、结论
常见加密算法特征总结
这篇文章不是从密码学理论展开,而是从 JS 逆向识别角度出发。
目标只有一个:当你在网页、混淆代码、接口参数、请求头、localStorage、cookie 里看到一段可疑字符串时,能快速判断它更像是哈希、对称加密、非对称加密,还是单纯编码。
一、先建立逆向判断思路
做 JS 逆向时,先不要急着看函数名,优先看下面几个维度:
- 输出长度是不是固定。
- 输出长度是否和输入长度明显相关。
- 输出字符集是什么。
- 同样输入多次执行,结果会不会变化。
- 代码里是否出现
key、iv、nonce、publicKey、privateKey、salt。 - 代码里是否出现
encrypt、decrypt、sign、verify、digest、hash、update、finalize。
可以先记住一个总规则:
- 哈希 / 摘要:通常固定长度,不可逆,同样输入结果通常固定。
- 对称加密:通常可逆,密文长度和明文长度相关,是否动态主要看
iv/nonce。 - 非对称加密:通常可逆或可验签,输出长度往往更受密钥长度影响。
- 编码:不是加密,通常可逆,长度变化符合编码规则。
二、按类型总览
| 类型 | 是否可逆 | 输出长度特征 | 是否常动态变化 | 是否依赖 key | 是否依赖 iv / nonce |
|---|---|---|---|---|---|
| 哈希 / 消息摘要 | 否 | 通常固定 | 通常不变 | 一般不需要 | 不需要 |
| HMAC / 带密钥摘要 | 否 | 通常固定 | 通常不变 | 需要 | 不需要 |
| 对称加密 | 是 | 与输入长度相关 | 可能变化 | 需要 | 很多模式需要 |
| 非对称加密 | 部分可逆 / 可验签 | 与密钥长度强相关 | 很多场景会变化 | 需要公私钥 | 一般不直接叫 iv |
| 编码 | 是 | 按编码规则变化 | 不变 | 不需要 | 不需要 |
三、哈希 / 消息摘要类
这一类最常见的用途不是"加密",而是做签名材料、摘要校验、参数指纹、缓存键。
1. MD5
| 项 | 特征 |
|---|---|
| 常见输出长度 | 128 bit,常见为 32 位十六进制字符串 |
| 常见字符特征 | 0-9a-f,有时大写;也可能再转 Base64 |
| 输出是否动态变化 | 同样输入通常不变 |
| 密钥长度特征 | 无;如果是 HMAC-MD5 才有 key |
| IV 特征 | 无 |
| 是否可逆 | 否 |
| 逆向识别点 | 常见调用 md5()、CryptoJS.MD5()、createHash('md5') |
补充:
- 如果你看到一个固定
32位十六进制串,优先怀疑MD5。 - 但也不要机械判断,因为某些站会把别的二进制结果转成
Hex,看起来也可能是32、64位。
2. SHA1
| 项 | 特征 |
|---|---|
| 常见输出长度 | 160 bit,常见为 40 位十六进制字符串 |
| 常见字符特征 | 0-9a-f |
| 输出是否动态变化 | 同样输入通常不变 |
| 密钥长度特征 | 无;如果是 HMAC-SHA1 才有 key |
| IV 特征 | 无 |
| 是否可逆 | 否 |
| 逆向识别点 | sha1()、CryptoJS.SHA1()、createHash('sha1') |
3. SHA256
| 项 | 特征 |
|---|---|
| 常见输出长度 | 256 bit,常见为 64 位十六进制字符串 |
| 常见字符特征 | 0-9a-f |
| 输出是否动态变化 | 同样输入通常不变 |
| 密钥长度特征 | 无;如果是 HMAC-SHA256 才有 key |
| IV 特征 | 无 |
| 是否可逆 | 否 |
| 逆向识别点 | sha256()、CryptoJS.SHA256()、createHash('sha256') |
4. SHA384 / SHA512
| 算法 | 常见十六进制长度 | 是否可逆 | 是否动态 |
|---|---|---|---|
SHA384 |
96 位 |
否 | 同样输入通常不变 |
SHA512 |
128 位 |
否 | 同样输入通常不变 |
5. SM3
| 项 | 特征 |
|---|---|
| 常见输出长度 | 256 bit,常见为 64 位十六进制字符串 |
| 常见字符特征 | 0-9a-f |
| 输出是否动态变化 | 同样输入通常不变 |
| 密钥长度特征 | 无 |
| IV 特征 | 无 |
| 是否可逆 | 否 |
| 逆向识别点 | 常见于 sm-crypto、国密站点、政企系统 |
哈希 / 摘要类统一特征
| 维度 | 规律 |
|---|---|
| 密文长度 | 基本固定,与输入长度没有线性对应关系 |
| 密文特征 | 常见为 Hex,少数转 Base64 |
| 是否动态变化 | 同样输入通常不变;如果变了,多半不是纯哈希 |
| 密钥长度特征 | 普通哈希没有 key |
| 初始化向量特征 | 没有 iv |
| 是否可逆 | 不可逆 |
四、摘要类的一个特殊分支:HMAC
很多逆向场景里,前端写的是"签名",但本质不是加密,而是 HMAC。
常见形式:
HmacMD5HmacSHA1HmacSHA256HmacSHA512
HMAC 识别特征
| 项 | 特征 |
|---|---|
| 本质 | 带密钥的摘要,不是对称加密 |
| 输出长度 | 由哈希算法决定,通常固定 |
| 密文特征 | 常见为 Hex / Base64 |
| 输出是否动态变化 | 同样输入 + 同样 key 时通常不变 |
| 密钥长度特征 | key 长度通常可变,业务里常见短字符串、token、固定盐 |
| IV 特征 | 无 |
| 是否可逆 | 否 |
| 逆向识别点 | CryptoJS.HmacSHA256(data, key)、createHmac() |
逆向时很容易误判成"对称加密",因为它也有 key。但要抓住一点:
- 只要没有
decrypt过程,输出又是固定长度,大概率更像HMAC而不是 AES。
五、对称加密类
这类在 JS 逆向里最常见的是 AES,其次是 DES/3DES、SM4,老项目里也偶尔能看到 RC4。
它们的核心特点是:加密和解密使用同一套密钥,通常可逆。
对称加密先记四个参数
遇到对称加密,不要只说"这是 AES",必须继续看:
keyivmodepadding
这四个参数有一个不一致,结果就可能完全不同。
1. AES
| 项 | 特征 |
|---|---|
| 类型 | 对称分组加密 |
| 是否可逆 | 是 |
| 密钥长度特征 | 常见 16 / 24 / 32 字节,对应 AES-128/192/256 |
| IV 特征 | 需要 iv 的模式下通常是 16 字节 |
| 常见模式 | ECB、CBC、CTR、CFB、OFB、GCM |
| 密文长度特征 | 原始二进制密文通常与明文长度相关;CBC/ECB 下按 16 字节块对齐 |
| 密文常见表现 | 常被转成 Base64 或 Hex |
| 输出是否动态变化 | 同样明文 + 同样 key + 同样 iv 时通常不变;如果 iv/nonce 每次变,密文就会变 |
| 逆向识别点 | CryptoJS.AES.encrypt()、crypto.createCipheriv('aes-...') |
补充理解:
ECB一般不需要iv,相同输入更容易得到相同输出。CBC常见,通常需要iv。CTR/GCM更像"流式处理",也通常依赖nonce或iv。
2. DES / 3DES
| 项 | DES | 3DES |
|---|---|---|
| 是否可逆 | 是 | 是 |
| 密钥长度特征 | 常按 8 字节理解 |
常见 16 或 24 字节 |
| IV 特征 | 需要时通常 8 字节 |
需要时通常 8 字节 |
| 分组大小 | 8 字节 |
8 字节 |
| 密文长度特征 | 按 8 字节块对齐 |
按 8 字节块对齐 |
| 是否动态变化 | 取决于 iv / 模式 |
取决于 iv / 模式 |
| 逆向关键词 | DES、DESede、TripleDES |
3. SM4
| 项 | 特征 |
|---|---|
| 类型 | 对称分组加密 |
| 是否可逆 | 是 |
| 密钥长度特征 | 16 字节 |
| IV 特征 | 常见 16 字节,取决于模式 |
| 分组大小 | 16 字节 |
| 密文长度特征 | 和明文长度相关,分组模式下按块对齐 |
| 输出是否动态变化 | 取决于 iv、模式、是否使用随机数 |
| 逆向识别点 | sm4、国密系统、sm-crypto |
4. RC4
| 项 | 特征 |
|---|---|
| 类型 | 对称流加密 |
| 是否可逆 | 是 |
| 密钥长度特征 | 可变,常见短 key 到较长 key |
| IV 特征 | 标准 RC4 没有传统分组 iv 概念 |
| 密文长度特征 | 原始二进制输出通常与输入长度基本一致 |
| 密文特征 | 常再转 Hex / Base64 |
| 输出是否动态变化 | 同样输入 + 同样 key 通常不变;若前面拼接动态串,整体才会变 |
| 逆向识别点 | RC4、异或味道很重、无分组概念 |
对称加密类统一特征
| 维度 | 规律 |
|---|---|
| 密文长度 | 通常与明文长度相关,不是固定死长度 |
| 密文特征 | 常见 Base64 或 Hex;也可能直接是二进制 |
| 是否动态变化 | 重点看 iv / nonce / 随机盐 / 时间戳拼接 |
| 密钥长度特征 | 有明确要求,尤其 AES/SM4 很明显 |
| 初始化向量特征 | 很多模式需要;ECB 通常没有 |
| 是否可逆 | 可逆 |
六、非对称加密类
这一类最常见的是 RSA,国内场景还会看到 SM2。
和对称加密最大的区别是:它使用的是公钥 / 私钥体系,不是同一把 key。
1. RSA
| 项 | 特征 |
|---|---|
| 类型 | 非对称加密 / 签名 |
| 是否可逆 | 加密场景可由对应私钥解密;签名场景是可验签,不是直接"解密还原" |
| 密钥长度特征 | 常见 1024、2048、4096 bit |
| IV 特征 | 一般没有传统意义上的 iv |
| 密文长度特征 | 强依赖密钥长度;2048 bit 密钥常见原始密文 256 字节 |
| 密文常见表现 | 常转 Base64,也可能 Hex |
| 输出是否动态变化 | 使用 PKCS#1 v1.5、OAEP 等填充时,同样明文多次加密通常会变化 |
| 逆向识别点 | JSEncrypt、node-forge、publicKey、privateKey、encryptLong |
逆向里的几个实用判断:
- 密文明显比明文长很多。
- 明文常常很短,比如密码、随机 key、会话密钥。
- 代码里经常先
AES,再用RSA加密AES key,这是典型混合加密。
2. SM2
| 项 | 特征 |
|---|---|
| 类型 | 国密非对称加密 / 签名 |
| 是否可逆 | 加密场景可由私钥解密;签名场景可验签 |
| 密钥长度特征 | 基于椭圆曲线,常见公钥是固定格式长串 |
| IV 特征 | 一般不按 iv 理解 |
| 密文长度特征 | 通常明显长于输入,长度与编码格式有关 |
| 密文特征 | 常见 C1C3C2 或 C1C2C3 结构,很多实现输出 Hex |
| 输出是否动态变化 | 通常会变化,因为会引入随机数 |
| 逆向识别点 | sm2、C1C3C2、国密 SDK、政企系统 |
非对称类统一特征
| 维度 | 规律 |
|---|---|
| 密文长度 | 更多由密钥长度决定,而不是简单跟着明文长度线性变化 |
| 密文特征 | 常见 Base64 / Hex,长度通常偏长 |
| 是否动态变化 | 很多安全填充方案下会动态变化 |
| 密钥长度特征 | 公钥 / 私钥成对出现,长度明显长于对称 key |
| 初始化向量特征 | 一般不按对称加密的 iv 理解 |
| 是否可逆 | 加密场景可逆;签名场景是可验证,不是还原明文 |
七、编码类:最容易被误当成"加密"
这类严格来说不属于加密算法,但在 JS 逆向里出现频率极高,必须单独拿出来。
1. Base64
| 项 | 特征 |
|---|---|
| 类型 | 编码 |
| 是否可逆 | 是 |
| 密钥长度特征 | 无 |
| IV 特征 | 无 |
| 密文长度特征 | 长度通常约为原始字节数的 4/3 |
| 密文字符特征 | A-Z a-z 0-9 + / =,URL 安全版常见 - _ |
| 输出是否动态变化 | 同样输入不变 |
| 逆向识别点 | btoa、atob、Base64.stringify |
2. Hex
| 项 | 特征 |
|---|---|
| 类型 | 编码 |
| 是否可逆 | 是 |
| 密钥长度特征 | 无 |
| IV 特征 | 无 |
| 密文长度特征 | 原始每 1 字节通常对应 2 个十六进制字符 |
| 密文字符特征 | 0-9a-fA-F |
| 输出是否动态变化 | 同样输入不变 |
| 逆向识别点 | toString('hex')、enc.Hex.stringify() |
编码类统一特征
| 维度 | 规律 |
|---|---|
| 密文长度 | 严格按编码规则变化 |
| 密文特征 | 字符集很稳定,很有辨识度 |
| 是否动态变化 | 同样输入不变 |
| 密钥长度特征 | 没有 key |
| 初始化向量特征 | 没有 iv |
| 是否可逆 | 可逆 |
八、逆向里最实用的"长度 + 动态性"速判表
| 可疑结果特征 | 优先怀疑对象 |
|---|---|
固定 32 位十六进制 |
MD5 |
固定 40 位十六进制 |
SHA1 |
固定 64 位十六进制 |
SHA256 / SM3 |
固定 96 位十六进制 |
SHA384 |
固定 128 位十六进制 |
SHA512 |
长度约为原始数据 4/3,字符集像 Base64 |
Base64 或"某算法结果再 Base64" |
长度和明文接近,且常随 iv 变化 |
AES / SM4 / DES 一类对称加密 |
| 明文很短但输出很长,且代码里有公钥 | RSA / SM2 |
| 有 key 但输出固定长度、没有解密流程 | HMAC |
九、JS 逆向中常见代码特征
1. 哈希 / HMAC 常见样子
javascript
CryptoJS.MD5(data).toString()
CryptoJS.SHA256(data).toString()
CryptoJS.HmacSHA256(data, key).toString()
crypto.createHash('sha256').update(data).digest('hex')
crypto.createHmac('sha256', key).update(data).digest('hex')
识别重点:
- 往往只有
update和digest。 - 常没有
decrypt。 - 输出长度通常固定。
2. AES / DES 常见样子
javascript
CryptoJS.AES.encrypt(data, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString()
识别重点:
- 重点不是只看到
AES,而是继续抠key、iv、mode、padding。 - 如果结果每次都变,优先找动态
iv、时间戳、随机数。
3. RSA 常见样子
javascript
const encrypt = new JSEncrypt()
encrypt.setPublicKey(publicKey)
const result = encrypt.encrypt(data)
识别重点:
publicKey、privateKey、setPublicKey很显眼。- 常用于登录密码、公钥加密随机串、混合加密里的 key 交换。
十、实战里最容易误判的点
1. Base64 不是加密
很多接口参数看起来像乱码,其实只是 Base64 编码。
2. 有 key 不一定是对称加密
HMAC 也有 key,但它不可逆,而且输出通常固定长度。
3. 输出变了,不一定就是"加密算法变了"
很多时候算法没变,变的是:
ivnonce- 时间戳
- 随机数
- 拼接顺序
- 编码方式
4. 看到 AES 还不够
实际复现失败时,最常见原因不是算法名错,而是下面任意一项不一致:
keyivmodepadding- 输入字符串编码
- 输出编码是
Hex还是Base64
5. 固定长度不代表一定是哈希
有些对称加密结果经过固定长度截断、二次编码、切片后,也可能伪装成固定长度字符串,所以还要结合调用链判断。
十一、面向 JS 逆向的最终分类记忆
哈希 / 摘要
- 常见算法:
MD5、SHA1、SHA256、SHA512、SM3 - 输出长度:通常固定
- 是否动态:同样输入通常不变
- 是否可逆:否
key/iv:通常都没有
HMAC
- 常见算法:
HmacSHA256、HmacSHA1 - 输出长度:通常固定
- 是否动态:同样输入 + 同样 key 通常不变
- 是否可逆:否
key:有iv:没有
对称加密
- 常见算法:
AES、DES、3DES、SM4、RC4 - 输出长度:和输入长度相关
- 是否动态:取决于
iv/nonce - 是否可逆:是
key:有明确长度要求iv:很多模式有
非对称加密
- 常见算法:
RSA、SM2 - 输出长度:更受密钥长度影响
- 是否动态:很多填充模式下会变化
- 是否可逆:加密场景可逆,签名场景可验签
key:公钥 / 私钥iv:通常没有传统iv
编码
- 常见形式:
Base64、Hex - 输出长度:按编码规则变化
- 是否动态:不变
- 是否可逆:是
key/iv:都没有
十二、结论
如果你是从 JS 逆向角度识别"这到底是什么算法",最实用的不是背定义,而是抓这六个点:
- 长度是不是固定。
- 字符集像不像
Hex/Base64。 - 同样输入是否会变化。
- 有没有
key。 - 有没有
iv/nonce。 - 有没有明显的加密、解密、摘要、签名调用链。
把这几个点结合起来,通常就能很快把目标归类到:
- 哈希 / 摘要
- HMAC
- 对称加密
- 非对称加密
- 编码
在实际复现里,真正卡人的往往不是"这是不是 AES",而是:
key从哪来iv从哪来- 输入在加密前做了什么拼接
- 输出在加密后做了什么编码
这才是 JS 逆向里最有价值的分析重点。
感谢关注【遇事不決洛必達】!欢迎点赞收藏和交流指正,我会持续分享我的学习经验和心得。