> ## Content Index
> Fetch the complete content index at: https://blog.vercanti.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# 加密算法识别
- URL: https://blog.vercanti.com/jia-mi-suan-fa-shi-bie/
- Published: 2026-08-28T14:35:11.000Z
- Updated: 2026-08-28T14:58:15.000Z
- Description: 快速判断目标加密算法，是逆向流程的第一步。 搜索以下关键字： MD5 的 JavaScript 特征：在函数内部有大量位运算（>>>, <<, |, ^），以及十六进制常量（如 0x67452301、0xefcdab89）。 判断模式： RSA 加密同一份数据每次结果不同（PKCS1 v1.5 填充随机），可以此区分 AES。 没有明显库特征，通常表现为： 部分网站使用自定义 Base64 字母表（字母表顺序被打乱），密文看起来是 Base64 但标准解码失败。 识别方法：在代码中搜索长度为 64 的字符串常量，即为自定义字母表。 先看输出长度和字符集，
- Author: yellowdog
- Tags: js逆向, 技巧步骤

> 官方文档：<https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines>  
> 适用场景：通过密文特征、输出长度和关键字快速判断目标使用的加密/哈希算法

快速判断目标加密算法，是逆向流程的第一步。

---

## 算法特征对照表

| 算法       | 输出长度                | 字符集              | 其他特征          |
| -------- | ------------------- | ---------------- | ------------- |
| MD5      | 32 位（hex）/ 16 位（短版） | \[0-9a-f\]       | 固定长度，无法解密     |
| SHA-1    | 40 位                | \[0-9a-f\]       | \-            |
| SHA-256  | 64 位                | \[0-9a-f\]       | \-            |
| SHA-512  | 128 位               | \[0-9a-f\]       | \-            |
| HMAC     | 同对应 SHA             | \[0-9a-f\]       | 需要 secret key |
| AES      | 变长（16 的倍数字节）        | Base64 编码后可见 +/= | 需要 key + iv   |
| DES/3DES | 同 AES               | Base64           | key 为 8/24 字节 |
| RSA      | 128/256/512 字节      | Base64           | 含公私钥，相同明文密文不同 |
| Base64   | 原始长度 × 4/3          | \[A-Za-z0-9+/=\] | 末尾常有 \= 填充，可逆 |

---

## 代码层面识别

### MD5 / SHA

搜索以下关键字：

```
md5  sha1  sha256  sha512  CryptoJS.MD5  CryptoJS.SHA256

```

MD5 的 JavaScript 特征：在函数内部有大量位运算（`>>>`, `<<`, `|`, `^`），以及十六进制常量（如 `0x67452301`、`0xefcdab89`）。

### AES

```javascript
// CryptoJS 使用特征
CryptoJS.AES.encrypt(message, key, { iv: iv, mode: ... })
CryptoJS.AES.decrypt(...)

// 内置 WebCrypto API
crypto.subtle.encrypt({ name: 'AES-CBC', iv }, key, data)

```

判断模式：

- `CBC`：需要 IV，最常见
- `ECB`：无 IV，相同明文 → 相同密文
- `GCM`：带认证标签

### RSA

```javascript
// 特征关键字
new JSEncrypt()
jsencrypt.setPublicKey(...)
forge.pki.publicKeyFromPem(...)

```

RSA 加密同一份数据每次结果不同（PKCS1 v1.5 填充随机），可以此区分 AES。

### 自定义加密

没有明显库特征，通常表现为：

- 大量位运算和循环
- 硬编码的字符表（如 Base62、自定义 Base64）
- 函数名经过混淆，只能通过逻辑分析还原

---

## 常见加密库特征

| 库名         | 全局变量 / 特征            | 备注                          |
| ---------- | -------------------- | --------------------------- |
| CryptoJS   | CryptoJS             | 最常见，覆盖 MD5/SHA/AES/DES/HMAC |
| jsencrypt  | JSEncrypt            | RSA 加密                      |
| node-forge | forge                | RSA/AES/证书处理                |
| crypto-js  | require('crypto-js') | Node.js 同款                  |
| sjcl       | sjcl                 | Stanford 出品，轻量              |
| WebCrypto  | crypto.subtle        | 浏览器原生，异步                    |

