带你手撕 AES算法在Python中的使用

记录一下AES加解密在python中的使用
研究AES之前先了解下常用的md5加密,既。然谈到md5,就必须要知道python3中digest()和hexdigest()区别。

  • hash.digest()
    返回摘要,作为二进制数据字符串值

  • hash.hexdigest()
    返回摘要,作为十六进制数据字符串值

# 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]

先说一下我踩得坑,我的版本是python3.7.9,之所以在引入的时候加了个备注# pycryptodome,是因为使用过程中我发现有的python环境需要装pycryptodome这个包,但引用AES的时候又用的是Crypto.Cipher,这里记录下这个坑。

from Crypto.Cipher import AES  # pycryptodome

PADDING

AES块加密说过,PADDING是用来填充最后一块使得变成一整块,所以对于加密解密两端需要使用同一的PADDING模式,大部分PADDING模式为PKCS5, PKCS7, NOPADDING。

pkcs5padding和pkcs7padding的区别

pkcs5paddingpkcs7padding都是用来填充数据的一种模式。在ECB中,数据是分块加密的。如果需要加密的数据的字节码的长度不是块大小的整数倍就需要填充。
使用PKCS5,填充时:
要填充7个字节,那么填入的值就是0×7;
如果只填充1个字节,那么填入的值就是0×1;
恰好8个字节时还要补8个字节的0×08
正是这种即使恰好是8个字节也需要再补充字节的规定,可以让解密的数据很确定无误的移除多余的字节。

PKCS7和PKCS5的区别是数据块的大小;

  • PKCS5填充块的大小为8bytes(64位)
  • PKCS7填充块的大小可以在1-255bytes之间。

因为AES并没有64位的块, 如果采用PKCS5, 那么实质上就是采用PKCS7

python实现
安装所需要的包

pip install pycryptodome

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()

密文示例:

密钥为 1234567890ABCEDF1234567890ABCEDF

  • 明文为 123456,加密后密文为:swqp5cQ56HME/pL99VuHkA==
  • 密文为:swqp5cQ56HME/pL99VuHkA==,解密后明文为 123456

可以看到代码中用到了SM3_add_len()
这里提供下SM3_add_len()的源码,其实就是用字符本身的长度拼接字符本身

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),这个我上一篇文章刚讲过,主要是判断如果它的条件返回错误,则终止程序执行。

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