介绍

在接口测试中我们常常遇到各种需要加密的场景,不同的加密方式需要我们使用不同的算法去实现
针对网络数据安全问题,可以用以下几种数据加密方式来解决:

数据加密方式 描述 主要解决的问题 常用算法
对称加密 指数据加密和解密使用相同的密钥 数据的机密性 DES, AES
非对称加密 也叫公钥加密,指数据加密和解密使用不同的密钥–密钥对儿 身份验证 DSA,RSA
单向加密 指只能加密数据,而不能解密数据 数据的完整性 MD5,SHA系列算法

编码与解码

通常所说的加密方式,都是对二进制编码的格式进行加密的,对应到Python中,则是我们的Bytes。所以当我们在Python中进行加密操作的时候,要确保我们操作的是Bytes,否则就会报错。将字符串和Bytes互相转换可以使用encode()和decode()方法。

  • encode():str对象的方法,用于将字符串转换为二进制数据(即bytes),也称为“编码”。
  • decode():bytes对象的方法,用于将二进制数据转换为字符串,也称为“解码”。
  • 在设置解码采用的字符编码时,需要与编码时采用的字符编码一致。使用decode()方法时,同样不会修改原字符串。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/6/15 20:02
# @Author  : shisuiyi
# @File    : str_to_Bytes.py
# @Software: win10 Tensorflow1.13.1 python3.9


# encode()编码
str0 = '不予の测试笔记'
byte0 = str0.encode("GBK")
print("编码前:", str0)
print("编码后:", byte0)

byte1 = b'\xb2\xbb\xd3\xe8\xa4\xce\xb2\xe2\xca\xd4\xb1\xca\xbc\xc7'
str1 = byte1.decode("GBk")
print("解码后:", str1)

输出:

编码前: 不予の测试笔记
编码后: b'\xb2\xbb\xd3\xe8\xa4\xce\xb2\xe2\xca\xd4\xb1\xca\xbc\xc7'
解码后: 不予の测试笔记

Base64加密与解密

# -*- coding: utf-8 -*-
import base64


def bs64_data_encode(st):  # base64加密
    new_str = str(st)
    encode_str = base64.b64encode(new_str.encode())
    return encode_str


def bs64_data_decode(st):   # base64解密
    res = base64.b64decode(st).decode()
    return res


if __name__ == '__main__':
    print(bs64_data_encode('不予の测试笔记'))
    print(bs64_data_decode('5LiN5LqI44Gu5rWL6K+V56yU6K6w'))

输出结果:

b'5LiN5LqI44Gu5rWL6K+V56yU6K6w'
不予の测试笔记

MD5加密

  1. 简介

MD5加密即message-digest algorithm 5(信息-摘要算法),即信息-摘要算法,可以将一个字符串,或文件,或压缩包,执行md5后,就可以生成一个固定长度为128bit的串。

  1. 用途

加密注册用户的密码。
网站用户上传图片 / 文件后,将MD5值作为文件名。(MD5可以保证唯一性)
key-value数据库中使用MD5值作为key。
比较两个文件是否相同。(在下载资源的时候,发现网站提供了MD5值,就是用来检测文件是否被篡改)

  1. 使用hashlib模块进行md5操作

# -*- coding: utf-8 -*-

import hashlib  # 导入导入模块hashlib


def MD5_demo(str):
    md = hashlib.md5()  # 创建md5对象
    md.update(str.encode(encoding='utf-8'))
    return md.hexdigest()  # 小写


if __name__ == "__main__":
    # 待加密信息
    str0 = '不予の测试笔记'
    md5_str = MD5_demo(str0)
    print('加密前为 :' + str0)
    print('加密后为 :' + md5_str)

输出结果:

加密前为 :不予の测试笔记
加密后为 :a6ac80c8865b983a163ea03ed24a2d8b

sha1加密

SHA1的全称是Secure Hash Algorithm(安全哈希算法) 。SHA1基于MD5,加密后的数据长度更长,它对长度小于264的输入,产生长度为160bit的散列值。比MD5多32位,因此,比MD5更加安全,但SHA1的运算速度就比MD5要慢。

# -*- coding: utf-8 -*-
"""
使用sha1加密算法,返回str加密后的字符串
"""
import hashlib


def sha1_secret_str(s: str):
    sha = hashlib.sha1(s.encode('utf-8'))
    encrypts = sha.hexdigest()
    return encrypts


if __name__ == '__main__':
    s = "不予の测试笔记"
    sha1_str = sha1_secret_str(s)
    print('加密前为 :' + s)
    print('加密后为 :' + sha1_str)

输出结果:

加密前为 :不予の测试笔记
加密后为 :796f1c0154647422ffc2ca9eb62041e9376c66af

SHA256

比特币挖矿的御用算法
SHA256是SHA-2下细分出的一种算法

SHA-2,名称来自于安全散列算法2(英语:Secure Hash Algorithm 2)的缩写,一种密码散列函数算法标准(哈希算法),由美国国家安全局研发,属于SHA算法之一,是SHA-1的后继者。

