zoukankan      html  css  js  c++  java
  • python常用加密AES/DES/RSA/MD5/SM2/SM4/3DES

    都是作者累积的,且看其珍惜,大家可以尽量可以保存一下,如果转载请写好出处https://www.cnblogs.com/pythonywy

    一.md5加密

    1.简介

    这是一种使用非常广泛的加密方式,不可逆的,常见16位和32位一般都是md5

    import hashlib
    
    data = '你好'
    print(hashlib.md5(data.encode(encoding="UTF-8")).hexdigest())  #32位
    print(hashlib.md5(data.encode(encoding="UTF-8")).hexdigest()[8:-8])  #16位
    

    二.RSA加密

    1.简介

    非对称加密算法,也就是比较常见的公钥私钥加密,可逆的

    2.指数和模加密无填充-模板一

    import rsa
    #模
    m = "ae068c2039bd2d82a529883f273cf20a48e0b6faa564e740402375a9cb332a029b8492ae342893d9c9d53d94d3ab8ae95de9607c2e03dd46cebe211532810b73cc764995ee61ef435437bcddb3f4a52fca66246dbdf2566dd85fbc4930c548e7033c2bcc825b038e8dd4b3553690e0c438bbd5ade6f5a476b1cbc1612f5d501f"
    #指数
    e = '10001'
    #加密参数
    message = '123456'
    
    class Encrypt(object):
        def __init__(self, e, m):
            self.e = e
            self.m = m
    
        def encrypt(self, message):
            mm = int(self.m, 16)
            ee = int(self.e, 16)
            rsa_pubkey = rsa.PublicKey(mm, ee)
            crypto = self._encrypt(message.encode(), rsa_pubkey)
            return crypto.hex()
    
        def _pad_for_encryption(self, message, target_length):
            message = message[::-1]
            max_msglength = target_length - 11
            msglength = len(message)
    
            padding = b''
            padding_length = target_length - msglength - 3
    
            for i in range(padding_length):
                padding += b'x00'
    
            return b''.join([b'x00x00', padding, b'x00', message])
    
        def _encrypt(self, message, pub_key):
            keylength = rsa.common.byte_size(pub_key.n)
            padded = self._pad_for_encryption(message, keylength)
    
            payload = rsa.transform.bytes2int(padded)
            encrypted = rsa.core.encrypt_int(payload, pub_key.e, pub_key.n)
            block = rsa.transform.int2bytes(encrypted, keylength)
    
            return block
    
    if __name__ == '__main__':
        en = Encrypt(e, m)
        print(en.encrypt(message))
    

    3.指数和模加密无填充-模板二

    import codecs
    
    def rsa_encrypt(content):
        public_exponent = '010001'
        public_modulus = 'ae068c2039bd2d82a529883f273cf20a48e0b6faa564e740402375a9cb332a029b8492ae342893d9c9d53d94d3ab8ae95de9607c2e03dd46cebe211532810b73cc764995ee61ef435437bcddb3f4a52fca66246dbdf2566dd85fbc4930c548e7033c2bcc825b038e8dd4b3553690e0c438bbd5ade6f5a476b1cbc1612f5d501f'
    
        content = content[::-1]
        rsa = int(codecs.encode(content.encode('utf-8'), 'hex_codec'),
                  16) ** int(public_exponent, 16) % int(public_modulus, 16)
        # 把10进制数rsa转为16进制('x'表示16进制),再取前256位,不够的在最前面补0
        return format(rsa, 'x').zfill(256)
    

    4.指数和模加密无填充-模板三

    import math
    if __name__ == '__main__':
        # 实为16进制串,前补0
        e = ''
        # m也需要补00
        m = '008eb933413be3234dddd2730fbb1d05c8848a43d5dc3bdd997f2a9935fba6beb9ffb36854482b0b46cf7e6f9afbbe2e2e7d606fde20bec57dbf722e7985192e8813e6b67628a6f202cf655b7d2ffce4e9dc682dd6034ae706c8e255f25e4051b9ca43f25b3ad686aac9c8f6aeb71d921c13a255c806f78a5a7b9a356c2dd274e3'
        m = int.from_bytes(bytearray.fromhex(m), byteorder='big')
        e = int.from_bytes(bytearray.fromhex(e), byteorder='big')
        # js加密为反向,为保持一致原文应反向处理,所以这里原文实际为204dowls
        plaintext = 'slwod402'.encode('utf-8')
        # 无填充加密逻辑
        input_nr = int.from_bytes(plaintext, byteorder='big')
        crypted_nr = pow(input_nr, e, m)
        keylength = math.ceil(m.bit_length() / 8)
        crypted_data = crypted_nr.to_bytes(keylength, byteorder='big')
        print(crypted_data.hex())
    

    5.指数和模加密有填充

    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives.asymmetric import rsa
    from cryptography.hazmat.primitives.asymmetric import padding
    import base64
    import binascii
    
    """
    另种rsa加密
    """
    
    
    def data_encrypt(text):
        """
            RSA 加密
        :param text:    加密前内容
        :return:        加密后内容
        """
        # 判断系统,加载指定模块
        public_exponent = int("010001",16)  #指数
        print(public_exponent)
        public_modulus=int('B23322F080BD5876C0735D585D25C7BC409F637237B07744D27FBF39FB100ABE59DF380EA6BFCDF28C286E7A0CD95BE87F6099F8F39B0E97D9782C3D33FCFB80D43D2F22A9D9417ECFD1A0B8421DEE1CD4B323E8078336E77419A97F94E60A90CA06551202F63819FC8E73425F06ECA4C05BBF8CA32366240A6C36CA61D85019',16) #模
        # content = 'leadeon' + text + time.strftime("%Y%m%d%H%M%S", time.localtime())
        content = text
        max_length = 117
        # public_key = serialization.load_pem_public_key(key, backend=default_backend())
        public_key = rsa.RSAPublicNumbers(public_exponent, public_modulus).public_key(default_backend())
        data = b''
        for i in range(0, len(content), max_length):
            data += public_key.encrypt(content[i: i + max_length].encode(),
                                       padding.PKCS1v15())
        data = base64.b64encode(data).decode()
        #data =binascii.b2a_hex(data).decode()  hex输出
        return data
    

    6.公钥加密

    # 公钥加密
    import base64
    import rsa
    from Crypto.PublicKey import RSA
    
    def encryptPassword(data, publicKeyStr):
        '''
        data:内容
        publicKeyStr:不需要-----BEGIN PUBLIC KEY-----开头,-----END PUBLIC KEY-----结尾的格式,只要中间部分即可
        key_encoded:不需要-----BEGIN PUBLIC KEY-----开头,-----END PUBLIC KEY-----结尾的格式
        '''
        key_encoded='''-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdZGziIrJOlRomzh7M9qzo4ibw
    QmwORcVDI0dsfUICLUVRdUN+MJ8ELd55NKsfYy4dZodWX7AmdN02zm1Gk5V5i2Vw
    GVWE205u7DhtRe85W1oR9WTsMact5wuqU6okJd2GKrEGotgd9iuAJm90N6TDeDZ4
    KHEvVEE1yTyvrxQgkwIDAQAB
    -----END PUBLIC KEY-----'''
        # 1、base64解码
        publicKeyBytes = base64.b64decode(publicKeyStr.encode())
        # 3、生成publicKey对象
        key = RSA.import_key(publicKeyBytes)
        #key = RSA.import_key(key_encoded)
        # 4、对原密码加密
        encryptPassword = rsa.encrypt(data.encode(), key)
        return base64.b64encode(encryptPassword).decode()
    

    三.DES

    1.简介

    这是一个分组加密算法,解密和加密是同一个算法,可逆的

    2.DES加密与解密以及hex输出和bs64格式输出

    import pyDes
    import base64
    
    Key = "12345678"  #加密的key
    
    Iv = None   #偏移量
    
    
    def bytesToHexString(bs):
        '''
        bytes转16进制
        '''
        return ''.join(['%02X ' % b for b in bs])
    def hexStringTobytes(str):
        '''16进制转bytes'''
        str = str.replace(" ", "")
        return bytes.fromhex(str)
    
    # 加密
    def encrypt_str(data):
        # 加密方法
        #padmode填充方式
        #pyDes.ECB模式
        method = pyDes.des(Key, pyDes.ECB, Iv, pad=None, padmode=pyDes.PAD_PKCS5)
        # 执行加密码 hex输出
        k = method.encrypt(data)
        data = bytesToHexString(k).replace(' ','')
        #bs64手粗
        #data =base64.b64encode(k)
        return data
    
    # 解密
    def decrypt_str(data):
        method = pyDes.des(Key, pyDes.ECB, Iv, pad=None, padmode=pyDes.PAD_PKCS5)
        k =hexStringTobytes(data)
        #bs64
        #k = base64.b64decode(data)
        return method.decrypt(k)
    
    
    Encrypt = encrypt_str("aaa")
    print(Encrypt)
    Decrypt = decrypt_str(Encrypt)
    print(Decrypt)
    

    四.3des

    代码模板

    import hashlib, base64
    import json
    from cryptography.hazmat.primitives.padding import PKCS7
    from cryptography.hazmat.primitives.ciphers import algorithms
    from Crypto.Cipher import DES3
    
    def pkcs7padding(text):
        """
        明文使用PKCS7填充
        最终调用DES3加密方法时,传入的是一个byte数组,要求是16的整数倍,因此需要对明文进行处理
        :param text: 待加密内容(明文)
        :return:
        """
        bs = DES3.block_size  # 16
        length = len(text)
        bytes_length = len(bytes(text, encoding='utf-8'))
        # tips:utf-8编码时,英文占1个byte,而中文占3个byte
        padding_size = length if (bytes_length == length) else bytes_length
        padding = bs - padding_size % bs
        # tips:chr(padding)看与其它语言的约定,有的会使用''
        padding_text = chr(padding) * padding
        return text + padding_text
    
    
    def pkcs7_unpad(content):
        """
        解密时候用
        :param content:
        :return:
        """
        if not isinstance(content, bytes):
            content = content.encode()
        pad = PKCS7(algorithms.DES3.block_size).unpadder()
        pad_content = pad.update(content) + pad.finalize()
        return pad_content
    
    
    def encrypt(key, content):
        """
        DES3加密
        key,iv使用同一个
        模式cbc
        填充pkcs7
        :param key: 密钥
        :param content: 加密内容
        :return:
        """
        key_bytes = bytes(key, encoding='utf-8')
        iv = key_bytes
        cipher = DES3.new(key_bytes, DES3.MODE_ECB)
        # 处理明文
        content_padding = pkcs7padding(content)
        # 加密
        encrypt_bytes = cipher.encrypt(bytes(content_padding, encoding='utf-8'))
        # 重新编码
        result = str(base64.b64encode(encrypt_bytes), encoding='utf-8')
        return result
    
    def decrypt(key,text):
        key_bytes = bytes(key, encoding='utf-8')
        iv = key_bytes
        cryptos = DES3.new(key_bytes, DES3.MODE_ECB)
        data = cryptos.decrypt(text)
        return json.loads(pkcs7_unpad(data))
    

    五.AES加密

    1.简介

    和DES差不多,可逆的

    2.AES_ECB_pkcs5padding(该模板不兼容中文)

    from Crypto.Cipher import AES
    import base64
    
    class Aes_ECB(object):
        def __init__(self):
            self.key = 'XXXXXXXXXXX'  #秘钥
            self.MODE = AES.MODE_ECB
            self.BS = AES.block_size
            self.pad = lambda s: s + (self.BS - len(s) % self.BS) * chr(self.BS - len(s) % self.BS)
            self.unpad = lambda s: s[0:-ord(s[-1])]
    
        # str不是16的倍数那就补足为16的倍数
        def add_to_16(value):
            while len(value) % 16 != 0:
                value += ''
            return str.encode(value)  # 返回bytes
    
        def AES_encrypt(self, text):
            aes = AES.new(Aes_ECB.add_to_16(self.key), self.MODE)  # 初始化加密器
            encrypted_text = str(base64.encodebytes(aes.encrypt(Aes_ECB.add_to_16(self.pad(text)))),
                                 encoding='utf-8').replace('
    ', '')  # 这个replace大家可以先不用,然后在调试出来的结果中看是否有'
    '换行符
            # 执行加密并转码返回bytes
            return encrypted_text
    

    3.AES_ECB_pkcs7padding(支持中文)

    import hashlib, base64
    from Crypto.Cipher import AES
    from cryptography.hazmat.primitives.padding import PKCS7
    from cryptography.hazmat.primitives.ciphers import algorithms
    
    
    def pkcs7padding(text):
        """
        明文使用PKCS7填充
        最终调用AES加密方法时,传入的是一个byte数组,要求是16的整数倍,因此需要对明文进行处理
        :param text: 待加密内容(明文)
        :return:
        """
        bs = AES.block_size  # 16
        length = len(text)
        bytes_length = len(bytes(text, encoding='utf-8'))
        # tips:utf-8编码时,英文占1个byte,而中文占3个byte
        padding_size = length if (bytes_length == length) else bytes_length
        padding = bs - padding_size % bs
        # tips:chr(padding)看与其它语言的约定,有的会使用''
        padding_text = chr(padding) * padding
        return text + padding_text
    
    
    def pkcs7_unpad(content):
        """
        解密时候用
        :param content:
        :return:
        """
        if not isinstance(content, bytes):
            content = content.encode()
        pad = PKCS7(algorithms.AES.block_size).unpadder()
        pad_content = pad.update(content) + pad.finalize()
        return pad_content
    
    
    def encrypt(key, content):
        """
        AES加密
        key,iv使用同一个
        模式cbc
        填充pkcs7
        :param key: 密钥
        :param content: 加密内容
        :return:
        """
        key_bytes = bytes(key, encoding='utf-8')
        iv = key_bytes
        cipher = AES.new(key_bytes, AES.MODE_ECB)
        # 处理明文
        content_padding = pkcs7padding(content)
        # 加密
        encrypt_bytes = cipher.encrypt(bytes(content_padding, encoding='utf-8'))
        # 重新编码
        result = str(base64.b64encode(encrypt_bytes), encoding='utf-8')
        return result
    
    def decrypt(key,text):
        key_bytes = bytes(key, encoding='utf-8')
        iv = key_bytes
        cryptos = AES.new(key_bytes, AES.MODE_ECB)
        data = cryptos.decrypt(text)
        return json.loads(pkcs7_unpad(data))
    

    4.识别是AES_128192256怎么识别

    根据key的长度进行识别
    128 16位
    192 24位
    256 32位
    #基本上不足的部分都是以0进行填充
    

    5.ECB和CBC在代码实现上的区别

    CBC相比ECB多一个偏移量,至于其他地方代码区别不大
    

    六.SM2/SM4

    GMSSL模块介绍

    GmSSL是一个开源的加密包的python实现,支持SM2/SM3/SM4等国密(国家商用密码)算法、项目采用对商业应用友好的类BSD开源许可证,开源且可以用于闭源的商业应用。

    安装模块

    pip install gmssl
    #https://github.com/duanhongyi/gmssl/blob/master/README.md官方文档
    

    SM2算法

    RSA算法的危机在于其存在亚指数算法,对ECC算法而言一般没有亚指数攻击算法 SM2椭圆曲线公钥密码算法:我国自主知识产权的商用密码算法,是ECC(Elliptic Curve Cryptosystem)算法的一种,基于椭圆曲线离散对数问题,计算复杂度是指数级,求解难度较大,同等安全程度要求下,椭圆曲线密码较其他公钥算法所需密钥长度小很多。

    gmssl是包含国密SM2算法的Python实现, 提供了 encryptdecrypt等函数用于加密解密, 用法如下:

    1. 初始化CryptSM2

    import base64
    import binascii
    from gmssl import sm2, func
    #16进制的公钥和私钥
    private_key = '00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'
    public_key = 'B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'
    sm2_crypt = sm2.CryptSM2(
        public_key=public_key, private_key=private_key)
    

    2. encryptdecrypt

    #数据和加密后数据为bytes类型
    data = b"111"
    enc_data = sm2_crypt.encrypt(data)
    dec_data =sm2_crypt.decrypt(enc_data)
    assert dec_data == data
    

    3.signverify

    data = b"111" # bytes类型
    random_hex_str = func.random_hex(sm2_crypt.para_len)
    sign = sm2_crypt.sign(data, random_hex_str) #  16进制
    assert sm2_crypt.verify(sign, data) #  16进制
    

    SM4算法

    国密SM4(无线局域网SMS4)算法, 一个分组算法, 分组长度为128bit, 密钥长度为128bit, 算法具体内容参照SM4算法

    gmssl是包含国密SM4算法的Python实现, 提供了 encrypt_ecbdecrypt_ecbencrypt_cbcdecrypt_cbc等函数用于加密解密, 用法如下:

    1. 初始化CryptSM4

    from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
    
    key = b'3l5butlj26hvv313'
    value = b'111' #  bytes类型
    iv = b'x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00' #  bytes类型
    crypt_sm4 = CryptSM4()
    

    2. encrypt_ecbdecrypt_ecb

    crypt_sm4.set_key(key, SM4_ENCRYPT)
    encrypt_value = crypt_sm4.crypt_ecb(value) #  bytes类型
    crypt_sm4.set_key(key, SM4_DECRYPT)
    decrypt_value = crypt_sm4.crypt_ecb(encrypt_value) #  bytes类型
    assert value == decrypt_value
    

    3. encrypt_cbcdecrypt_cbc

    crypt_sm4.set_key(key, SM4_ENCRYPT)
    encrypt_value = crypt_sm4.crypt_cbc(iv , value) #  bytes类型
    crypt_sm4.set_key(key, SM4_DECRYPT)
    decrypt_value = crypt_sm4.crypt_cbc(iv , encrypt_value) #  bytes类型
    assert value == decrypt_value
    

    七.其他不怎么需要模板的加密

    1.base64加密

    import base64   #base64也是用来加密的,但是这个是可以解密的
    s = "password"
    print(base64.b64encode(s.encode()) )  #加密
    

    2.uuid

    #有时候你会看到一些比如xxxx-xxxx-xxx-xxx误以为是加密其实很多是uuid模块自动生成的
    随机数格式为:xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx
    
    python的uuid模块提供UUID类和函数uuid1(), uuid3(), uuid4(), uuid5()
    
    1.uuid.uuid1([node[, clock_seq]])
    基于时间戳
    
    使用主机ID, 序列号, 和当前时间来生成UUID, 可保证全球范围的唯一性. 但由于使用该方法生成的UUID中包含有主机的网络地址, 因此可能危及隐私. 该函数有两个参数, 如果 node 参数未指定, 系统将会自动调用 getnode() 函数来获取主机的硬件地址. 如果 clock_seq 参数未指定系统会使用一个随机产生的14位序列号来代替.
    
    2.uuid.uuid3(namespace, name)
    基于名字的MD5散列值
    
    通过计算命名空间和名字的MD5散列值来生成UUID, 可以保证同一命名空间中不同名字的唯一性和不同命名空间的唯一性, 但同一命名空间的同一名字生成的UUID相同.
    
    3.uuid.uuid4()
    基于随机数
    
    通过随机数来生成UUID. 使用的是伪随机数有一定的重复概率.
    
    4.uuid.uuid5(namespace, name)
    基于名字的SHA-1散列值
    

    3.md5加盐

    import hashlib
    
    #注意加密顺序 
    m=hashlib.md5('加密内容'.encode('utf8'))
    m.update(b"盐")
    sign = m.hexdigest()
    

    4.字符串和16进制字符串之间转换

    import binascii
    
    binascii.b2a_hex('字符串'.encode())  输出b'e5ad97e7aca6e4b8b2'
    binascii.a2b_hex('e5ad97e7aca6e4b8b2').decode()   输出 '字符串'
    
  • 相关阅读:
    容器跨主机网络通信学习笔记(以Flannel为例)
    Kubernetes控制器Job和CronJob
    记一次使用Flannel插件排错历程
    Kubernetes控制器Deployment
    Kubernetes如何通过StatefulSet支持有状态应用?
    react18 来了,我 get 到...
    gojs 实用高级用法
    vuecli3 vue2 保留 webpack 支持 vite 成功实践
    calibre 报错 This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem. 解决
    unable to recognize "*.yaml": no matches for kind "RoleBinding" in version "rbac.authorization.k8s.io/v1beta1"
  • 原文地址:https://www.cnblogs.com/pythonywy/p/13534962.html
Copyright © 2011-2022 走看看