加密算法:DES AES RSA URLENCODE

2020-09-04  本文已影响0人  阿登20

DES加密

Python加密库PyCryptodome
PyCrytodome 取代了 PyCrypto 。
安装与导入
Windows安装之前需要先安装Microsoft Visual c++ 2015

image.png

下载地址https://www.microsoft.com/en-us/download/details.aspx?id=48145

在Linux上安装,可以使用以下 pip 命令

pip install pycryptodome
import Crypto

在Windows 系统上安装则稍有不同

pip install pycryptodomex
import Cryptodome

DES算法为密码体制中的对称密码体制,又被称为美国数据加密标准。

DES是一个分组加密算法,典型的DES以64位为分组对数据加密,加密和解密用的是同一个算法。

DES算法的入口参数有三个:Key、Data、Mode。其中Key为7个字节共56位,是DES算法的工作密钥;Data为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密。

密钥长64位,密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位,使得每个密钥都有奇数个1),分组后的明文组和56位的密钥按位替代或交换的方法形成密文组。

加密原理
DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小。这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半。使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。DES 使用 16 个循环,使用异或,置换,代换,移位操作四种基本运算。

算法步骤
1)初始置换
其功能是把输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长3 2位,其置换规则为将输入的第58位换到第一位,第50位换到第2位……依此类推,最后一位是原来的第7位。L0、R0则是换位输出后的两部分,L0是输出的左32位,R0是右32位,例:设置换前的输入值为D1D2D3……D64,则经过初始置换后的结果为:L0=D58D50……D8;R0=D57D49……D7。
其置换规则见下表:
58,50,42,34,26,18,10,2,60,52,44,36,28,20,12,4,
62,54,46,38,30,22,14,6,64,56,48,40,32,24,16,8,
57,49,41,33,25,17,9,1,59,51,43,35,27,19,11,3,
61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7,
2)逆置换
经过16次迭代运算后,得到L16、R16,将此作为输入,进行逆置换,逆置换正好是初始置换的逆运算,由此即得到密文输出。
此算法是对称加密算法体系中的代表,在计算机网络系统中广泛使用.

DES加密和解密的过程

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/9/3 18:02
# @File  : des_.py
# @Author: adeng
# @Date  : 2020/9/3
============================
"""

# DES算法为密码体制中的对称密码体制,又被称为美国数据加密标准。
# ------------------加密过程--------------------
# 由于linux和windows导入有所区别。
import sys
if sys.platform == "win32":
    from Cryptodome.Cipher import DES
    from Cryptodome.Random import get_random_bytes
elif sys.platform == "linux":
    from Crypto.Cipher import DES
    from Crypto.Random import get_random_bytes
# 必须是8个字节,也就是64位
key = get_random_bytes(8) # 随机8个字节的bytes。一般key是固定的找开发大佬要
print(key)

# 创建一个DES实例
des = DES.new(key, DES.MODE_OFB)
iv = des.iv


# 定义一个函数,用来解决加密的文本长度对8取余,不等0的情况
# 方法1
def change_str_8(text):
    text = text + (8-len(text)%8)*" "
    return text
"""
方法2
def change_str_8(text):
     '''
     text不是8的倍数【加密文本text必须为8的倍数!】,那就补足为8的倍数
     '''
     while len(text)%8 != 0:
         text += " "
     return text
