爬虫圈,常见的加密手段,你应该了解一下

举报
梦想橡皮擦 发表于 2023/05/29 11:48:32 2023/05/29
【摘要】 常见加密手段 实验介绍本实验为大家介绍一下常见的加密技术,掌握之后,可以在反爬时加入各加密算法,从而提高爬虫采集难度,本实验为大家介绍三类加密,其一是消息摘要算法/签名算法,其二是对称加密,最后一种是非对称加密,每一类型,都通过 Python 代码进行实践。特别提醒,本实验内容不会对加密算法底层逻辑进行解析,学习重点在应用层。 知识点消息摘要算法/签名算法实践对称加密算法实践非对称加密算法...

常见加密手段

实验介绍

本实验为大家介绍一下常见的加密技术,掌握之后,可以在反爬时加入各加密算法,从而提高爬虫采集难度,本实验为大家介绍三类加密,其一是消息摘要算法/签名算法,其二是对称加密,最后一种是非对称加密,每一类型,都通过 Python 代码进行实践。特别提醒,本实验内容不会对加密算法底层逻辑进行解析,学习重点在应用层。

知识点

  • 消息摘要算法/签名算法实践
  • 对称加密算法实践
  • 非对称加密算法实践

消息摘要算法/签名算法

md5 加密

md5 信息摘要算法,是最常用的密码散列函数,其可以产生 128 位的散列值,也就是 128 个 0 和 1 的二进制串,由于长度太长,故将二进制转换成了 16 进制,每 4 位表示一个十六进制,因此常见的 md5 都是 32 位。

在实践中还存在 16 位的 md5 值,该值是将 32 位 md5 去掉前 8 位,去掉后 8 位得到。

Code 目录建立 15_demo 文件夹,然后创建 md5_demo.py 文件,示例代码如下所示:

import hashlib

my_str = '梦想橡皮擦'
hl = hashlib.md5()
hl.update(my_str.encode("utf8"))
hl_my_str = hl.hexdigest()

# 加密之后的数据
print(hl_my_str)

# 加入参数,防止被撞库
hl2 = hashlib.md5(bytes('加盐', encoding='utf-8'))
hl2.update(my_str.encode("utf-8"))
hl2_str = hl2.hexdigest()
print(hl2_str)

md5 信息摘要算法其不可逆,并且有如下特点:

  • 压缩性:任意长度的数据,计算出 md5 长度固定;

  • 易计算:md5 模块使用便捷,计算方便;

  • 抗修改:md5 的原始数据做任何修改,都会导致 md5 发生变化;

  • 抗碰撞:加参数之后,被撞库的概率极低。

SHA1 加密

SHA1 安全哈希算法,是一种数字签名算法,其基于 md5 ,加密后会产生一长度 160 位的散列值,比 md5 多了 32 位,故安全性更高,但速度较慢。

import hashlib

str = "梦想橡皮擦"

a = hashlib.sha1(str.encode("utf-8")).hexdigest()
print("sha1 加密前,字符串为",str)

print("sha1 加密后,字符串为",a)

对称加密算法

DES 加密

DES 是一种比较传统的数据加密标准,属于对称加密,即通过密钥可以还原密码为明文。

在 Python 中可以通过 pyDes 库实现,使用命令 pip3 install pyDes 安装库。

创建 des_demo.py,代码如下所示:

import base64
from pyDes import *

Des_Key = "xiangpia" # 自定义 Key,长度为 8

Des_IV = "12345678" # 自定义 IV 向量


# 加密函数
def DesEncrypt(code, key=None, iv=None):
    if key is None:
        key=Des_Key
    if iv is None:
        iv=Des_IV

    k = des(key, CBC, iv, pad=None, padmode=PAD_PKCS5)
    EncryptStr = k.encrypt(code)
    return base64.b64encode(EncryptStr)

# 解密函数
def DesDecrypt(encode, key=None, iv=None):
    if key is None:
        key=Des_Key
    if iv is None:
        iv=Des_IV

    k = des(key, CBC, iv, pad=None, padmode=PAD_PKCS5)
    b64str = base64.b64decode(encode)
    return k.decrypt(b64str)