SHA-2下又可再分为六个不同的算法标准,包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。这些变体除了生成摘要的长度 、循环运行的次数等一些微小差异外,

算法的基本结构是一致的。对于任意长度的消息,SHA256都会产生一个256bit长的哈希值,称作消息摘要。这个摘要相当于是个长度为32个字节的数组,通常用一个长度为64的十六进制字符串来表示。

# -*- coding: utf-8 -*-
import hashlib


def sha256_single(value):
    """
    sha256加密
    :param value: 加密字符串
    :return: 加密结果转换为16进制字符串,并大写
    """
    hsobj = hashlib.sha256()
    hsobj.update(value.encode("utf-8"))
    return hsobj.hexdigest().upper()


if __name__ == '__main__':
    s = "不予の测试笔记"
    sha256_str = sha256_single(s)
    print('加密前为 :' + s)
    print('加密后为 :' + sha256_str)

输出结果:

加密前为 :不予の测试笔记
加密后为 :F218FC60E61A5F910442686A6882B608AC5A81F9D021A4FCF271E2BE8252DE45

DES加密

安装和导入:

安装:pip install pyDes
导入:from pyDes import des, CBC, PAD_PKCS5

示例:

# -*- coding: utf-8 -*-
"""
@FileName:  des.py
@Author:    shisuiyi
@time:      2022/06/16
"""

from pyDes import des, CBC, PAD_PKCS5
import binascii

"""
    DES加密、解密
"""


class DesHandle:
    def __init__(self, text):
        self.text = text
        self.KEY = '12345678'  # 这个key是固定问开发,

    def des_encrypt(self):
        """
        DES 加密
        :param s: 原始字符串
        :return: 加密后字符串,16进制
        """
        secret_key = self.KEY  # 密码
        iv = secret_key  # 偏移
        # secret_key:加密密钥,CBC:加密模式,iv:偏移, padmode:填充
        des_obj = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
        # 返回为字节
        secret_bytes = des_obj.encrypt(self.text.encode("utf-8"), padmode=PAD_PKCS5)
        # 返回为16进制
        return binascii.b2a_hex(secret_bytes)

    def des_descrypt(self):
        """
        DES 解密
        :param s: 加密后的字符串,16进制
        :return:  解密后的字符串
        """
        secret_key = self.KEY
        iv = secret_key
        des_obj = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
        decrypt_str = des_obj.decrypt(binascii.a2b_hex(self.text), padmode=PAD_PKCS5)

        return bytes.decode(decrypt_str)  # bytes.decode() 将bit转为str


if __name__ == '__main__':
    handle1 = DesHandle("不予の测试笔记")
    print(handle1.des_encrypt())
    handle2 = DesHandle("d902f013c0d73869401b7b7e7fa694a84de91ae7c5fbeffd")
    print(handle2.des_descrypt())

输出结果:

b'd902f013c0d73869401b7b7e7fa694a84de91ae7c5fbeffd'
不予の测试笔记

AES加密

AES算法详解:高级加密标准,它是一种对称加密算法,AES只有一个密钥,这个密钥既用来加密,也用于解密。

AES加密方式有五种:ECB, CBC, CTR, CFB, OFB。
从安全性角度推荐CBC加密方法,本文介绍了CBC,ECB两种加密方法的python实现。
CBC 和ECB模式的区别就是:

CBC加密需要一个十六位的key(密钥)和一个十六位iv(偏移量)
ECB加密不需要iv,只需要key(密钥)

安装

在 Windows下使用AES时要安装的是pycryptodome 模块
pip install pycryptodome
在 Linux下使用AES时要安装的是pycrypto模块
pip install pycrypto

AES的ECB 模式实现

# -*- coding: utf-8 -*-
import base64
from Crypto.Cipher import AES

AES_KEY = 'aw123zsc212s9ju0'  # It must be 16, 24 or 32 bytes long (respectively for *AES-128*, *AES-192* or *AES-256*).


def add_to_16(text: str) -> bytes:
    """
    不足16位的地方补全位数
    :param text: 源字符串
    :return: 补足字符串
    """
    b_text = text.encode('utf-8')
    # 计算需要补的为位数
    if len(text) % 16:
        add = 16 - (len(b_text) % 16)
    else:
        add = 0
    return b_text + (b'\0' * add)


def encrypt_by_aes(text: str, key: str) -> str:
    """
    加密函数
    :param text: 源字符串
    :param key: 密钥
    :return: 加密字符串
    """
    key = key.encode('utf-8')
    text = add_to_16(text)  # 如果长度不够补足 16 位
    cryptos = AES.new(key, AES.MODE_ECB)  # 使用ECB模式
    cipher_text = cryptos.encrypt(text)  # 加密
    return base64.standard_b64encode(cipher_text).decode('utf-8')  # 将加密结果转为base64编码输出


def decrypt_by_aes(text: str, key: str):
    """
    解密函数
    :param text: 加密字符串
    :param key: 密钥
    :return: 解密结果
    """
    key = key.encode('utf-8')
    text = text.encode('utf-8')
    text = base64.b64decode(text)  # 先使用base64解码
    cryptos = AES.new(key, AES.MODE_ECB)
    cipher_text = cryptos.decrypt(text)  # 解密
    return cipher_text.decode('utf-8').strip('\0')


