Python脚本之MD5加密、AES加解密ECB、异或加解密

本文为博主原创,未经许可严禁转载。
本文链接:https://blog.csdn.net/zyooooxie/article/details/117022776

最近手上有些需求用到了加密、解密,爬了很多坑,做个总结。

个人博客:https://blog.csdn.net/zyooooxie

简单介绍

MD5,message-digest algorithm 5(信息-摘要算法),不可逆;在字符串加密、请求报文 加密、数据库字段值 加密中经常用到;(实际校验过程: 收到请求后,服务端重新计算、比对, 如果相同-通过,不同-失败)

AES,高级加密标准(英语:Advanced Encryption Standard);AES加密的模式分 ECB, CBC, CTR, CFB, OFB;AES只有一个密钥,这个密钥既用来加密,也用于解密。【对称加密】

异或:加密是 明文与密钥 进行异或运算,得到 密文;解密是 密文与密钥 再次进行异或运算,还原成 明文。【一次加密,两次解密】

MD5加密-hashlib

需求

某接口参数:

参数名	必选	类型	说明

zySum	是		String	MD5加密签名:id=value0&zy=value1&csdn=value2+qq153132336(最后的+不算)

代码

import hashlib
import datetime

def md5_func(test_str: str, key=None):
    print('MD5加密前为 :' + test_str)

    if key is None:
        m = hashlib.md5()
    else:
        m = hashlib.md5(key.encode('utf-8'))

    m.update(test_str.encode())
    res = m.hexdigest()
    print('MD5加密后为 :' + res)

    return res


def cs():
    # id=value0&zy=value1&csdn=value2+qq153132336
    v0 = 'zyooooxie'
    v1 = 'csdn'
    v2 = 'test'
    test_str = '&'.join(['id=' + v0, 'zy=' + v1, 'csdn=' + v2])
    test_str += 'qq153132336'

    md5_func(test_str)

AES加、解密-pycryptodome

我是直接下载、使用的pycryptodome;【Windows10】

安装过程的坑

1、pip install pycryptodome

在cmd执行时,报错:Microsoft Visual C++ 14.0 is required;

必须得去 下载安装包。

苦逼的是:安装包大小是3.7G,光下载就花了2个多小时。

2、安装 Visual Studio 2015

安装-安装结束(重启)-设置环境变量

安装 又是一个多小时。

3、再次 pip

打开安装文件夹-cmd-设置编码-set CL值-再执行pip。

这一步又花了我 一个多小时!

代码

AES/ECB/PKCS5Padding

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.Padding import unpad
import base64


def encrypt_func(encrypt_str: str, key: str = 'testTESTtestTEST') -> str:
    BS = 16
    # data_str进行 PKCS5Padding 的填充
    new = pad(encrypt_str.encode("utf-8"), BS)

    # 初始化加密器
    aes = AES.new(key.encode("utf-8"), AES.MODE_ECB)

    # 进行aes加密
    encrypt_aes = aes.encrypt(new)

    # 用base64转成字符串形式
    encrypted_text = base64.b64encode(encrypt_aes).decode()
    Log.info(encrypted_text)

    return encrypted_text



def decrypt_func(decrypt_str: str, key: str = 'testTESTtestTEST') -> str:
    BS = 16

    # 初始化加密器
    aes = AES.new(key.encode("utf-8"), AES.MODE_ECB)

    # 用base64转成bytes
    base64_decrypted = base64.decodebytes(decrypt_str.encode(encoding='utf-8'))

    # 执行解密
    decrypted_text = aes.decrypt(base64_decrypted)

    # 去填充
    new_decrypted_text = unpad(decrypted_text, BS)

    # 转str
    new_decrypted_str = new_decrypted_text.decode()
    Log.info(new_decrypted_str)

    return new_decrypted_str

^ 异或

需求

(其实,这一部分主要是 我自己发散思维想到的一些)

某接口参数 zy2 的加密方式是:

1,【第一版】某数字与8888异或后,再做AES解密(key=‘testTESTtestTEST’);
2,【第二版】某数字与8888异或后,将其结果(int) 转为字符数组;把数组的每个元素 与 7 再做异或,组合成为str;

这个版本 我觉得有问题:0-9 每个数字 和 7做异或,

def test():
    print('数字 0-9 和 7 进行异或')
    for a in range(10):
        print('数字:{}'.format(a), '异或结果:{}'.format(a ^ 7))

得到的实际结果是:

数字 0-9 和 7 进行异或
数字:0 异或结果:7
数字:1 异或结果:6
数字:2 异或结果:5
数字:3 异或结果:4
数字:4 异或结果:3
数字:5 异或结果:2
数字:6 异或结果:1
数字:7 异或结果:0
数字:8 异或结果:15
数字:9 异或结果:14

那 按第二版 执行到最后的结果 假设为 121415451(str),解密反推时,怎么判断14、15是一个数字异或的结果(9、8),还是2个数字异或的结果(6和3、6和2)?

我没想通。

实际因为赶项目,这个加密被取消了。那我自己发散思维了!

3,【发散思维】某数字与8888异或后,将其结果 转为字符数组;把数组的每个元素 与 7 再做异或【元素为8时,结果为Z;元素为9时,结果为Y】,组合成为str;

