RSA.js 前端加密逆向实战:3步定位智慧江财登录密码加密逻辑

📅 2026/7/10 2:23:27 👁️ 阅读次数 📝 编程学习
RSA.js 前端加密逆向实战:3步定位智慧江财登录密码加密逻辑

RSA.js 前端加密逆向实战:3步定位智慧江财登录密码加密逻辑

当你在浏览器中输入账号密码点击登录时,那些看似简单的字符在传输前经历了怎样的蜕变?以江西财经大学智慧校园系统为例,其前端采用RSA非对称加密保护用户密码。本文将手把手带你用开发者工具解剖这套加密机制,掌握一套可复用的前端加密逆向分析方法。

1. 逆向分析前的准备工作

逆向工程如同侦探破案,需要先锁定"案发现场"。打开Chrome开发者工具(Windows快捷键F12,Mac快捷键Option+Command+I),我们主要使用以下功能模块:

  • Network面板:记录所有网络请求,重点关注XHR和Doc类型
  • Sources面板:查看和调试网页加载的所有JavaScript文件
  • Console面板:实时执行JavaScript代码片段
  • Elements面板:查看DOM结构和表单元素

首先访问智慧江财登录页,清空Network记录后执行一次登录操作。在Network面板的Filter输入login快速定位到登录请求,可以看到关键请求参数:

POST /cas/login HTTP/1.1 username=2202140875&password=7a8f9b3...&lt=_c4EC...&_eventId=submit

关键观察点

  • password参数值明显不是明文(长度固定且为十六进制字符串)
  • 存在lt等隐藏字段作为一次性令牌
  • 请求头包含Content-Type: application/x-www-form-urlencoded

2. 三步定位加密核心逻辑

2.1 全局搜索加密参数

在Sources面板按下Ctrl+Shift+F开启全局搜索,输入passwordencrypt等关键词。很快在某个js文件中发现可疑代码片段:

function checkInput(){ var pwd = document.getElementById("password").value; var encPwd = rsaEncrypt(pwd); document.getElementById("passwordEnc").value = encPwd; return true; }

这段代码揭示了加密流程:

  1. 获取明文密码输入
  2. 调用rsaEncrypt函数加密
  3. 将结果赋给隐藏表单字段passwordEnc

2.2 追踪加密函数实现

继续搜索rsaEncrypt函数定义,定位到核心加密逻辑:

function rsaEncrypt(text) { var rsa = new RSAKey(); rsa.setPublic( "5598e3b75d21a2989274e222fa59ab07d829faa29b544e3a920c4dd287aed9302a657280c23220a35ae985ba157400e0502ce8e44570a1513bf7146f372e9c842115fb1b86def80e2ecf9f8e7a586656d12b27529f487e55052e5c31d0836b2e8c01c011bca911d983b1541f20b7466c325b4e30b4a79652470e88135113c9d9", "10001" ); return rsa.encrypt(text); }

关键参数说明

  • n:RSA模数(Modulus),十六进制大整数
  • e:公钥指数(Exponent),通常为65537(0x10001)
  • encrypt():执行实际加密操作

2.3 验证加密结果

在Console面板直接调用加密函数验证:

rsaEncrypt("test123") // 输出:7a8f9b3d5e6c12a4f7...

与Network中捕获的加密结果格式一致,确认这就是目标加密函数。

3. 深度解析RSA.js实现

通过进一步分析,发现系统使用了经典的RSA加密库组合:

文件功能依赖关系
rsa.js核心RSA算法实现依赖jsbn.js
jsbn.js大整数运算库无依赖
rng.js随机数生成器依赖prng4.js
prng4.js伪随机数生成器实现无依赖

加密调用链如下:

  1. RSAKey()构造函数初始化密钥对象
  2. setPublic(n, e)设置公钥参数
  3. encrypt(text)执行PKCS#1 v1.5填充和模幂运算

典型加密流程代码

// 初始化RSA实例 const rsa = new RSAKey(); // 设置公钥(实际项目这些参数可能需要动态获取) rsa.setPublic( "5598e3b75d21a2989274e222fa59ab07d829faa29b544e3a920c4dd287aed9302a657280c23220a35ae985ba157400e0502ce8e44570a1513bf7146f372e9c842115fb1b86def80e2ecf9f8e7a586656d12b27529f487e55052e5c31d0836b2e8c01c011bca911d983b1541f20b7466c325b4e30b4a79652470e88135113c9d9", "10001" ); // 加密密码 const encrypted = rsa.encrypt("myPassword123"); console.log(encrypted); // 输出加密结果

4. 动态参数处理实战技巧

在实际逆向过程中,经常会遇到参数动态变化的情况。以下是几种常见场景的应对策略:

4.1 公钥参数动态获取

有时n/e参数会通过接口返回或写在页面元素中。可通过以下方式提取:

// 从页面元素获取 const n = document.querySelector("#rsaN").value; const e = document.querySelector("#rsaE").value; // 从接口响应获取(需Hook XMLHttpRequest或Fetch API) const originalOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function() { this.addEventListener("load", function(){ if(this.responseURL.includes("getRSAKey")) { const data = JSON.parse(this.responseText); console.log("获取到RSA参数:", data.n, data.e); } }); return originalOpen.apply(this, arguments); };

4.2 加密函数Hook技巧

当加密函数被混淆或难以定位时,可以Hook关键函数:

// 保存原始函数 const originalEncrypt = window.rsaEncrypt; // 重写函数 window.rsaEncrypt = function(text) { console.log("加密原文:", text); const result = originalEncrypt(text); console.log("加密结果:", result); return result; };

4.3 自动化脚本示例

结合上述分析,可以编写自动登录脚本(Node.js示例):

const { RSAKey } = require("./rsa"); const axios = require("axios"); async function login(username, password) { // 第一步:获取登录页动态参数 const { data } = await axios.get("https://ssl.jxufe.edu.cn/cas/login"); const lt = parseLT(data); // 从HTML中提取lt参数 // 第二步:RSA加密密码 const rsa = new RSAKey(); rsa.setPublic( "5598e3b75d21a2989274e222fa59ab07d829faa29b544e3a920c4dd287aed9302a657280c23220a35ae985ba157400e0502ce8e44570a1513bf7146f372e9c842115fb1b86def80e2ecf9f8e7a586656d12b27529f487e55052e5c31d0836b2e8c01c011bca911d983b1541f20b7466c325b4e30b4a79652470e88135113c9d9", "10001" ); const encPassword = rsa.encrypt(password); // 第三步:提交登录 const params = new URLSearchParams(); params.append("username", username); params.append("password", encPassword); params.append("lt", lt); params.append("_eventId", "submit"); const response = await axios.post("https://ssl.jxufe.edu.cn/cas/login", params); console.log("登录结果:", response.data); } function parseLT(html) { // 实现从HTML中提取lt参数的逻辑 return html.match(/name="lt" value="([^"]+)"/)[1]; }

逆向分析前端加密就像解谜游戏,关键在于找到正确的线索入口。通过本文介绍的三步法——抓包定位、全局搜索、参数追踪,配合开发者工具的灵活使用,可以系统性地破解大多数网站的前端加密逻辑。