if __name__ == '__main__':
    source_str = '不予の测试笔记'
    encrypt_str = encrypt_by_aes(source_str, AES_KEY)
    decrypt_str = decrypt_by_aes(encrypt_str, AES_KEY)
    print(encrypt_str)
    print(decrypt_str)

输出结果:

v1Y+LCYilaKuVd9jXGW4OG6wQrmakZhhT7CDN48lliM=
不予の测试笔记

AES的CBC 模式实现

# -*- coding: utf-8 -*-
import base64
from Crypto.Cipher import AES

class EncryptDate:
    def __init__(self, key, iv):
        self.key = key.encode("utf-8")                          # 初始化密钥
        self.iv = iv.encode("utf-8")                            # 初始化偏移量
        self.length = 16                                        # 初始化数据块大小
        self.aes = AES.new(self.key, AES.MODE_CBC, self.iv)     # 初始化AES,ECB模式的实例
        # 截断函数,去除填充的字符
        self.unpad = lambda s: s[0:-s[-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):  # 加密函数
        a = self.pad(encrData)
        res = self.aes.encrypt(a.encode("utf-8"))
        msg = str(base64.b64encode(res), encoding="utf8")
        return msg

    def decrypt(self, decrData):  # 解密函数
        res = base64.decodebytes(decrData.encode("utf-8"))
        msg_text = self.aes.decrypt(res)
        decrypt_text = self.unpad(msg_text).decode('utf8')
        return decrypt_text


if __name__ == '__main__':
    aes_key = "0CoJUm6Qyw8W8jud"
    aes_iv = "9999999999999999"
    text_data = '不予の测试笔记'
    encrypt_data = EncryptDate(aes_key, aes_iv).encrypt(text_data)
    decrypt_data = EncryptDate(aes_key, aes_iv).decrypt(encrypt_data)
    print("原始数据:", text_data)
    print("加密后数据:", encrypt_data)
    print("数据解密:", decrypt_data)

输出结果:

原始数据: 不予の测试笔记
加密后数据: DSiSraEccFNBbo5L7O60C4sZw9z+owwxfTi8fMFYYVM=
数据解密: 不予の测试笔记

RSA加密

RSA加密算法是一种非对称加密算法, 使用openssl ,keytools等工具生成一对公私钥对,使用被公钥加密的数据可以使用私钥来解密。

# -*- coding: utf-8 -*-
import rsa
import base64


# rsa加密
def rsaEncrypt(str):
    # 生成公钥、私钥
    (pubkey, privkey) = rsa.newkeys(1024)
    print("公钥: ", pubkey)
    print("私钥: ", privkey)
    # 明文编码格式
    content = str.encode('utf-8')
    # 公钥加密
    crypto = rsa.encrypt(content, pubkey)
    # # 一般加密的密文会以base64编码的方式输出
    b_res = base64.b64encode(crypto).decode()
    return(b_res, privkey)


# rsa解密
def rsaDecrypt(str, pk):
    # 私钥解密
    str = base64.b64decode(str.encode())
    content = rsa.decrypt(str, pk)
    con = content.decode('utf-8')

    return con


(a, b) = rsaEncrypt("不予の测试笔记")
print('加密后密文:', a)
content = rsaDecrypt(a, b)
print('解密后明文:', content)

输出结果:

公钥:  PublicKey(113470524225910557322884041079730885629500891762564656647656493210767749547668213373094028584810486476685694392950833477491276179265755337717974938997270915920724776540032039593464817490125523868061678130911761061942123329506543626197368650416434554584363549666830839661425323410205940989023322707335471888693, 65537)
私钥:  PrivateKey(113470524225910557322884041079730885629500891762564656647656493210767749547668213373094028584810486476685694392950833477491276179265755337717974938997270915920724776540032039593464817490125523868061678130911761061942123329506543626197368650416434554584363549666830839661425323410205940989023322707335471888693, 65537, 49057384888184532877406601155882858742790763495437798212531838177424865582550790510905995177106372336701595509862656449810608042225245460410166786907298318676412949734430422952998615505434350499917821657126361553083727322987072459664877185816829930588001976168732927196445249652057892467131716493395488174913, 42634469690852041372779335865769377507324089843269658005185029937283890025207576461770779563428903937547975990563042099326958533052937770882166072164786597159641161, 2661473803912649805246869624668668574550205591791588900635990794504918156173482653597243444437455173742897237144953732507167046192020136204937613)
加密后密文: hI2rGwCXvG/8Y1yDg/G4rQLVKl22UnD/bun08CITOMHyeY2J7MI5c+Ex2sUTb2KJO+6QHkDJpAv+Q70KLmeprxQVMdnwapRNFg6imds+QdffkT926pt0kmF95h71GWdH7PRuoB23JoSYkm5aiZUuwfp3lW+g0bJEbvtmkI0bD2s=
解密后明文: 不予の测试笔记