2020-03-30

加密技术定义、使用

在开发爬虫的过程中,我们经常遇到的一种反爬措施是数据加密。常见的加密算法可以分为三类:对称加密算法,非对称加密算法和Hash算法(事实上不是加密算法而是摘要算法)

一、对称加密

1.定义

采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。由于其速度快,对称性加密通常在消息发送方需要加密大量数据时使用。但是,加解密双方使用同样的密钥进行加密和解密。密钥是控制加密及解密的指令,算法是一种规则,规定如何进行加密和解密。因此加密的安全性不仅取决于加密算法本身,密钥管理的安全性更是重要。因为加密解密都使用同一个密钥,如何把密钥安全地传递到解密者手上就成了必须要解决的问题。

2.工作过程

下面举个例子来简要说明一下对称加密的工作过程。甲和乙是一对生意搭档,他们住在不同的城市。由于生意上的需要,他们经常会相互之间邮寄重要的货物。为了保证货物的安全,他们商定制作一个保险盒,将物品放入其中。他们打造了两把相同的钥匙分别保管,以便在收到包裹时用这个钥匙打开保险盒,以及在邮寄货物前用这把钥匙锁上保险盒。

上面是一个将重要资源安全传递到目的地的传统方式,只要甲乙小心保管好钥匙,那么就算有人得到保险盒,也无法打开。这个思想被用到了现代计算机通信的信息加密中。

3.常用算法

对称加密的常用算法有:DES,3DES,AES

DES

简介

DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。

算法原理

太过非人类,有兴趣自行查阅相关资料。

算法特点

分组比较短、密钥太短、密码生命周期短、运算速度较慢。因为算法中有大量的位运算,一般在硬件中实现。

3DES

简介

3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次DES加密算法。由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解;3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法

AES

https://blog.csdn.net/lrwwll/article/details/78069013 有意思的博客

简介

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。

不同于它的前任标准DES,Rijndael使用的是代换-置换网络,而非Feistel架构。AES在软件及硬件上都能快速地加解密,相对来说较易于实作,且只需要很少的存储器。作为一个新的加密标准,目前正被部署应用到更广大的范围。

算法原理

不讨论。

设计思想
  • 抵抗所有已知的攻击。
  • 在多个平台上速度快,编码紧凑。
  • 设计简单。
实际开发中使用AES加密需要注意的地方
  • 服务端和我们客户端必须使用一样的密钥和初始向量IV
  • 服务端和我们客户端必须使用一样的加密模式
  • 服务端和我们客户端必须使用一样的Padding模式

以上三条有一个不满足,双方就无法完成互相加解密。

同时针对对称加密密钥传输问题这个不足:我们一般采用RSA+AES加密相结合的方式,用AES加密数据,而用RSA加密AES的密钥。同时密钥和IV可以随机生成,这要是128位16个字节就行,但是必须由服务端来生成,因为如果由我们客户端生成的话,就好比我们客户端存放了非对称加密的私钥一样,这样容易被反编译,不安全,一定要从服务端请求密钥和初始向量IV。

在python中使用

PyCrypto是 Python 中密码学方面最有名的第三方软件包。可惜的是,它的开发工作于2012年就已停止。

幸运的是,有一个该项目的分支PyCrytodome 取代了 PyCrypto 。

PyCrypto文档: https://pycryptodome.readthedocs.io/en/latest/src/introduction.html

安装与导入
  1. 完全替代老的PyCrypto库,你可以这样安装:

    pip install pycryptodome
    

    这种情况下,所有的模块安装在Crypto包下。

    避免同时安装PyCryptoPyCryptodome, 它们相互起冲突。

    因此,只有当您确定整个应用程序部署在virtualenv中时,才建议使用此选项。

  2. 一个独立于老的PyCrypto库的方案,你可以这样安装:

    pip install pycryptodomex
    

    这种情况下,所有的模块安装在Cryptodome包下。

    PyCryptoPyCryptodome可以共存。

不同操作系统的安装详见官方文档。

案例

DES案例
# DES 使用
import binascii
from Cryptodome.Cipher import DES
key = b'-8B key-'               # key 必须是8个字节64位

# 创建一个密码对象
# iv 参数也需要是一个8字节64位的二进制数的初始化向量
# DES.MOD_OFB加密模式
cipher = DES.new(key, DES.MODE_OFB, iv=b'12345179')
# 待加密数据
data = '我是心蓝最帅无敌'.encode()
# 加密
msg = cipher.encrypt(data)
# 输出二进制数据
print(msg)
# 输出16进制字符串
print(binascii.b2a_hex(msg))

# 解密过程

# 创建一个新的密码对象
# 模式,key,iv 和加密过程对应
cipher2 = DES.new(key, iv=cipher.iv, mode=DES.MODE_OFB)

# 解密
res = cipher2.decrypt(msg)
# 解码成明文字符串
print(res.decode('utf-8'))

文档参考:https://pycryptodome.readthedocs.io/en/latest/src/cipher/des.html

DES加密了解就好,几乎没人使用了。

