加密在爬虫中经常涉及,常见的加密有MD5, SHA1, HMAC, DES, AES, RSA。
常见的加密算法基本分为这几类:
- 线性散列算法(签名算法)MD5 SHA
- 对称加密算法 AES DES
- 非对称加密算法 RSA
1. 线性散列算法(签名算法)
1.1 MD5
Message-Digest Algorithm,消息摘要算法,一种被广泛使用的密码散列函数,它能够将任意长度的消息转换成128bit的消息摘要,这个特性被称为“压缩”。
相比Base64编码,MD5的运算过程要复杂很多。由于MD5在运算过程中使用了补位、追加和移位等操作,所以他人无法从输出结果倒推出输入字符,这个特性被称为不可逆,所以解密一般是通过暴力穷举,以及网站的接口实现解密。
MD5的RFC文档编号为1321,文档地址为https://tools.ietf.org/html/rfc1321。RFC1321约定了一些术语和符号,并描述了MD5算法的计算步骤和方法。
MD5的典型应用场景就是一致性验证,如文件一致性和信息一致性。在注册账号时的密码一般都是用的MD5加密。
md5加密后产生一个固定长度(16字节,32位)的数据,在线加密解密网址:https://md5jiami.bmcx.com/
字符串:123456 可加密成16位或32位
16位小写:49ba59abbe56e057
32位小写:e10adc3949ba59abbe56e057f20f883e
# e10adc39 49ba59abbe56e057 f20f883e 32位其实就是16位前后加了一些东西
MD系列的加密方式有很多,增加破解成本的方法举例:
- 使用一段无意义且随机的私匙进行MD5加密会生成一个加密串,称为串1,将要加密的的数据跟串1拼接,再进行一次MD5,这时会生成串2,将串2再次进行MD5加密,这时生成的串3就是加密后的数据
Js实现如下:
# Js可以通过crypto-js加密库进行算法实现
const CryptoJs = require('crypto-js');
let password = 'vahan123';
let encPwd = CryptoJs.MD5(password).toString();
python实现如下:
import hashlib
obj = hashlib.md5() # 加盐:obj = hashlib.md5("salt".encode('utf-8'))
obj.update('vahan'.encode('utf-8'))
v1 = obj.hexdigest() # fb0e22c79ac75679e9881e6ba183b354 十六进制
v2 = obj.digest() # b'\xfb\x0e"\xc7\x9a\xc7Vy\xe9\x88\x1ek\xa1\x83\xb3T' 二进制字节
1.2 SHA1
Secure Hash Algorithm,安全哈希算法,比MD5的安全性更强,对长度小于2^64位的消息,SHA1会产生一个160bit的消息摘要。一般在未高度混淆的Js代码中,SHA1加密的关键词就是sha1。
SHA在线加密解密网站:http://www.wetools.com/sha/
从代码上看,SHA1与MD5的实现很相似:
Js实现如下:
const CryptoJs = require('crypto-js');
let password = 'vahan123';
let encPwd = CryptoJs.SHA1(password).toString();
python实现如下:
import hashlib
m = hashlib.sha1()
m.update("vahan".encode("utf-8"))
m.hexdigest()
1.3 HMAC
Hash Message Authentication Code,散列消息鉴别码。HMAC加密算法是一种安全的基于加密hash函数和共享密钥的消息认证协议。实现原理是用公开函数和密钥产生一个固定长度的值作为认证标识,用这个标识鉴别消息的完整性。
以HMAC中的SHA256加密为例:
Js实现如下:
const CryptoJs = require('crypto-js');
let key = 'key';
let text = 'vahan';
let hash = CryptoJs.HmacSHA256(text, key);
let hashInHex = CryptoJs.enc.Hex.stringify(hash);
python实现如下:
import hmac
import hashlib
key = 'key'.encode()
text = 'vahan'.encode()
mac = hmac.new(key, text, hashlib.sha256) # 或 hashlib.sha512
mac.digest()
mac.hexdigest()
2 对称加密算法
2.1 DES
Data Encryption Standard,数据加密标准,是一种对称加密方式,其加密、解密使用同样的密钥,密钥长度为56位。
破解方法:暴力破解。DES使用 56 位的密钥,则可能的密钥数量是 2 的 56 次方个,只要计算足够强大是可以被破解的。
DES算法的入口参数:Key、Data、Mode,padding
- Key 为7个字节共56位,是DES算法的工作密钥;
- Data 是要被加密或被解密的数据;
- Mode 为DES的工作方式;
- padding 为填充模式,如果加密后密文长度达不到指定整数倍(8个字节、16个字节),填充对应字符,padding的赋值固定为 CryptoJS.pad.Pkcs7 即可。
Js逆向时,DES加密的搜索关键词有DES,mode,padding等:
deskey = CryptoJS.enc.Utf8.parse("12345678");
message = CryptoJS.enc.Utf8.parse("vahan");
cfg = {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
};
// DES加密
var encrypt = CryptoJS.DES.encrypt(message,deskey,cfg).toString();
// DES解密
var decrypt = CryptoJS.DES.decrypt(encrypt,deskey,cfg).toString(CryptoJS.enc.Utf8);
python实现代码:
import binascii
from pyDes import des, CBC, PAD_PKCS5
def des_encrypt(secret_key, s):
iv = secret_key
k = des(secret_ley, CBC, iv, pad=None, padmode=PAD_PKCS5)
en = k.encrypt(s,padmode=PAD_PKCS5)
return binascii.b2a_hex(en) # # 将二进制字符串转换成对应的十六进制数据
def des_decrypt(secret_key, s):
iv = secret_key
k = des(secret_ley, CBC, iv, pad=None, padmode=PAD_PKCS5)
de = k.decrypt(binascii.a2b_hex(s),padmode=PAD_PKCS5) # 将十六进制字符串转换成对应的二进制数据
return de
secret_str = des_encrypt('999', 'vahan')
clear_str = des_decrypt('999', secret_str)
提醒:ECB 是电子密码本模式,这是DES的一种简单模式,但在实际应用中通常推荐使用更安全的模式,如CBC模式。在python中,不同的库实现DES的代码形式不同,但结果是一样的。
2.2 AES
Advanced Encryption Standard,高级加密标准,这个标准用来替代原先的DES,是美国联邦政府采用的一种区块加密标准。
AES和DES的区别:
-
加密后密文长度的不同:DES加密后密文长度是8的整数倍,AES加密后密文长度是16的整数倍
-
应用场景不同:企业级开发使用DES足够安全,如果要求高使用AES
AES的填充模式常用的有三种,分别是NoPadding,ZeroPadding,Pkcs7,默认为Pkcs7。
Js逆向时,AES加密的搜索关键词有AES,mode,padding等:
let aeskey = "1234567890abcdef";
let message = "vahan";
cfg = {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
};
// DES加密
var encrypt = CryptoJS.AES.encrypt(message,aeskey,cfg).toString(); // 得到的结果是字符串
// DES解密
let key = CryptoJs.enc.Utf8.parse("1234567890abcdef");
var decrypt = CryptoJS.AES.decrypt(encrypt,key,cfg).toString(CryptoJS.enc.Utf8); // vahan
aes.js 实现:
// 加密
function encrypt(data,key,iv) { //key,iv:16B的字符串
var key = CryptoJS.enc.Latin1.parse(key);
var iv = CryptoJS.enc.Latin1.parse(iv);
return CryptoJS.AES.encrypt(data, key,{
iv : iv,
mode : CryptoJS.mode.CBC,
padding : CryptoJS.pad.ZeroPadding
}).toString();
}
// 解密
function decrypt(data,key,iv){ //key,iv:16B的字符串
var key = CryptoJS.enc.Latin1.parse(key);
var iv = CryptoJS.enc.Latin1.parse(iv);
var decrypted=CryptoJS.AES.decrypt(data,key,{
iv : iv,
mode : CryptoJS.mode.CBC,
padding : CryptoJS.pad.ZeroPadding
});
return decrypted.toString(CryptoJS.enc.Utf8);
}
Python 实现代码:
import base64
from Crypto.Cipher import AES
# AES
# 需要补位,str不是16的倍数那就补足为16的倍数
def add_to_16(value):
while len(value) % 16 != 0:
value += '\0'
return str.encode(value) # 返回bytes
# 加密方法
def encrypt(key, text):
aes = AES.new(add_to_16(key), AES.MODE_ECB) # 初始化加密器
encrypt_aes = aes.encrypt(add_to_16(text)) # 先进行aes加密
encrypt_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8')
return encrypt_text
# 解密方法
def decrypt(key, text):
aes = AES.new(add_to_16(key), AES.MODE_ECB) # 初始化加密器
base64_decrypted = base64.decodebytes(text.encode(encoding='utf-8'))
decrypted_text = str(aes.decrypt(base64_decrypted), encoding='utf-8').replace('\0', '') # 执行解密并转码返回str
return decrypted_text
下面介绍CBC模式的实现代码,作为了解即可:
pip install pycryptodome
当key与iv是普通字符串时:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
def aes_encrypt(data_string):
key = "fd6b639dbcff0c2a1b03b389ec763c4b".encode('utf-8')
iv = "77b07a672d57d64c".encode('utf-8')
data = data_string.encode("utf-8")
aes = AES.new(
key=key,
mode=AES.MODE_CBC,
iv=iv
)
raw = pad(data, 16)
return aes.encrypt(raw)
data = "|878975262|1.3.5|ktjwlm89_to920weqpg|433070"
result = aes_encrypt(data)
print(result)
当key与iv是十六进制字符串时:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import binascii
def aes_encrypt(data_string):
key = binascii.a2b_hex("4E2918885FD98109869D14E0231A0BF4")
iv = binascii.a2b_hex("16B17E519DDD0CE5B79D7A63A4DD801C")
aes = AES.new(
key=key,
mode=AES.MODE_CBC,
iv=iv
)
raw = pad(data_string.encode('utf-8'), 16)
return aes.encrypt(raw)
data = "|878975262|1.3.5|ktjwlm89_to920weqpg"
result = aes_encrypt(data)
print(result)
3. 非对称加密算法
3.1 RSA
RSA,全称Rivest-Shamir-Adleman,RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。RSA是第一个能同时用于加密和数字签名的算法,它能够抵抗目前为止已经的所有密码攻击。
非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥),私有密钥(privatekey:简称私钥),公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
注意:使用时都是使用公匙加密使用私匙解密。公匙可以公开,私匙自己保留。
Js代码中的RSA常见标志 setPublickey。
Js实现加密可以使用jsencrypt加密库,另外需要生成好公钥和私钥,可以到在线网站去生成:http://web.chacuo.net/netrsakeypair
<html>
<script src="https://cdn.bootcss.com/jsencrypt/3.0.0-beta.1/jsencrypt.js"></script>
<script type="text/javascript">
//公钥
var PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALyBJ6kZ/VFJYTV3vOC07jqWIqgyvHulv6us/8wzlSBqQ2+eOTX7s5zKfXY40yZWDoCaIGk+tP/sc0D6dQzjaxECAwEAAQ==-----END PUBLIC KEY-----';
//私钥
var PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvIEnqRn9UUlhNXe84LTuOpYiqDK8e6W/q6z/zDOVIGpDb545NfuznMp9djjTJlYOgJogaT60/+xzQPp1DONrEQIDAQABAkEAu7DFsqQEDDnKJpiwYfUE9ySiIWNTNLJWZDN/Bu2dYIV4DO2A5aHZfMe48rga5BkoWq2LALlY3tqsOFTe3M6yoQIhAOSfSAU3H6jIOnlEiZabUrVGqiFLCb5Ut3Jz9NN+5p59AiEA0xQDMrxWBBJ9BYq6RRY4pXwa/MthX/8Hy+3GnvNw/yUCIG/3Ee578KVYakq5pih8KSVeVjO37C2qj60d3Ok3XPqBAiEAqGPvxTsAuBDz0kcBIPqASGzArumljkrLsoHHkakOfU0CIDuhxKQwHlXFDO79ppYAPcVO3bph672qGD84YUaHF+pQ-----END PRIVATE KEY-----';
//使用公钥加密
var encrypt = new JSEncrypt();//实例化加密对象
encrypt.setPublicKey(PUBLIC_KEY);//设置公钥
var encrypted = encrypt.encrypt('hello bobo!');//对指定数据进行加密
//使用私钥解密
var decrypt = new JSEncrypt();
decrypt.setPrivateKey(PRIVATE_KEY);//设置私钥
var uncrypted = decrypt.decrypt(encrypted);//解密
</script>
</html>
python实现代码较多,需要时自行搜索。
4. 国密算法
国密算法,即国家密码管理局发布的一系列国产商用密码标准算法,旨在保障国家信息安全。以下是对国密加密的详细介绍:
一、国密算法的主要类型
SM1:
- 类型:分组加密算法,属于对称加密算法。
- 特点:分组长度和密钥长度都为128比特,算法安全保密强度及相关软硬件实现性能与AES相当。
- 应用:该算法不公开,仅以IP核的形式存在于芯片中,已研制出系列芯片、智能IC卡、智能密码钥匙、加密卡、加密机等安全产品,广泛应用于电子政务、电子商务及国民经济的各个应用领域。
SM2:
- 类型:椭圆曲线公钥密码算法,属于非对称加密算法。
- 特点:性能更优更安全,密码复杂度高、处理速度快、机器性能消耗更小。
- 应用:可用于数据加密、解密、数字签名等操作,广泛应用于数据加密、数字签名、身份认证和网络安全等领域。此外,SM2算法还适用于物联网领域,保护物联网设备之间的通信安全,确保数据的可靠传输。
SM3:
- 类型:密码散列函数标准。
- 特点:主要用于数字签名及验证、消息认证码生成及验证、随机数生成等,其安全性及效率与SHA-256相当。
- 应用:在信息安全领域,SM3算法被用于保护密码学协议、数字证书和电子签名等数据的完整性。在区块链领域,SM3算法被用于加密货币的区块生成和链上交易的校验,确保区块链的安全性。此外,SM3算法还可以应用于密码学随机数的生成和伪随机序列的校验等领域,增加了数据的安全性和可靠性。
SM4:
- 类型:分组密码标准,属于对称加密算法。
- 特点:分组长度与密钥长度均为128bit,加密算法与密钥扩展算法都采用32轮非线性迭代结构,S盒为固定的8比特输入8比特输出。算法公开。
- 应用:主要用于数据加密,实现简单,加解密速度较快,消耗资源少,适用于加密静态储存或数据信号传输通道中的数据。此外,SM4算法还适用于散列算法、消息认证码和伪随机数生成器等领域,实现了多种功能的全面升级。
此外,国家密码管理局还发布了SM7、SM9以及祖冲之密码算法(ZUC)等算法,这些算法在各自的领域也发挥着重要的作用。