"""

name = "阿登哥哥啊" # 要加密的文本
text_name = change_str_8(name)

# 加密:encrypt()
encrypt_text = des.encrypt(text_name.encode('utf-8'))

print("DES加密后:\n",encrypt_text,sep="")

#-------DES解密过程----

# decrypt(加密文本) 返回是一个byte,需要decode()解码,然后去除右边的空格
des = DES.new(key,DES.MODE_OFB,iv=iv)
decrypt_text = des.decrypt(encrypt_text).decode().rstrip(" ")
print(decrypt_text)

#-----------------------------------------------------------------
import binascii

# 这是密钥
key = b'abcdefgh'
# 需要去生成一个DES对象
des = DES.new(key, DES.MODE_OFB)
iv = des.iv
# 需要加密的数据
# text = 'python spider!'
text = '阿登哥哥啊'
text = text + (8 - (len(text) % 8)) * ' '
# 加密的过程
encrypt_text = des.encrypt(text.encode())
# 加密过后二进制转化为16进制ascii--->decode()转化为字符串
encrypt_text = binascii.b2a_hex(encrypt_text).decode()
print(encrypt_text)
# 解密需要ASCII 先转化为二进制 然后再进行解密
des = DES.new(key, DES.MODE_OFB, iv=iv)
plaint = des.decrypt(binascii.a2b_hex(encrypt_text.encode("utf-8"))).decode().rstrip(" ")
print(plaint, type(plaint))

# -------------------DES 函数封装------------------------------

# -----------------------------------------
def des_encrypt(text, key=b"dyunrena"):
    """
    DES 对称法加密text
    text:需要加密的文本
    key:8位,必须是byte,默认值可以做成 配置文件,以后修改直接修改配置文件
    """
    import sys,binascii
    if sys.platform == "win32":
        from Cryptodome.Cipher import DES
        from Cryptodome.Random import get_random_bytes
    elif sys.platform == "linux":
        from Crypto.Cipher import DES
        from Crypto.Random import get_random_bytes

    des = DES.new(key, DES.MODE_OFB,iv=iv)
    name_text = text + (8 - len(text) % 8) * " "
    encrypt_text = des.encrypt(name_text.encode("utf-8"))
    return binascii.b2a_hex(encrypt_text).decode()


def des_decrypt(text, key=b"dyunrena"):
    """
    DES 对称法加密text,类型str
    text:需要加密的文本
    key:8位,必须是byte.默认值可以做成 配置文件,以后修改直接修改配置文件
    """
    import sys, binascii
    if sys.platform == "win32":
        from Cryptodome.Cipher import DES
        from Cryptodome.Random import get_random_bytes
    elif sys.platform == "linux":
        from Crypto.Cipher import DES
        from Crypto.Random import get_random_bytes


    des = DES.new(key, DES.MODE_OFB,iv=iv)
    # 解密
    decrypt_text = des.decrypt(binascii.a2b_hex(text.encode("utf-8")))  # 返回是一个 b

    return decrypt_text.decode()

print("加密:",des_encrypt('python spider!'))
print("解密:",des_decrypt(des_encrypt("他问她头发头发11112hell    ")))

AES加密

AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同。

一般常用的是128位

DES加密和解密的过程

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/9/4 0:16
# @File  : aes_.py
# @Author: adeng
# @Date  : 2020/9/4
============================
"""
import sys,binascii
if sys.platform == "win32":
    from Cryptodome.Cipher import AES
    from Cryptodome.Random import get_random_bytes
    from Cryptodome import Random
elif sys.platform == "linux":
    from Crypto.Cipher import AES
    from Crypto.Random import get_random_bytes

# 密钥key必须为 16(AES-128), 24(AES-192), 32(AES-256)
key = b'this is a 16 key'
# 创建一个AES实例
cipher = AES.new(key, AES.MODE_EAX,nonce=key)

data = "我是阿登啊"
# data = "hello"
# 加密的明文长度必须为16的倍数, 如果长度不为16的倍数, 则需要补足为16的倍数

# 加密
cipher_text, tag = cipher.encrypt_and_digest(data.encode("utf-8"))
cipher_text = binascii.b2a_hex(cipher_text).decode() # 转化成字符串
print(cipher_text)


# 重新创建一个AES实例
aes = AES.new(key, AES.MODE_EAX,nonce=key)

decrypt_text = aes.decrypt(binascii.a2b_hex(cipher_text.encode("utf-8")))

print(decrypt_text,type(decrypt_text))

decrypt_text = decrypt_text.decode()
print(decrypt_text)


#---------------------------------------------------------
# # 封装成函数
def aes_encrypt(data,key=b'this is a 16 key'):
    cipher = AES.new(key, AES.MODE_EAX,nonce=key)
    cipher_text, tag = cipher.encrypt_and_digest(data.encode("utf-8"))
    return binascii.b2a_hex(cipher_text).decode("utf-8")

def aes_decrypt(data,key=b'this is a 16 key'):
    data = binascii.a2b_hex(data.encode("utf-8"))
    cipher = AES.new(key,AES.MODE_EAX,nonce=key)
    decrypt_text = cipher.decrypt(data)
    return decrypt_text.decode()

print(aes_encrypt("python1111111111"))
print(aes_decrypt(aes_encrypt("python122222")))


RSA加密