3DES案例
# 3DES案例
from Cryptodome.Cipher import DES3

# 需要24个字节长度的key,一般会随机生成
# 本质上是三次des的key的串联,k1,k2,k3
# 当k1=k2=k3时,DES3降级为DES
key = b'12345678qwertyui12345678'

# 创建一个密码对象
cipher = DES3.new(key, DES3.MODE_CFB)
# 原数据
data = '我是心蓝'.encode()
# 加密
msg = cipher.encrypt(data)
print(msg)

# 解密过程
cipher2 = DES3.new(key, DES3.MODE_CFB, iv=cipher.iv)
# 解密
res = cipher2.decrypt(msg)
print(res.decode('utf-8'))

文档参考:https://pycryptodome.readthedocs.io/en/latest/src/cipher/des3.html

AES案例
# AES案例
from Cryptodome.Cipher import AES
# 16个字节的密码
key = b'1234567890123456'
# 创建加密对象
cipher = AES.new(key, AES.MODE_EAX)
data = '我是心蓝'.encode()
# 加密
msg = cipher.encrypt(data)

print(msg)
# 解密 过程
# 创建一个新的密码对象
cipher2 = AES.new(key, AES.MODE_EAX, nonce=cipher.nonce)
res = cipher2.decrypt(msg)
print(res.decode('utf-8'))

文档参考:https://pycryptodome.readthedocs.io/en/latest/src/cipher/modern.html

二、非对称加密

1.定义

对称加密算法是一种密钥的保密方法。

非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

2.特点

非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。

事实上,公钥加密算法很少用于数据加密,它通常只是用来做身份认证,因为它的密钥太长,加密速度太慢--公钥加密算法的速度甚至比对称加密算法的速度慢上3个数量级(1000倍)。

3.工作原理

  1. A要向B发送信息,A和B都要产生一对用于加密和解密的公钥和私钥
  2. A的私钥保密,A的公钥告诉B;B的私钥保密,B的公钥告诉A。
  3. A要给B发送信息时,A用B的公钥加密信息,因为A知道B的公钥。
  4. A将这个消息发给B(已经用B的公钥加密消息)。
  5. B收到这个消息后,B用自己的私钥解密A的消息。其他所有收到这个报文的人都无法解密,因为只有B才有B的私钥。

4.常用算法

非对称加密最常用,最广泛的算法是:RSA

RSA

简介

RSA加密算法是一种非对称加密算法。在公开密钥加密电子商业中RSA被广泛使用。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。今天只有短的RSA钥匙才可能被强力方式解破。到目前为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。

算法原理

RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

RSA的加解密过程非常简单:

公钥 (n, e)
私钥 (n, d)
加密 密文 = (明文^e)%n
解密 明文 = (密文^d)%n

RSA加密算法实现过程:https://www.cnblogs.com/coolYuan/p/9168284.html

RSA加密算法原理:http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html

RSA加密算法python实现:https://www.jb51.net/article/138018.htm

在python中使用

生成RSA密钥
# 生成RSA密钥
from Cryptodome.PublicKey import RSA

key = RSA.generate(2048)
private_key = key.export_key()
print(private_key)
file_out = open("private.pem", "wb")
file_out.write(private_key)
public_key = key.publickey().export_key()
print(public_key)
file_out = open("receiver.pem", "wb")
file_out.write(public_key)
使用RSA加密数据
from Cryptodome.PublicKey import RSA
from Cryptodome.Cipher import PKCS1_OAEP
data = '我是心蓝哈哈哈哈'.encode()

# 导入公钥
recipient_key = RSA.import_key(open("receiver.pem").read())
# 创建一个密码对象
cipher_rsa = PKCS1_OAEP.new(recipient_key)

# 加密
msg = cipher_rsa.encrypt(data)
print(msg)
使用RSA解密数据
# 接上面代码
# 导入私钥
private_key = RSA.import_key(open("private.pem").read())
cipher_rsa = PKCS1_OAEP.new(private_key)
# 解密
res = cipher_rsa.decrypt(msg)
print(res.decode('utf-8'))
爬虫中的用法

有些网站会在请求过程中发送公钥,然后加密参数后传回后台来实现数据的加密。

import binascii

from Cryptodome.PublicKey import RSA
from Cryptodome.Cipher import PKCS1_OAEP

data = '我是心蓝哈哈哈哈'.encode()
# 网页上收到的n值
pubkey_n = '8d7e6949d411ce14d7d233d7160f5b2cc753930caba4d5ad24f923a505253b9c39b09a059732250e56c594d735077cfcb0c3508e9f544f101bdf7e97fe1b0d97f273468264b8b24caaa2a90cd9708a417c51cf8ba35444d37c514a0490441a773ccb121034f29748763c6c4f76eb0303559c57071fd89234d140c8bb965f9725'
# e常常为65537
pbukey_e = 65537
# 生成公钥
recipient_key = RSA.RsaKey(n=int(pubkey_n, 16), e=65537)
# 创建rsa对象
cipher_rsa = PKCS1_OAEP.new(recipient_key)
# 加密数据
msg = cipher_rsa.encrypt(data)
print(msg)
# 输出16进制字符串
print(binascii.b2a_hex(msg))

