JavaScript逆向之摘要算法

什么是摘要算法

JavaScript 中的摘要算法(也称为哈希函数或散列函数)是一种将任意长度的数据映射为固定长度字符串的算法。这个输出的字符串被称为"摘要"或"哈希值"。 这种算法具有以下关键特性: **1. 单向性:从原始数据生成摘要非常容易,但从摘要反向推算出原始数据几乎是不可能的。

  1. 确定性:相同的数据输入,无论执行多少次,永远会得到相同的摘要。
  2. 抗碰撞性:即使对原始数据做极其微小的改动(比如改变一个字母),生成的摘要也会变得面目全非。找到两个不同输入却能产生相同摘要的"碰撞"是极其困难的。**

在 JavaScript 中实现摘要算法,通常不推荐手动编写算法本身,因为它复杂且容易出错。最常见和可靠的方式是使用成熟的第三方库如crypto-js

摘要算法分类

MD5

算法介绍

想象一下,你要给一份非常重要的文件(比如一份合同)做一个独一无二的标记,这个标记能代表整个文件的内容。MD5 就是这样一种技术。 它的全称是 Message-Digest Algorithm 5(信息摘要算法第五版)。它具有以下几个关键特性:

  1. 固定长度输出 (Fixed-Length Output) 无论你的输入数据有多长------无论是短短一句话还是一个几 GB 大的电影文件------MD5 计算出的结果(摘要或哈希值)永远是 128位 的。这个 128 位的值通常被表示为一个 32 个字符的十六进制字符串。 例如: e10adc3949ba59abbe56e057f20f883e

  2. 确定性 (Deterministic) 只要输入的数据完全相同,无论在何时、何地、用何种工具计算,其 MD5 值永远是一模一样的。这是保证其可靠性的基础。

  3. 高灵敏性 (Avalanche Effect) 输入数据哪怕只有最微小的改变(比如一个字母的大小写变化、多一个空格),计算出的 MD5 值也会变得天差地别、完全不同。 "Hello, world" 的 MD5 值是 3e25960a79dbc69b674cd4ec67a72c62 "hello, world" 的 MD5 值是 5eb63bbbe01eeed093cb22bb8f5acdc3

  4. 单向性 (One-Way Function) 从原始数据计算出 MD5 值非常容易和快速。但是,几乎不可能从 MD5 值反向推算出原始数据。这就像你可以轻易地把一头牛做成汉堡肉,但不可能把汉堡肉再变回一头牛。

这是关于 MD5 最重要的一点:由于存在严重的安全漏洞,MD5 已被认为是不安全的加密算法,绝对不应再用于任何需要安全保障的场景。

JavaScript 实现

需先安装crypto-js

bash 复制代码
npm install crypto-js
javascript 复制代码
// 引入整个库
const CryptoJS = require('crypto-js');

// 或者只引入 MD5 模块以减小打包体积
// import MD5 from 'crypto-js/md5';

const message = "Hello, World!";

// 计算 MD5 哈希
const hash = CryptoJS.MD5(message).toString(CryptoJS.enc.Hex);

console.log(`原始消息: "${message}"`);
console.log(`MD5 哈希: ${hash}`);
// 输出: MD5 哈希: 65a8e27d8879283831b664bd8b7f0ad4

Python 实现

直接使用标准库hashlib模块

python 复制代码
import hashlib

# 要进行哈希计算的字符串
message = "Hello, World!"

# 1. 创建一个 MD5 hash 对象
md5_hash = hashlib.md5()

# 2. 更新 hash 对象的内容
#    必须将字符串编码为字节 (bytes),通常使用 'utf-8'
md5_hash.update(message.encode('utf-8'))

# 3. 获取十六进制的摘要 (digest)
hex_digest = md5_hash.hexdigest()

print(f"原始消息: '{message}'")
print(f"MD5 哈希值: {hex_digest}")
# 输出: MD5 哈希值: 65a8e27d8879283831b664bd8b7f0ad4

SHA

算法介绍

它的全称是 Secure Hash Algorithm,即安全散列算法。具有以下几个至关重要的特性:

  1. 固定长度 (Fixed Length):无论输入的数据多大或多小,输出的哈希值长度永远是固定的。例如,SHA-256 的输出永远是 256 位(表示为 64 个十六进制字符)。

  2. 确定性 (Deterministic):相同的数据输入,无论计算多少次,永远会得到完全相同的哈希值。

  3. 单向性 (One-Way):从原始数据生成哈希值非常容易,但从哈希值反向推算出原始数据是不可能的。这就像你可以从一个人的 DNA 确定他的指纹,但无法从指纹再造出这个人。

  4. 高灵敏性 (Avalanche Effect):原始数据哪怕发生最微小的改变(比如一个字母的大小写变化),生成的哈希值也会变得面目全非。

