记录一下AES算法在Python中的使用,AES的原理
本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理
本文章来自腾讯云 作者:Python进阶者
想要学习Python?有问题得不到第一时间解决?来看看这里“1039649593”满足你的需求,资料都已经上传至文件中,可以自行下载!还有海量最新2020python学习资料。
点击查看

# hashlib是涉及安全散列和消息摘要,提供多个不同的加密算法接口,如SHA1、SHA224、SHA256、SHA384、SHA512、MD5等。 import hashlib md5 = hashlib.md5() md5.update("test".encode('utf-8')) print(u"digest返回的摘要:%s"% md5.digest()) print(u"hexdigest返回的摘要:%s"% md5.hexdigest())
AES:密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。
AES分为几种模式,比如ECB,CBC,CFB、PGP、OFB、CTR等等这个我们可以点击源码即可看到。
#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`. MODE_ECB = 1 #: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`. MODE_CBC = 2 #: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`. MODE_CFB = 3 #: This mode should not be used. MODE_PGP = 4 #: Output FeedBack (OFB). See `blockalgo.MODE_OFB`. MODE_OFB = 5 #: CounTer Mode (CTR). See `blockalgo.MODE_CTR`. MODE_CTR = 6 #: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. MODE_OPENPGP = 7
对于流加密,需要将分组密码转化为流模式工作。对于块加密(或称分组加密),如果要加密超过块大小的数据,就需要涉及填充和链加密模式。
ECB(Electronic Code Book电子密码本)模式
ECB模式是最早采用和最简单的模式,它将加密的数据分成若干组,每组的大小跟加密密钥长度相同,然后每组都用相同的密钥进行加密。
优点:
1.简单;
2.有利于并行计算;
3.误差不会被传送;
缺点:
1.不能隐藏明文的模式;
2.可能对明文进行主动攻击; 因此,此模式适于加密小消息。
CBC(Cipher Block Chaining,加密块链)模式
优点:
1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。
缺点:
1.不利于并行计算;
2.误差传递;
3.需要初始化向量IV
CFB(Cipher FeedBack Mode,加密反馈)模式
优点:
1.隐藏了明文模式;
2.分组密码转化为流模式;
3.可以及时加密传送小于分组的数据;
缺点:
1.不利于并行计算;
2.误差传送:一个明文单元损坏影响多个单元;
3.唯一的IV;
OFB(Output FeedBack,输出反馈)模式
优点:
1.隐藏了明文模式;
2.分组密码转化为流模式;
3.可以及时加密传送小于分组的数据;
缺点:
1.不利于并行计算;
2.对明文的主动攻击是可能的;
3.误差传送:一个明文单元损坏影响多个单元 [4] 。
python代码
# -*- coding:utf-8 -*- import base64 from Crypto.Cipher import AES class EncryptDate: def __init__(self, key): self.key = key # 初始化密钥 self.length = AES.block_size # 初始化数据块大小 self.aes = AES.new(self.key, AES.MODE_ECB) # 初始化AES,ECB模式的实例 # 截断函数,去除填充的字符 self.unpad = lambda date: date[0:-ord(date[-1])] def pad(self, text): """ #填充函数,使被加密数据的字节码长度是block_size的整数倍 """ count = len(text.encode('utf-8')) add = self.length - (count % self.length) entext = text + (chr(add) * add) return entext def encrypt(self, encrData): # 加密函数 res = self.aes.encrypt(self.pad(encrData).encode("utf8")) msg = str(base64.b64encode(res), encoding="utf8") return msg def decrypt(self, decrData): # 解密函数 res = base64.decodebytes(decrData.encode("utf8")) msg = self.aes.decrypt(res).decode("utf8") return self.unpad(msg) def sm3(text): if text is None or len(text) < 5: return '' return Encode.SM3_add_len(text).upper() def md5(text): if text is None or len(text) < 5: return '' a = hashlib.md5() # 计算md5值 a.update(text.encode(encoding='utf-8')) # 返回摘要,作为十六进制数据字符串值 return a.hexdigest().upper()

def SM3_add_len(src): msg=str(src) msg=str(len(msg))+msg return Encode.SM3(msg)
测试
test_key = "1234567890ABCEDF1234567890ABCEDF" test_txt = "123456" eg2 = EncryptDate(test_key) # 这里密钥的长度必须是16的倍数 en2 = eg2.encrypt(test_txt) # 对123456进行加密,判断是否加密后等于swqp5cQ56HME/pL99VuHkA== print("加密:", en2) print("解密:", eg2.decrypt(en2)) assert en2 == 'swqp5cQ56HME/pL99VuHkA==' # 判断是否加密后等于swqp5cQ56HME/pL99VuHkA== assert eg2.decrypt(en2) == test_txt # 对加密后的密文解密,判断是否等于123456 test_bank_card = '6222222222222222222' print(sm3(test_bank_card)) # 判断6222222222222222222 经过ECB/PKCS5Padding加密后是否等于5A7E1B360D38CBFDFF078A197283C772C40A4903C1C2D9A082977F209508AFC1 assert sm3(test_bank_card) == '5A7E1B360D38CBFDFF078A197283C772C40A4903C1C2D9A082977F209508AFC1' # 判断110000201912010000 经过md5加密后是否等于E8C8E29576C886A87A80C39B405F0A19 id_no = '110000201912010000' print(md5(id_no)) assert md5(id_no) == 'E8C8E29576C886A87A80C39B405F0A19' ph_no = '13800000000' print(md5(ph_no)) assert md5(ph_no) == '5DAAD257487F1B493114181A22E37EB5'
可以看到我这里测试用了断言(assert),这个我上一篇文章刚讲过,主要是判断如果它的条件返回错误,则终止程序执行。

浙公网安备 33010602011771号