if __name__ == '__main__':
    ret = DesEncrypt("hello lanqiao")
    print(ret)

运行代码,得到下述输出:

上述代码中比较重要的内容如下所示:

# 加密核心函数
k = des(key, CBC, iv, pad=None, padmode=PAD_PKCS5)

其中 key 相当于是加密盐,CBC 是加密模式,iv 是加密向量,pad 填充值,padmode 是填充方式,具体说明如下:

初始向量

初始向量缩写为 iv,一般也称作初始变数,它可以与密钥结合使用,为固定长度的值,在实战中一般使用随机数初始化。

加密模式

目前主流的加密和数字认证算法,基本都采用块加密,即将明文分成大小相等的数据块,然后执行加密算法,常见的模式说明如下所示,有兴趣的可以单独进行深入学习:

  • ECB:电子密码本模式,密文被分隔成长度相等的块,单独进行加密;

  • CBC:密码块连接模式,使用循环的形式,将前一块的密文和当前块异或之后再加密;

  • CFB:密码反馈模式,翻转的 CBC 模式;

  • OFB:输出反馈模式;

  • CTR:计数器模式。

填充方式 padmode

由于 des 需要将明文分成大小相等的数据块,所以最后一块数据在加密前需要进行填充,常见的填充形式有:

  • PKCS7:假设数据长度需要填充 n 个字节,那就填充 n 个字节,并且每个字节的大小都是 n;

  • PKCS5:PKCS7 的子集,块大小固定为 8 字节;

  • ZeroPadding:所有字节填充为 0;

  • ISO10126:填充字节为随机数值。

AES 加密

AES 是一种高级加密标准,一般情况下用来替代 DES,故二者逻辑基本一致,实现该加密算法,需要使用 Crypto 库实现,先用命令 pip3 install pycryptodome 进行安装。

建立 aes_demo.py 文件,然后导入模块并定义全局变量。

import base64
from Crypto.Cipher import AES

iv = '1234567887654321'
key = 'xiangxiangxiang1'

data = 'hello lanqiao'

代码说明如下:

  • iv:初始向量;

  • key:密钥,长度是 128 bit,故使用长度为 16 的字符串;

  • data:待加密数据。

接下来编写加密函数:

import base64
from Crypto.Cipher import AES

iv = '1234567887654321'
key = 'xiangxiangxiang1'  # 长度为 16
data = 'hello lanqiao'


# 由于 AES 区块固定为 128 bit,所以字节长度最低需要16位
def pad(data):
    pad_data = data
    for i in range(0, 16 - len(data)):
        pad_data = pad_data + ' '
    return pad_data


# 实现 AES 加密
def aes_encode(key, data):

    # 将长度补齐到 16 位
    if len(data) < 16:
        data = pad(data)
    # 初始化 aes 对象,模式为 CBC
    aes_obj = AES.new(key.encode("utf-8"), AES.MODE_CBC, iv.encode("utf-8"))
    # 执行加密方法
    aes_en_str = aes_obj.encrypt(data.encode("utf-8"))
    # 进行 base64编码
    aes_en_str = base64.b64encode(aes_en_str)
    # 转换成字符串
    aes_en_str = aes_en_str.decode("utf-8")
    return aes_en_str


if __name__ == '__main__':
    data = aes_encode(key, data)
    print(data)

密文解码函数如下所示:

def aec_de(key, data):
    # 密文进行二进制编码
    data = data.encode("utf-8")
    # 解 base64 编码
    data = base64.b64decode(data)

    aes_de_obj = AES.new(key.encode("utf-8"), AES.MODE_CBC, iv.encode("utf-8"))
    # 解密
    aes_de_str = aes_de_obj.decrypt(data)
    # 去空格
    aes_de_str = aes_de_str.strip()
    # 明文解码
    aes_de_str = aes_de_str.decode("utf-8")
    return aes_de_str