三、Hash算法

1.定义

一种算法的名称,一般翻译为哈希,或者散列。

它是把任意长度的输入通过散列算法转变成固定长度的输出,该输出就是散列值。

2.特点

  • 不可逆: 无法通过散列值还原原来的数据
  • 定长输出:无论输入的原始数据有多长,结果长度相同
  • 抗修改:输入微小的改变,会引起结果的巨大改变
  • 强碰撞性:很难找到两段不同的数据,使他们产生相同的hash值

3.应用领域

  • 一致性验证
  • 数字签名
  • 安全访问认证

4.常用算法

md5

MD5消息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。

SHA家族

安全散列算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。

SHA家族的五个算法,分别是SHA-1、SHA-224、SHA-256、SHA-384,和SHA-512,由美国国家安全局(NSA)所设计,并由美国国家标准与技术研究院(NIST)发布;是美国的政府标准。后四者有时并称为SHA-2。

5.在python中使用

import hashlib
# sha1 sha256 sha512 一样的用法
info = '心蓝老师最帅!'
m = hashlib.md5(info.encode())  # 注意传入数据一定是二进制数据
res1 = m.hexdigest()  # 输出散列字符串
print(res1)
res2 = m.digest()   # 输出二进制数据

# 大数据的hash
big_m = hashlib.md5()
with open('movie.avi', 'rb') as f:
    for line in f:
        big_m.update(line)      # 循环追加
print(big_m.hexdigest())

作业

将RSA的加密过程通过面向对象的方式写成一个类,封装起来。

只需要传入一些参数就可以进行加密。

from Cryptodome.Cipher import AES, PKCS1_OAEP
from Cryptodome.PublicKey import RSA


class Rsa:
    def __init__(self, pubkey, e=65537):
        """
        create a Rsa object
        :param pubkey:
            public key
            It can be an integer or a string.
            When it is a string, its format is either
            a hexadecimal string or a PEM format
        :param e:
            The general value is 65537.
        """
        if isinstance(pubkey, int):
            self.key = RSA.RsaKey(n=pubkey, e=e)

        else:
            if not isinstance(pubkey, str):
                raise ValueError('pubkey must be str or int.')

            if '----' in pubkey:
                try:
                    self.key = RSA.import_key(pubkey)
                except Exception as e:
                    print(e)
            else:
                if pubkey == pubkey.lower():
                    pubkey = int(pubkey, 16)
                    self.key = RSA.RsaKey(n=pubkey, e=e)
                else:
                    pubkey = '-----BEGIN PUBLIC KEY-----\n' + pubkey + '\n-----END PUBLIC KEY-----'
                    try:
                        self.key = RSA.import_key(pubkey)
                    except Exception as e:
                        print(e)

    def encrypt(self, data):
        """
        encrypted data by rsa
        :param data: Plaintext
        :return: Binary ciphertext
        """
        cipher_rsa = PKCS1_OAEP.new(self.key)
        return cipher_rsa.encrypt(data)


class Aes:
    def __init__(self, key):
        """
        create a Aes object
        :param key: key used for encryption
        """
        if len(key) not in (16, 24, 32):
            raise ValueError('Incorrect AES key length.')
        if not isinstance(key, bytes):
            raise ValueError('The key must be bytes.')
        self.key = key

    def encrypt(self, data, mode, *args, **kwargs):
        """
        encrypted data by aes
        :param data: Plaintext
        :param mode: Encryption mode
        :param args:
        :param kwargs:
        :return: Binary ciphertext
        """
        cipher = AES.new(self.key, mode=mode, *args, **kwargs)
        if not isinstance(data, bytes):
            raise ValueError('The data must be bytes.')
        return cipher.encrypt(data)


if __name__ == '__main__':

    rsa = Rsa(pubkey=open("receiver.pem").read())
    res = rsa.encrypt('我是心蓝'.encode())
    print(res)
    print(len(res))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容

  • 专题一,主要介绍HTTPS建立安全链接的原理,包括非对称加密、对称加密、CA认证等知识,还包括对一些业界常用算法的...
    有何不可12317阅读 296评论 0 0
  • 这篇文章主要讲述在Mobile BI(移动商务智能)开发过程中,在网络通信、数据存储、登录验证这几个方面涉及的加密...
    雨_树阅读 2,316评论 0 6
  • 作者简介 原创微信公众号郭霖 WeChat ID: guolin_blog 大家早上好,转眼假期就结束了,又到了...
    木木00阅读 1,196评论 0 9
  • 前言 本文梳理主要基于书籍《Java加密与解密的艺术》、维基百科、百度百科以及网络上众多资料,如有涉及版权问题,请...
    hello_cyz阅读 2,091评论 1 7
  • 听到《疯狂动物城》这个名字,我的第一反应是《疯狂外星人》,这是去年五一我和毛毛一起看的电影。中国人翻译外国电影貌似...
    樸樹苗阅读 237评论 0 0