非对称加密
典型的非对称加密
典型的如RSA等,常见方法,使用openssl ,keytools等工具生成一对公私钥对,使用被公钥加密的数据可以使用私钥来解密,反之亦然(被私钥加密的数据也可以被公钥解密) 。

在实际使用中私钥一般保存在发布者手中,是私有的不对外公开的,只将公钥对外公布,就能实现只有私钥的持有者才能将数据解密的方法。 这种加密方式安全系数很高,因为它不用将解密的密钥进行传递,从而没有密钥在传递过程中被截获的风险,而破解密文几乎又是不可能的。

但是算法的效率低,所以常用于很重要数据的加密,常和对称配合使用,使用非对称加密的密钥去加密对称加密的密钥。

简介
RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。

该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用

而且,因为RSA加密算法的特性,RSA的公钥私钥都是10进制的,但公钥的值常常保存为16进制的格式,所以需要将其用int()方法转换为10进制格式。

RSA加密和解密的过程

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/9/4 1:53
# @File  : rsa_.py
# @Author: adeng
# @Date  : 2020/9/4
============================
"""

import sys,binascii
if sys.platform == "win32":
    from Cryptodome.PublicKey import RSA
    from Cryptodome.Cipher import PKCS1_OAEP,PKCS1_v1_5
elif sys.platform == "linux":
    from Crypto.PublicKey import RSA
    from Crypto.Cipher import PKCS1_OAEP, PKCS1_v1_5

class MyRSA():
    def create_rsa_key(self, password):
        """

        创建RSA密钥

        步骤说明:

        1、从 Crypto.PublicKey 包中导入 RSA,创建一个密码

        2、生成 1024/2048 位的 RSA 密钥

        3、调用 RSA 密钥实例的 exportKey 方法,传入密码、使用的 PKCS 标准以及加密方案这三个参数。

        4、将私钥写入磁盘的文件。

        5、使用方法链调用 publickey 和 exportKey 方法生成公钥,写入磁盘上的文件。

        """

        key = RSA.generate(1024)

        encrypted_key = key.exportKey(passphrase=password.encode("utf-8"), pkcs=8,

                                      protection="scryptAndAES128-CBC")

        with open("my_private_rsa_key.bin", "wb") as f:
            f.write(encrypted_key) # 私钥写入文件

        with open("my_rsa_public.pem", "wb") as f:
            f.write(key.publickey().exportKey()) # 公钥写入文件


    def encrypt(self, plaintext):
        """
        plaintext:需要加密的文本,公钥加密,私钥解密
        """

        # 加载公钥

        recipient_key = RSA.import_key(

            open("my_rsa_public.pem").read()

        )

        cipher_rsa = PKCS1_v1_5.new(recipient_key) # 准备加密

        en_data = cipher_rsa.encrypt(plaintext.encode("utf-8"))

        return binascii.b2a_hex(en_data).decode() # 返回字符串

        # print(len(en_data), en_data)

    def decrypt(self, en_data, password):
        """
        en_data:加密过后的数据
        """
        # 读取私钥

        private_key = RSA.import_key(

            open("my_private_rsa_key.bin").read(),

            passphrase=password

        )

        cipher_rsa = PKCS1_v1_5.new(private_key) # 准备解密

        data = cipher_rsa.decrypt(binascii.a2b_hex(en_data.encode("utf-8")), None)

        return data.decode()

        # print(data)


mrsa = MyRSA()

mrsa.create_rsa_key('dyunren')

e = mrsa.encrypt('我叫阿登啊')

d = mrsa.decrypt(e, 'dyunren')

print(e)

print(d)

URLENCODE加密

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
# @Time : 2020/9/4 2:36
# @File  : urlencode_.py
# @Author: adeng
# @Date  : 2020/9/4
============================
"""

# urlencode在线解码:http://tool.chinaz.com/tools/urlencode.aspx

url = "www.baidu.com/?name=阿登,gender=男"

from urllib.parse import quote, unquote

# 加密
enc_url = f"www.baidu.com/?name={quote('阿登')},gender={quote('男')}"
print(enc_url)

# 解码

dec_url = unquote(enc_url)
print(dec_url)

#----------------------------------------

def url_decrypt(enc_url):
    """
    enc_url:加密过的url,特征是一般是?后面有很多个%
    """
    return unquote(enc_url)
上一篇下一篇

猜你喜欢

热点阅读