一、加密算法概述
刚开始做爬虫逆向的时候,看到各种加密算法一脸懵。MD5、SHA、AES、RSA,这些名词听起来都很高大上,但不知道它们到底是干嘛的,什么时候该用哪个。
后来慢慢摸索,发现其实加密算法就分几大类:哈希、对称加密、非对称加密。理解了它们的原理和适用场景,再遇到加密的接口就不慌了。
加密算法分类
- 哈希算法:MD5、SHA-1、SHA-256,单向转换,不可逆
- 对称加密:AES、DES,加密解密用同一个密钥
- 非对称加密:RSA,公钥加密、私钥解密
- 消息认证:HMAC,验证消息完整性和真实性
二、哈希算法
哈希算法是最常用的加密方式。它把任意长度的输入转换成固定长度的输出,而且这个过程是单向的,无法从输出反推输入。
2.1 MD5
MD5 是最经典的哈希算法,输出固定 32 位十六进制字符串。
import hashlib
# MD5 加密
def md5_encrypt(text):
md5 = hashlib.md5()
md5.update(text.encode('utf-8'))
return md5.hexdigest()
# 使用
result = md5_encrypt('hello world')
print(result) # 5eb63bbbe01eeed093cb22bb8f5acdc3
注意:MD5 已经被证明不安全,可以被碰撞攻击。现在主要用于数据完整性校验,不用于密码存储。
2.2 SHA 系列
SHA 家族比 MD5 更安全,常用的有 SHA-1、SHA-256、SHA-512。
import hashlib
# SHA-1
sha1 = hashlib.sha1()
sha1.update('hello world'.encode('utf-8'))
print(sha1.hexdigest())
# SHA-256(推荐)
sha256 = hashlib.sha256()
sha256.update('hello world'.encode('utf-8'))
print(sha256.hexdigest())
# SHA-512
sha512 = hashlib.sha512()
sha512.update('hello world'.encode('utf-8'))
print(sha512.hexdigest())
2.3 哈希算法对比
| 算法 | 输出长度 | 安全性 | 适用场景 |
|---|---|---|---|
| MD5 | 128 位(32 字符) | 低 | 数据校验、非安全场景 |
| SHA-1 | 160 位(40 字符) | 中 | 一般数据校验 |
| SHA-256 | 256 位(64 字符) | 高 | 密码存储、数字签名 |
| SHA-512 | 512 位(128 字符) | 很高 | 高安全场景 |
三、对称加密
对称加密用同一个密钥进行加密和解密。特点是速度快,适合加密大量数据。
3.1 AES 加密
AES 是目前最常用的对称加密算法。
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
# AES 加密
def aes_encrypt(text, key, iv):
"""AES-CBC 加密"""
cipher = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
padded_data = pad(text.encode('utf-8'), AES.block_size)
encrypted = cipher.encrypt(padded_data)
return base64.b64encode(encrypted).decode('utf-8')
# AES 解密
def aes_decrypt(encrypted_text, key, iv):
"""AES-CBC 解密"""
cipher = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
encrypted_data = base64.b64decode(encrypted_text)
decrypted = cipher.decrypt(encrypted_data)
return unpad(decrypted, AES.block_size).decode('utf-8')
# 使用
key = '0123456789abcdef' # 16 字节密钥
iv = 'abcdef0123456789' # 16 字节初始向量
text = 'hello world'
encrypted = aes_encrypt(text, key, iv)
print(f"加密后: {encrypted}")
decrypted = aes_decrypt(encrypted, key, iv)
print(f"解密后: {decrypted}")
3.2 AES 的工作模式
| 模式 | 特点 | 适用场景 |
|---|---|---|
| ECB | 简单,但安全性低 | 不推荐 |
| CBC | 需要 IV,安全性好 | 常用 |
| CTR | 并行加密,速度快 | 高并发场景 |
| GCM | 自带认证,最安全 | 高安全场景 |
四、非对称加密
非对称加密使用一对密钥:公钥和私钥。公钥加密的数据只能用私钥解密,反之亦然。
4.1 RSA 加密
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64
# 生成密钥对
key = RSA.generate(2048)
private_key = key.export_key()
public_key = key.publickey().export_key()
# 保存密钥
with open('private.pem', 'wb') as f:
f.write(private_key)
with open('public.pem', 'wb') as f:
f.write(public_key)
# RSA 加密
def rsa_encrypt(text, public_key):
rsa_key = RSA.import_key(public_key)
cipher = PKCS1_v1_5.new(rsa_key)
encrypted = cipher.encrypt(text.encode('utf-8'))
return base64.b64encode(encrypted).decode('utf-8')
# RSA 解密
def rsa_decrypt(encrypted_text, private_key):
rsa_key = RSA.import_key(private_key)
cipher = PKCS1_v1_5.new(rsa_key)
encrypted_data = base64.b64decode(encrypted_text)
decrypted = cipher.decrypt(encrypted_data, None)
return decrypted.decode('utf-8')
# 使用
text = 'hello world'
encrypted = rsa_encrypt(text, public_key)
print(f"加密后: {encrypted}")
decrypted = rsa_decrypt(encrypted, private_key)
print(f"解密后: {decrypted}")
4.2 非对称加密的特点
- 安全性高:私钥不传输,很难被窃取
- 速度慢:比对称加密慢 100-1000 倍
- 适合小数据:通常用于加密密钥,而非大量数据
五、HMAC 消息认证
HMAC 结合了哈希算法和密钥,用于验证消息的完整性和真实性。
5.1 HMAC 实现
import hmac
import hashlib
# HMAC-SHA256
def hmac_sha256(message, secret_key):
h = hmac.new(secret_key.encode('utf-8'), message.encode('utf-8'), hashlib.sha256)
return h.hexdigest()
# 使用
message = 'hello world'
secret = 'my_secret_key'
signature = hmac_sha256(message, secret)
print(f"HMAC: {signature}")
# 验证
expected = hmac_sha256(message, secret)
if hmac.compare_digest(signature, expected):
print("验证通过")
else:
print("验证失败")
5.2 HMAC 在爬虫中的应用
很多网站的接口会用 HMAC 对请求参数签名,防止篡改。参考本站的 51job 数据采集实战,其中 sign 参数就是用 HmacSHA256 生成的。
六、Base64 编码
Base64 不是加密算法,而是一种编码方式。它把二进制数据转换成文本,方便传输。
6.1 Base64 编码解码
import base64
# 编码
text = 'hello world'
encoded = base64.b64encode(text.encode('utf-8')).decode('utf-8')
print(f"编码后: {encoded}") # aGVsbG8gd29ybGQ=
# 解码
decoded = base64.b64decode(encoded).decode('utf-8')
print(f"解码后: {decoded}") # hello world
6.2 URL 安全的 Base64
# URL 安全的 Base64(替换 +/ 为 -_)
encoded = base64.urlsafe_b64encode(text.encode('utf-8')).decode('utf-8')
print(f"URL 安全编码: {encoded}")
decoded = base64.urlsafe_b64decode(encoded).decode('utf-8')
print(f"解码后: {decoded}")
七、爬虫中的加密应用
7.1 识别加密类型
遇到加密参数时,先根据特征判断加密类型:
| 特征 | 可能的算法 |
|---|---|
| 32 位十六进制 | MD5 |
| 40 位十六进制 | SHA-1 |
| 64 位十六进制 | SHA-256 |
| Base64 编码,长度可变 | AES、RSA |
7.2 实战:逆向加密参数
import hashlib
import time
def generate_sign(params, secret_key):
"""模拟接口签名生成"""
# 1. 排序参数
sorted_params = sorted(params.items())
# 2. 拼接字符串
param_str = '&'.join([f'{k}={v}' for k, v in sorted_params])
# 3. 拼接密钥
sign_str = f'{param_str}&key={secret_key}'
# 4. MD5 加密
sign = hashlib.md5(sign_str.encode('utf-8')).hexdigest()
return sign
# 使用
params = {
'page': '1',
'size': '20',
'timestamp': str(int(time.time()))
}
secret_key = 'your_secret_key'
sign = generate_sign(params, secret_key)
params['sign'] = sign
print(f"签名: {sign}")
print(f"完整参数: {params}")
八、总结
加密算法是爬虫逆向的核心技能。理解每种算法的原理和适用场景,才能在遇到加密接口时快速找到突破口。
| 算法类型 | 代表算法 | 特点 | 适用场景 |
|---|---|---|---|
| 哈希 | MD5、SHA-256 | 单向、不可逆 | 数据校验、密码存储 |
| 对称加密 | AES | 速度快、密钥相同 | 大量数据加密 |
| 非对称加密 | RSA | 安全性高、速度慢 | 密钥交换、数字签名 |
| 消息认证 | HMAC | 验证完整性 | 接口签名验证 |
遇到加密不要慌,先用 在线加解密工具 验证猜测,确认算法后再写代码实现。