Node.js RSA 前端密码加密逆向:3步定位 jsbn.js 与 rng.js 依赖链
Node.js RSA前端密码加密逆向:3步定位jsbn.js与rng.js依赖链
当你在分析一个网站的前端加密逻辑时,经常会遇到复杂的JavaScript依赖关系。特别是在处理RSA加密时,往往会牵扯到多个加密库的相互调用。本文将以一个典型场景为例,教你如何快速定位并理解这些依赖关系。
1. 逆向分析前的准备工作
在开始逆向分析之前,我们需要准备好必要的工具和环境。首先确保你已经安装了最新版本的Chrome浏览器和Node.js运行环境。对于代码分析,推荐使用VS Code作为编辑器,它提供了优秀的JavaScript调试功能。
关键工具清单:
- Chrome开发者工具(F12打开)
- VS Code + JavaScript调试插件
- Node.js 16+ 运行环境
- Postman或类似的API测试工具
提示:在进行逆向分析时,建议使用无痕浏览模式,避免浏览器缓存干扰分析结果。
2. 定位加密入口点
打开目标网站并调出开发者工具,切换到Network面板。在登录表单中输入测试凭据(如用户名:test,密码:123456),但先不要点击登录。此时开启"Preserve log"选项,然后执行登录操作。
观察网络请求,你会发现密码字段通常以加密形式传输。在我们的案例中,password参数显示为一长串看似随机的字符:
password: "a7f3d8c1b5e902f4d6..."接下来,我们需要在源代码中定位这个加密过程的实现位置。使用Chrome的全局搜索功能(Ctrl+Shift+F),搜索关键词如"encrypt"、"RSA"或"password"。很快我们就能找到加密入口:
// 加密入口示例代码 function encryptPassword(rawPass) { const rsa = new RSAKey(); rsa.setPublic(MODULUS, EXPONENT); return rsa.encrypt(rawPass); }3. 追踪加密库依赖链
现在我们已经找到了加密入口,接下来需要分析其依赖关系。在我们的案例中,RSA实现依赖于三个关键文件:
| 文件名称 | 功能描述 | 依赖关系 |
|---|---|---|
| rsa.js | 提供RSA加密核心功能 | 依赖jsbn.js和rng.js |
| jsbn.js | 大整数运算库 | 无外部依赖 |
| rng.js | 随机数生成器 | 依赖prng4.js |
通过分析调用栈,我们发现完整的依赖链如下:
- 主页面调用rsa.js的encrypt方法
- rsa.js依赖jsbn.js进行大数运算
- rsa.js同时依赖rng.js生成随机数
- rng.js又依赖prng4.js实现伪随机数生成
关键代码分析:
// rsa.js中的关键片段 function RSAEncrypt(text) { // 使用jsbn.js的BigInteger const m = new BigInteger(text, 16); // 使用rng.js的随机数生成器 const rng = new SecureRandom(); // 加密核心逻辑 const c = this.doPublic(m, rng); return c.toString(16); }4. 构建独立的Node.js加密模块
理解了加密逻辑和依赖关系后,我们可以将这些代码移植到Node.js环境中。首先需要将以下文件保存到本地:
- rsa.js
- jsbn.js
- rng.js
- prng4.js
然后创建一个封装模块:
// encrypt.js const { RSAKey } = require('./rsa'); const fs = require('fs'); class RSACrypto { constructor(publicKey) { this.rsa = new RSAKey(); const [modulus, exponent] = publicKey.split('|'); this.rsa.setPublic(modulus, exponent); } encrypt(plainText) { return this.rsa.encrypt(plainText); } static fromConfigFile(path) { const config = JSON.parse(fs.readFileSync(path)); return new RSACrypto(config.publicKey); } } module.exports = RSACrypto;使用这个模块非常简单:
const RSACrypto = require('./encrypt'); const crypto = new RSACrypto('MODULUS|EXPONENT'); const encrypted = crypto.encrypt('mypassword'); console.log('Encrypted:', encrypted);5. 常见问题与调试技巧
在实际操作中,你可能会遇到各种问题。以下是几个常见情况及解决方法:
依赖加载顺序错误
确保文件加载顺序正确:先加载prng4.js,然后是rng.js、jsbn.js,最后是rsa.js。加密结果不一致
检查以下几点:- 公钥参数(模数和指数)是否正确
- 文本编码是否一致(通常是UTF-8)
- 随机数生成器是否正常工作
性能优化
对于高频加密场景,可以考虑:- 预初始化RSAKey实例
- 使用Web Worker避免阻塞主线程
- 缓存加密结果(适用于相同输入)
注意:在实际项目中,加密参数可能会定期更换。建议实现自动化的参数抓取机制,而不是硬编码在代码中。
通过以上步骤,你应该已经掌握了前端RSA加密的逆向分析方法。这种方法不仅适用于登录场景,也可以应用于其他需要分析前端加密逻辑的情况。记住,理解加密原理比单纯复制代码更重要,这能帮助你在遇到变种加密方案时快速适应。
