开局一张图,内容全靠搜哈哈哈。
有些复杂的原理性的东西,实在是无法用文字表述,写一堆可能读者也看不懂,所以推荐初学者还是老实着看视频咯。接下来就是记录一些常见的python的加解密方法。
环境安装
pip install pycryptodemo
pip install pyDES
(避坑:vscode配置python环境的时候出错,请在powershell输入set-executionpolicy remotesigned,然后y)
用Python实现DES加解密(ECB)
16进制模式
from Crypto.Cipher import DES
import binascii
key = b'abcdefgh'#这是密钥
des = DES.new(key,DES.MODE_ECB)#实例化一个DES对象,输入参数是密钥和加密模式ECB
text = 'www.52ying.top'#待加密的密文,需要是8字节的倍数
text = text + (8 - (len(text)%8))*'='#进行八字节用等于号填充
print("填充后的数据:",text)#输出一下填充好后的数据
encrypto_text = des.encrypt(text.encode())#将数据进行默认的utf_8编码格式编码字符串然后进行DES加密
encryptResult = binascii.b2a_hex(encrypto_text)#将加密后的结果转化为16进制的字符串
print("加密后的结果转化为16进制的字符串:",encryptResult)
encrypto_text = binascii.a2b_hex(encryptResult)#将十六进制字符串解码回原来的加密结果
decryptResult = des.decrypt(encrypto_text)#DES解密
print("解密结果:",decryptResult)
base64模式
from Crypto.Cipher import DES
import base64
key = b'12345678'
text = 'www.52ying.top'
des = DES.new(key,DES.MODE_ECB)
text = text + (8-(len(text)%8))*'='
print("填充后:",text)
enCryptotext = des.encrypt(text.encode())
print("加密后的结果:",enCryptotext)
CryptResult = base64.standard_b64encode(enCryptotext)
print("加密结果编码后:",CryptResult)
deCryptotext = des.decrypt(base64.standard_b64decode(CryptResult))#解码并解密
print("解密后:",deCryptotext)
用Python实现3DES加解密
3DES和DES的区别就是密钥是24字节
from Crypto.Cipher import DES3
import base64
key = b'123456789012345678901234'
des3 = DES3.new(key,DES3.MODE_ECB)
def enCrypto(data):
data = data + (8-(len(data)%8))*'='
print("填充后:",data)
enCryptotext = des3.encrypt(data.encode())
enResult = base64.standard_b64encode(enCryptotext)
print("加密编码后:",enResult)
return enResult
def deCrypto(data):
deCryptotext = des3.decrypt(base64.standard_b64decode(data))
print("解码解密后:",deCryptotext)
if __name__ == '__main__':
print("请输入密文:")
data = input()
deCrypto(enCrypto(data))
DES算法填充方式
DES算法是分组算法,每个分组都是64位。如果数据位数不足64位的倍数,则需要填充,补充到64位的倍数,填充的方式有如下的方法:
NoPadding:这种加密由加密双方约定填充内容,比如填充\0或者空格,最后去掉即可
PKCS7Padding:假设数据长度需要填充n(n>0)个字节才对齐,那么填充n个字节,每个字节都是n;如果数据本身就已经对齐了,则填充一块长度为块大小的数据,每个字节都是块大小。
PKCS5Padding:数据字节长度对8取余,余数为m,若m>0,则补足8-m个字节,字节数值为8-m,即差几个字节就补几个字节,字节数值即为补充的字节数,若为0则补充8个字节的8 。在解密时,最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文。它是PKCS7Padding的子集
ISO 10126:前面随机填充,最后一个字节填充总共补充的字节数。
Zero padding:不足8位补 0,有可能会出问题,因为不知道数据本身会不会以一个或多个 0 字节结尾。
ANSIX923: 在填充时首先获取需要填充的字节长度 = (块长度 – (数据长度 % 块长度)), 在填充字节序列中最后一个字节填充为需要填充的字节长度值, 填充字节中其余字节均填充数字零.
用Python实现DES加解密(CBC)
from Crypto.Cipher import DES
import base64
class DESUtil:
__BLOCK_SIZE_8 = __BLOCK_SIZE_8 = DES.block_size#分块大小
__IV = b'1'*8#偏移量,这里使用的是8字节的全由1组成
@staticmethod #返回函数的静态方法,使用时不需要进行实例化
def encrypt(str,key):
cipher = DES.new(key,DES.MODE_CBC,DESUtil.__IV)
x = DESUtil.__BLOCK_SIZE_8 - (len(str)%DESUtil.__BLOCK_SIZE_8)
#判断输入的数据是否满足8字节
if x != 0:
str = str + chr(x)*x
print("填充后:",str)
msg = base64.standard_b64encode(cipher.encrypt(str.encode()))
return msg
@staticmethod
def decrypt(enstr,Key):
cipher = DES.new(key,DES.MODE_CBC,DESUtil.__IV)
decryptByts = base64.standard_b64decode(enstr)
msg = cipher.decrypt(decryptByts)
paddingLen = msg[len(msg)-1]
return msg[0:-paddingLen]
if __name__ == "__main__":
key = b"12345678"
result = DESUtil.encrypt("www.52ying.top", key)
print ("加密并编码:",result)
print ("解密并解码:",DESUtil.decrypt(result, key))
前面的代码中主要使用“Crypto”模块,接下来使用“pyDes”模块实现DES加密,工作模式是CBC,填充方式是PAD_PKCS5,代码如下:
import base64
from pyDes import *
Des_key = '12345678'#Key的长度为8字节
Des_IV = b'12345678'#自定义IV向量
def Encrption(str):
k = des(Des_key,CBC,Des_IV,padmode=PAD_PKCS5)
return base64.b64encode(k.encrypt(str))
def Decode(str):
k = des(Des_key,CBC,Des_IV,padmode=PAD_PKCS5)
return k.decrypt(base64.standard_b64decode(str))
if __name__ == "__main__":
d = Encrption("www.52ying.top")
print("加密:",d)
print("解密:",Decode(d))
例题
下载图片,发现图片中有两串由01组成的字符串。长度分别是511bit和63bit,对于DES算法来说,少1bit,考虑在前面填充0,然后进行ASCII转换得到的数据如下(http://www.txttool.com/wenben\_binarystr.asp):
0101001101111001011000110110110000110000011101100011001101110010(Sycl0v3r)
01001101001100100101100101111000010011100111101001001001001100000100111101000100010010100110111101001110010101110111010001101111010011100100010001011001011110100110000101010111010110100110110101001101001100100110011101111000010110100110101001011010011011100101101001101101010110010011010001001101010001110110001100110100010011110101010001001101001101010100111101000100010000010111100001001111010101110111010001110010010011100100010001001001011110010110000101000100010101100110110101001111010001000110011100110000(M2YxNzI0ODJoNWtoNDYzaWZmM2gxZjZnZmY4MGc4OTM5ODAxOWtrNDIyaDVmODg0)
第二结果中符合base64的编码特性,编码得到:3f172482h5kh463iff3h1f6gff80g89398019kk422h5f884,根据题目中提示进行凯撒解码,密码是21,得到3a172482c5fc463daa3c1a6baa80b89398019ff422c5a884。
最后一步使用密钥Sycl0v3r解密3a172482c5fc463daa3c1a6baa80b89398019ff422c5a884得到:You_Got_It@_@