SHA是一系列算法的总称,对比如下:

算法系列 具体名称 (Specific Name) 输出长度 (位) 输出长度 (十六进制字符) 内部结构 当前安全状态 主要特点与应用
SHA-1 SHA-1 160 40 Merkle--Damgård 不安全 (Insecure) 已被完全弃用。 存在已知的碰撞攻击漏洞。曾是行业标准,现已被所有主流应用淘汰。
SHA-2 SHA-224 224 56 Merkle--Damgård 安全 (Secure) SHA-256 的截短版,使用较少。
SHA-256 256 64 Merkle--Damgård 安全 (当前事实标准) 应用最广泛的哈希算法。 用于数字签名、区块链(比特币)、TLS/SSL 等。是绝大多数场景的首选
SHA-384 384 96 Merkle--Damgård 安全 (Secure) SHA-512 的截短版,用于需要更高安全级别的特定场景。
SHA-512 512 128 Merkle--Damgård 安全 (高强度) 提供极高的安全级别。在 64 位系统上性能优于 SHA-256。用于长期数据归档和高安全要求的应用。
SHA-3 SHA3-224 224 56 Keccak (海绵结构) 安全 (Secure) 新一代标准。基于与 SHA-2 完全不同的 Keccak 结构,作为其强大的备用方案。
SHA3-256 256 64 Keccak (海绵结构) 安全 (Secure) SHA-256 的新一代对应版本,提供了结构上的多样性,增强了密码学的稳健性。
SHA3-384 384 96 Keccak (海绵结构) 安全 (Secure) SHA-384 的新一代对应版本。
SHA3-512 512 128 Keccak (海绵结构) 安全 (Secure) SHA-512 的新一代对应版本,提供最高的安全级别和全新的内部设计。

JavaScript 实现

需先安装crypto-js

bash 复制代码
npm install crypto-js
javascript 复制代码
const CryptoJS = require('crypto-js');

const myMessage = "Hello, World!";

// 直接调用相应的算法函数,并用 .toString() 转换为十六进制字符串
const hash = CryptoJS.SHA256(myMessage).toString(CryptoJS.enc.Hex);

console.log(`原始消息: "${myMessage}"`);
console.log(`SHA-256 哈希 (crypto-js): ${hash}`);
// 预期输出: a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e

Python 实现

直接使用标准库hashlib模块

python 复制代码
import hashlib

message = "Hello, World!"

# 必须先将字符串编码为字节 (bytes)
encoded_message = message.encode('utf-8')

# --- SHA-256 (推荐,当前标准) ---
sha256_hash = hashlib.sha256(encoded_message).hexdigest()
print(f"原始消息: '{message}'")
print(f"SHA-256 哈希: {sha256_hash}")
print(f"长度: {len(sha256_hash)} 个字符 (256 位)")

HMAC

算法介绍

它的全称是 Hash-based Message Authentication Code,即基于哈希的消息认证码。简单来说,HMAC 是一种通过密钥来增强摘要算法(如 SHA-256)安全性的技术。它是一种"带密钥的哈希" (keyed hash),能够同时保证数据的完整性 (Integrity)和真实性 (Authentication)。HMAC 并不是一个全新的摘要算法,而是一种标准化的使用方式,它将一个密钥和一个摘要算法(如 SHA-256)组合在一起。其计算过程可以简化理解为一个巧妙的"双重哈希"结构:

python 复制代码
HMAC(Key, Message) = Hash( Key + Hash( Key + Message ) )

HMAC 的核心优点:

  1. 数据完整性 (Data Integrity):与普通哈希一样,证明数据在传输过程中没有被修改。

  2. 身份验证 (Authentication):这是 HMAC 的关键价值。由于计算 HMAC 必须持有正确的共享密钥,因此验证通过就等于确认了消息的来源是可信的,而不是伪造的。

JavaScript 实现

需先安装crypto-js

bash 复制代码
npm install crypto-js
javascript 复制代码
const CryptoJS = require('crypto-js');

const mySecretKey = 'my-super-secret-key';
const myMessage = 'This is a message to authenticate';