---

## 识别流程

```
1. 抓包，找到加密参数
2. 观察密文特征（长度、字符集、是否每次变化）
3. 全局搜索加密库关键字
4. 在 Network → Initiator 或 XHR 断点定位调用位置
5. 在 Scope 面板找到 key / iv 的实际值
6. 本地验证还原

```

---

## Base64 变体识别

部分网站使用自定义 Base64 字母表（字母表顺序被打乱），密文看起来是 Base64 但标准解码失败。

识别方法：在代码中搜索长度为 64 的字符串常量，即为自定义字母表。

```javascript
// 标准 Base64 字母表
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

// 自定义变体示例（字母表顺序不同）
"ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba9876543210+/"

```

---

## 最佳实践

**先看输出长度和字符集，再看代码**：固定长度十六进制字符串大概率是哈希（32=MD5，40=SHA-1，64=SHA-256）；变长含 `+/=` 是 Base64；变长纯十六进制是对称加密。确定类别后再进 DevTools 搜索，节省时间。

**用已知输入验证判断**：用 `"test"` 作为输入测试目标加密函数，然后用 Python 计算各算法对 `"test"` 的结果并比对，快速定位算法。比靠代码阅读猜测更可靠。

**同时识别 JS 库标志**：`CryptoJS` → 找 `CryptoJS.AES`/`MD5`/`SHA256`；`forge` → 找 `forge.cipher`；`sjcl` → 找 `sjcl.cipher`；`jsencrypt` → RSA；搜索这些库名比搜算法关键字命中率更高。

**国密算法单独建分支识别**：发现常规算法（AES/RSA/SHA）对不上时，再搜索国密关键字（`sm2`、`sm3`、`sm4`、`gmssl`、`smCrypto`、`OSCCA`）。国密近年在政府/金融类网站普及率显著上升。

**用 `魔法数字速查` 文档配合 S-Box 搜索**：找到疑似的加密函数后，搜索文档中对应算法的特征常量，二次确认识别结果，避免误判。

---

## 常见陷阱

### 陷阱：把 HMAC 输出误认为哈希

**现象：** 签名参数长度与 SHA-256 输出一致，但用标准 SHA-256 无法复现。  
**原因：** HMAC-SHA256 和 SHA-256 输出同为 64 字符十六进制，区别在于 HMAC 额外使用了密钥。  
**解决：** 搜索代码中是否有密钥参数（`key`、`secret`、`salt`）传入哈希函数；若有，换用 HMAC 计算。

### 陷阱：Base64 变体被误认为加密

**现象：** 用标准 Base64 解码后得到乱码，认为有加密。  
**原因：** 自定义字母表 Base64 的字符集与标准不同，直接解码结果错误。  
**解决：** 在代码中搜索长度为 64 的字符串常量（自定义字母表），找到后用 `str.maketrans` 替换后再 Base64 解码：`base64.b64decode(s.translate(str.maketrans(custom_table, standard_table)))`。

### 陷阱：AES-ECB 与 AES-CBC 混淆

**现象：** 知道是 AES 加密，但用 CBC 解密出乱码；改用 ECB 正常。  
**原因：** ECB 模式不需要 IV，每个块独立加密；若代码中没有 IV 参数或 IV 为全零，通常是 ECB 或 Zero-IV CBC。  
**解决：** 检查 CryptoJS 调用中的 `mode` 参数（`CryptoJS.mode.ECB` / `CBC`）；若没有显式指定，查看是否传了 IV 参数。

---

## 参见

[概念基础](https://blog.vercanti.com/jia-mi-suan-fa-ji-chu-gai-nian/)  
[魔法数字速查](https://blog.vercanti.com/jia-mi-suan-fa-mo-fa-shu-zi-su-cha/)  
[MD5](https://blog.vercanti.com/md5/)  
[SHA](https://blog.vercanti.com/sha-xi-lie/)  
[Base64与编码](https://blog.vercanti.com/base64-yu-bian-ma/)

还原方法：提取字母表，使用标准 Base64 解码时替换字母表即可。