python爬虫之数据加密解密
一、什么叫数据加密
数据加密是指利用加密算法和秘钥将明文转变为密文的过程。
二、数据加密的方式
1、单向加密
指只能加密数据而不能解密数据,这种加密方式主要是为了保证数据的完整性,常见的加密算法有MD5、sha系列等(位于python内置的hashlib模块中)。
2、对称加密
指数据加密和解密使用相同的秘钥,这种加密方式主要是为了保证数据的机密性,常见的加密算法有DES、AES(位于python第三方库pycrytodomex中)。
3、非对称加密
也叫公钥加密,指数据加密和解密使用不同的密钥,这种加密方式基本不可能被破解,主要用于身份验证等方面,常见的加密算法有DSA、RSA(位于python第三方模块rsa中)。
三、加密算法
1、单向加密算法(MD5、sha系列)
from hashlib import md5, sha256, sha512 m = md5() m.update("123".encode()) print(m.hexdigest()) # 32 # 202cb962ac59075b964b07152d234b70 print(m.digest()) # b‘ ,\xb9b\xacY\x07[\x96K\x07\x15-#Kp‘ s = sha512() s.update("123".encode()) print(s.hexdigest()) # 3c9909afec25354d551dae21590bb26e38d53f2173b8d3dc3eee4c047e7ab1c1eb8b85103e3be7ba613b31bb5c9c36214dc9f14a42fd7a2fdb84856bca5c44c2 print(s.digest()) b‘<\x99\t\xaf\xec%5MU\x1d\xae!Y\x0b\xb2n8\xd5?!s\xb8\xd3\xdc>\xeeL\x04~z\xb1\xc1\xeb\x8b\x85\x10>;\xe7\xbaa;1\xbb\\\x9c6!M\xc9\xf1JB\xfdz/\xdb\x84\x85k\xca\\D\xc2‘
2、对称加密算法(AES、DES)
安装第三方库:
pip install pycryptodomex -i https://pypi.douban.com/simple
DES算法为密码体制中的对称密码体制,又被称为美国数据加密标准。 DES是一个分组加密算法,典型的DES以64位为分组对数据加密,加密和解密用的是同一个算法。 DES算法的入口参数有三个:Key1。其中Key为8个字节共64位,是DES算法的工作密钥;Data为8个字节64位的整数倍,是要被加密或被解密的数据** 密钥长64位,密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位,使得每个密钥都有奇数个1),对64位二进制数据块进行加密,分组后的明文组和56位的密钥按位替代或交换的方法形成密文组。每次加密对64位的输入数据进行16轮编码,经过一系列替换和移位后转换成完全不同的64位输出数据。
from Cryptodome.Cipher import DES key = b‘88888888‘ data = "Good Good Study! Day Day Up!" count = 8 - (len(data) % 8) plaintext = data + count * "=" des = DES.new(key, DES.MODE_ECB) ciphertext = des.encrypt(plaintext.encode()) print(ciphertext) # b‘D\xa4Z\x1dt\xba\xf3\xe8\xdbv\x1aP\x81\xe4\xe6Jx?\xfe\xf2\x0b\x82\nG\x08d\xea\xd0\t\x07vs‘ plaintext = des.decrypt(ciphertext) plaintext = plaintext[:(len(plaintext)-count)] print(plaintext) # b‘Good Good Study! Day Day Up!‘
3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次DES加密算法。 由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解。3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。 3DES(即Triple DES)是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准),加密算法,其具体实现如下:设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,M代表明文,C代表密文,这样: 3DES加密过程为:C=Ek3(Dk2(Ek1(M))) 3DES解密过程为:M=Dk1(EK2(Dk3(C)))。
AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同。
from Cryptodome.Cipher import DES, AES from Cryptodome import Random # 密钥的长度为16字节、24字节或32字节 key = b"8888888888888888" print(AES.block_size) # 16 iv = Random.new().read(AES.block_size) # 也可以为24、32 plaintext = "测试数据" # 该数据长度不受限制 aes = AES.new(key, AES.MODE_EAX, iv) ciphertext = aes.encrypt(plaintext.encode()) # 一般后端会将iv放在加密的数据前一起传递到前端 transform_data = iv + ciphertext print(transform_data) # b‘\x9e\xabF\xddx\xfa\x9f\xb7\x91\xa0\xafp\xee\xe9w\x8e\x11\x08\x12\xae\x0b\xc0\xc1\xbe\x80\xb2\xff\x0c‘ iv = transform_data[:16] aes = AES.new(key, AES.MODE_EAX, iv) plaintext = aes.decrypt(transform_data[16:]) print(plaintext) # b‘\xe6\xb5\x8b\xe8\xaf\x95\xe6\x95\xb0\xe6\x8d\xae‘ print(plaintext.decode()) # 测试数据
3、非对称加密算法(RSA、DSA)
安装第三方库:
pip install rsa -i https://pypi.douban.com/simple
指的是加密和解密使用不同的秘钥。 一把作为公开的公钥,另一把作为私钥。这对密钥中的公钥进行加密,私钥用于解密。反之亦然(被私钥加密的数据也可以被公钥解密) 。 在实际使用中私钥一般保存在发布者手中,是私有的不对外公开的,只将公钥对外公布,就能实现只有私钥的持有者才能将数据解密的方法。 这种加密方式安全系数很高,因为它不用将解密的密钥进行传递,从而没有密钥在传递过程中被截获的风险,而破解密文几乎又是不可能的。 但是算法的效率低,所以常用于很重要数据的加密,常和对称配合使用,使用非对称加密的密钥去加密对称加密的密钥。 事实上,**公钥加密算法很少用于数据加密,它通常只是用来做身份认证**,因为它的密钥太长,加密速度太慢--公钥加密算法的速度甚至比对称加密算法的速度慢上3个数量级(1000倍)。
import rsa # 公钥加密、私钥解密 public_key, private_key = rsa.newkeys(1024) print(public_key) # PublicKey(115358647593237027749555219330290547595292720354379729059572469455025379115527291514465303947468690370446593609121177089794716265226101498361786298396410892325533861129676356325971818358112602498513419680609056457389715318966834362898086552554130435425753061655286667511557573410756120684188042377774434444807, 65537) print(private_key) # PrivateKey(115358647593237027749555219330290547595292720354379729059572469455025379115527291514465303947468690370446593609121177089794716265226101498361786298396410892325533861129676356325971818358112602498513419680609056457389715318966834362898086552554130435425753061655286667511557573410756120684188042377774434444807, 65537, 111285529956928522901721617280604228002764723117703733926382810265271061290888840676549733913221737511493431004615227720952917381576663793443813612330045581626681883557204892676718975967265771623672679503776812616315334112382868415864141371197836942710738341439472967902074841400226409659228441303650822610777, # 38470842708546405208704625508367712891471208299333441783981501073550023095274000403563916879641908231011170773153102126825952183163444780110955065002626432268349573, 2998599444966402616240989100234166167805477168671480027322013770416359562366030923233399853472241710845190991402502764232214027989568380839340059) plaintext = b"15863274538" ciphertext = rsa.encrypt(plaintext, public_key) print(ciphertext) # b‘\x04\xb3ri\x1e\nA\xfb\x94\xff\xde{HtNw\xd4Q{\xdeRJ\xe0Fwl\x97kL\xde\xe6m\xc1\x8f\xd4\t\x96=\xb62\xad\x02\xfe\xeb4\xb4i\x8f\x9e\x0fp\x10\xbe\x8fiNrrUB\xbc\xe3\x87Q-\xe2\xa5\x86\xd9\x0b6,.\x90\xa1\xa6\x80\xf3\xaa\xcc\xdf7!\xdcp\xea\x0eE_?$\x8b\xcd\xb2\xca\x18\xf9e\xb5\x9b^\x84CcU\xe5.\xaeeFlz\xdeh\xb8\xa3D\xcb\xb6\xd5\x02\xe38\x98\xc80#Q‘ plaintext = rsa.decrypt(ciphertext, private_key) print(plaintext) # b‘15863274538‘ # 私钥加签、公钥验签 plaintext = b"15863274538" sign_message = rsa.sign(plaintext, private_key, "MD5") plaintext = b"15863274538" method = rsa.verify(b"15863274532", sign_message, public_key) print(method) # rsa.pkcs1.VerificationError: Verification failed
4、补充算法(base64)
目前Base64已经成为网络上常见的传输8Bit字节代码的编码方式之一。在做支付系统时,系统之间的报文交互都需要使用Base64对明文进行转码,然后再进行签名或加密,之后再进行(或再次Base64)传输。那么,Base64到底起到什么作用呢? 在参数传输的过程中经常遇到的一种情况:使用全英文的没问题,但一旦涉及到中文就会出现乱码情况。与此类似,网络上传输的字符并不全是可打印的字符,比如二进制文件、图片等。Base64的出现就是为了解决此问题,它是基于64个可打印的字符来表示二进制的数据的一种方法。 电子邮件刚问世的时候,只能传输英文,但后来随着用户的增加,中文、日文等文字的用户也有需求,但这些字符并不能被服务器或网关有效处理,因此Base64就登场了。随之,Base64在URL、Cookie、网页传输少量二进制文件中也有相应的使用。 原文链接:https://blog.csdn.net/wo541075754/article/details/81734770
from base64 import b64encode, b64decode plaintext = "我的银行卡密码是020012" ciphertext = b64encode(plaintext.encode()) print(ciphertext) # b‘5oiR55qE6ZO26KGM5Y2h5a+G56CB5pivMDIwMDEy‘ plaintext = b64decode(ciphertext) print(plaintext) # b‘\xe6\x88\x91\xe7\x9a\x84\xe9\x93\xb6\xe8\xa1\x8c\xe5\x8d\xa1\xe5\xaf\x86\xe7\xa0\x81\xe6\x98\xaf020012‘ print(plaintext.decode()) # 我的银行卡密码是020012