4,【最终版】某数字与8888异或后,将其结果 转为字符数组;把数组的每个元素 与 7 再做异或【元素为8时,结果为 大写的26个英文字母的随机一个;元素为9时,结果为 小写的26个英文字母的随机一个】,组合成为str;

代码


def new_encrypt(test_int: int):
    # test_list = [str(int(t) ^ 7) for t in str(test_int)]

    test_list = list()
    # 优化加密
    for ti in str(test_int):
        if int(ti) == 9:        # res 为 14
            # res = 'Z'
            res = random.choice(ascii_lowercase)
        elif int(ti) == 8:      # res 为 15
            # res = 'Y'
            res = random.choice(ascii_uppercase)
        else:
            res = int(ti) ^ 7

        test_list.append(res if isinstance(res, str) else str(res))

    print(test_list)
    res = ''.join(test_list)
    print(res)
    return res


def new_decrypt(test_str: str):
    # abc_list = [str(int(i) ^ 7) for i in test_str]

    abc_list = list()
    for ts in test_str:
        if ts in ascii_lowercase:
            res = 9
        elif ts in ascii_uppercase:
            res = 8
        else:
            res = int(ts) ^ 7

        abc_list.append(str(res))

    print(abc_list)
    res = int(''.join([*abc_list]))
    print(res)
    return res

随便使用某个数字 来验证下:


    a = new_encrypt(83640969731621451856880722)
    new_decrypt(a)
    

每次加密的结果 近乎100% 不同:

['Y', '4', '1', '3', '7', 'g', '1', 'l', '0', '4', '6', '1', '5', '6', '3', '2', '6', 'A', '2', '1', 'G', 'Z', '7', '0', '5', '5']
Y4137g1l046156326A21GZ7055
['8', '3', '6', '4', '0', '9', '6', '9', '7', '3', '1', '6', '2', '1', '4', '5', '1', '8', '5', '6', '8', '8', '0', '7', '2', '2']
83640969731621451856880722



['T', '4', '1', '3', '7', 'f', '1', 'l', '0', '4', '6', '1', '5', '6', '3', '2', '6', 'N', '2', '1', 'J', 'V', '7', '0', '5', '5']
T4137f1l046156326N21JV7055
['8', '3', '6', '4', '0', '9', '6', '9', '7', '3', '1', '6', '2', '1', '4', '5', '1', '8', '5', '6', '8', '8', '0', '7', '2', '2']
83640969731621451856880722

继续发散下思维

假设 某接口参数zy3 的值 就是1、2、3、5这4个固定元素 随机重复N次;
假设每个元素 重复出现3次,明文是123553212351,想要加密,咋简单实现呢?

按上面异或的思路(8、9对应大、小写英文字母的随机取值),1、2、3、5 对应某种方式计算后的随机值;

计算方式为取模

若key为7,

那1可以是10*7+1,可以是9*7+1,可以是11*7+1;
那2可以是200*7+2,可以是201*7+2,可以是199*7+2;
那3可以是3001*7+3,可以是3000*7+3,可以是2999*7+3;
那5可以是40000*7+5,可以是40001*7+5,可以是39999*7+5;

实际得出的结果就是:

		1-71|64|78
		2-1402|1409|1395
		3-21010|21003|20996
		4-280005|280012|279998

123553212351对应的结果可以是:71、1402、21010、280005、280012、21003、1409、64、1395、20996、279998、78;

【再复杂】对 三个转换后的值 做个随机取数 ;【再复杂plus】计算1、2、3、5的三个值时,取值更随机;

计算方式为直角坐标系的四个象限

若1为第二象限,第二象限角:2nπ+π/2<α< 2nπ+π;
若2为第三象限,第三象限角:2nπ+π<α<2nπ+3π/2;
若3为第一象限,第一象限角:2nπ<α<2nπ+π/2;
若5为第四象限,第四象限角:2nπ+3π/2<α<2nπ+2π;

举例,取n=6(key),故

第二象限角的取值范围是12.5π弧度 - 13π弧度,那1的值 就随机取(2250,2340),比如 2289|2300|2301;
第三象限角的取值范围是13π弧度 - 13.5π弧度,那2的值 就随机取(2340,2430),比如 2341|2342|2400;
第一象限角的取值范围是12π弧度 - 12.5π弧度,那3的值 就随机取(2160,2250),比如 2200|2201|2240;
第四象限角的取值范围是13.5π弧度 - 14π弧度,那5的值 就随机取(2430,2520),比如 2510|2511|2519;

123553212351对应的结果可以是:2289、2341、2200、2510、2511、2201、2342、2300、2400、2240、2519、2301;

【再复杂】对 三个转换后的值 做个随机取数 ;【再复杂plus】取1、2、3、5的三个值时,取得更随机;

这一部分的代码就不提供了。

本文链接:https://blog.csdn.net/zyooooxie/article/details/117022776

交流技术 欢迎+QQ 153132336 zy
个人博客 https://blog.csdn.net/zyooooxie

おすすめ

転載: blog.csdn.net/zyooooxie/article/details/117022776
おすすめ