// 直接调用 HmacSHA256 方法,传入消息和密钥
const signature = CryptoJS.HmacSHA256(myMessage, mySecretKey).toString(CryptoJS.enc.Hex);

console.log(`消息: "${myMessage}"`);
console.log(`密钥: "${mySecretKey}"`);
console.log(`HMAC-SHA256 签名 (crypto-js): ${signature}`);
// 预期输出: 5b5d844512c4423bd865e95ba45d55a3fd95d55b0a390d45362e269f8d550302

Python 实现

python 复制代码
import hmac
import hashlib

# 1. 准备密钥和消息 (作为普通字符串)
secret_key = 'my-super-secret-key'
message = 'This is a message to authenticate'

# 2. 将密钥和消息都编码为字节 (bytes)
key_bytes = secret_key.encode('utf-8')
message_bytes = message.encode('utf-8')

# 3. 创建 HMAC 对象
#    hmac.new(key, message, digest_algorithm)
hmac_object = hmac.new(
    key_bytes,
    msg=message_bytes,
    digestmod=hashlib.sha256
)

# 4. 获取十六进制格式的签名
signature = hmac_object.hexdigest()

print(f"消息: '{message}'")
print(f"密钥: '{secret_key}'")
print(f"HMAC-SHA256 签名: {signature}")

# HMAC-SHA256 签名: 5b5d844512c4423bd865e95ba45d55a3fd95d55b0a390d45362e269f8d550302

逆向技巧

根据生成的字符串长度和固定不变的特点来推断使用的是哪种摘要算法,然后使用相关加密工具来证实。例如,加密字符串有以下特征:

  • 32个字符的16进制字符串
  • 同样的字符串加密结果不变

那要高度怀疑使用的是MD5算法,可以使用字符串"1"进行MD5计算出的16进制摘要为c4ca4238a0b923820dcc509a6f75849b 来进一步确认使用的是否是标准的MD5算法。如果是则可以直接使用crypto-js 本地实现。

字符串"1"计算出的摘要

算法 (Algorithm) 安全状态 (Security Status) 摘要值 (十六进制)
MD5 ❌ 不安全 (Insecure) c4ca4238a0b923820dcc509a6f75849b
SHA-1 ❌ 不安全 (Insecure) 356a192b7913b04c54574d18c28d46e6395428ab
SHA-224 ✅ 安全 (Secure) ab8b6038d157a3dc17f0dfc613c799a22f08a230d705663b6522c713
SHA-256 ✅ 安全 (Secure) 6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b
SHA-384 ✅ 安全 (Secure) e59b581559b3b0a5a36371804e76d08b3e828d15f79119ce01e3e110e75a3641dfd82a6327e57f6f59450c265d95e267
SHA-512 ✅ 安全 (Secure) 4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172ce793f8c42415f487b1e8f480982e0782b2f63d808fe6

案例

我们看下下面接口请求header里的x-signature 很明显这个参数是40位16进制的字符,我们怀疑这个可能是SHA-1,定位代码加密的位置如下图 这里从字面上可以看出使用的是HMAC,摘要算法是SHA-1,我们猜测的没错!那到底是不是标准的算法呢,这里我们做个测试。 我们使用在线工具,测试同样的加密字符串和密钥 这里我们就证实了网站使用的是标准的HMAC摘要算法是SHA-1,所以我们就不需要去扣代码,直接使用第三方库crypto-js

相关推荐
SamsongSSS5 小时前
JavaScript逆向SM国密算法
javascript·算法·逆向
Samsong1 天前
自动收集webpack调用模块
逆向
ningmengjing_2 天前
webpack打包方式
前端·爬虫·webpack·node.js·逆向
shellvon2 天前
前端攻防:揭秘 Chrome DevTools 与反调试的博弈
前端·逆向
Samsong2 天前
JavaScript逆向之补环境
逆向
CYRUS_STUDIO6 天前
静态分析神器 + 动态调试利器:IDA Pro × Frida 混合调试实战
android·逆向
CYRUS STUDIO7 天前
FART 自动化脱壳框架优化实战:Bug 修复与代码改进记录
android·自动化·逆向·fart
CYRUS_STUDIO7 天前
静态分析根本不够!IDA Pro 动态调试 Android 应用的完整实战
android·逆向
CYRUS_STUDIO7 天前
攻防 FART 脱壳:实现 AJM 壳级别的对抗功能 + 绕过全解析
android·安全·逆向