if __name__ == '__main__':
    data = aes_encode(key, data)
    ret = aec_de(key, data)
    print(ret)

非对称加密算法

采用两个密钥进行加密和解密,对应的分别是公钥和私钥,如使用公钥对数据加密,则必须使用私钥解密。

RSA 加密算法

RSA 加密算法时常见的 非对称加密算法,该算法效率比较低,所以一般用于重要数据加密,在 Python 中可以使用 Crypto 库实现该算法,上文已经对该库进行了安装。

下面优先生成公钥和私钥。

from Crypto import Random
from Crypto.PublicKey import RSA

# 生成伪随机数
random_gen = Random.new().read
# 生成秘钥对实例对象,其中 1024 是秘钥的长度

rsa = RSA.generate(1024, random_gen)
# 获取私钥,保存到文件

private_pem = rsa.exportKey()
with open('private.pem', 'wb') as f:
    f.write(private_pem)
# 获取公钥,保存到文件
public_pem = rsa.publickey().exportKey()
with open('public.pem', 'wb') as f:
    f.write(public_pem)

公钥创建完毕之后,就可以使用其进行加密了,代码如下。

import base64
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5

msg = "梦想橡皮擦"
# 读取公钥
key = open('public.pem').read()
public_key = RSA.importKey(key)
# 加密
pk = PKCS1_v1_5.new(public_key)
encrypt_text = pk.encrypt(msg.encode())
# 加密后进行 base64 编码
result = base64.b64encode(encrypt_text)
# 转换成字符串
result_str = bytes.decode(result)
print(result)
print(result_str)

运行代码得到如下结果:

解密需要通过私钥进行,从 private.pem 读取私钥,然后调用 PKCS1_v1_5.new(private_key).decrypt() 方法即可实现,示例代码如下所示:

import base64
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from Crypto import Random

key = open('private.pem').read()
private_key = RSA.importKey(key)

cipher = PKCS1_v1_5.new(private_key)

# random_generator = Random.new().read
# 待解密字符串:lwiHsq3ZCa6+AogrAm5fMAJrkFvWu5aT2D9znAo3JqnLez3GLvhofQzmI2QaNL5ToCxp9SnngsLiG4weE4V/tavy9q0hVjzHofWOPri4ZfdMFtKWsRUUZwR3ifNaJTmDcmGBX6su5ES3KgL7wGUF1qQgQcpEaY/aKKb/IP5fPJw=
text = cipher.decrypt(base64.b64decode("lwiHsq3ZCa6+AogrAm5fMAJrkFvWu5aT2D9znAo3JqnLez3GLvhofQzmI2QaNL5ToCxp9SnngsLiG4weE4V/tavy9q0hVjzHofWOPri4ZfdMFtKWsRUUZwR3ifNaJTmDcmGBX6su5ES3KgL7wGUF1qQgQcpEaY/aKKb/IP5fPJw="), None)
print(text.decode('utf8'))

运行代码可以得到前文加密内容,临摹该案例注意公钥和私钥的搭配使用。

Base64 编码

Base64 是一种常见 8 位字节编码方式,由于 Base64 编码不可读,所以其也会被用于加密,在 Python 中,可以使用内置 base64 模块进行编码和解码,注意只能用包含 ASCII 的字符或二进制数据进行编码。

示例代码如下所示:

import base64

a = base64.b64encode(b"hello world")
print(a)

b = base64.b64decode(b'aGVsbG8gd29ybGQ=')
print(b)

运行代码输出结果如下所示:

b'aGVsbG8gd29ybGQ='
b'hello world'

Base 64 编码经常出现在其它加密代码中,所以是必备技能。

总结

本实验为大家介绍了三大类加密方式,每种加密方式下都包含多种加密实现,学习不同的加密算法,并将其合理的应用到自己的站点中,可以整体提高爬取难度。

在后续的学习中,可以对每种加密算法进行深入学习,了解其原理和实现,从而在实战项目中,将多种加密手段搭配使用。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。