常见的加密 (MD5, SHA1, HMAC, DES, AES, RSA)

加密在爬虫中经常涉及,常见的加密有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)等算法,这些算法在各自的领域也发挥着重要的作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值