平常我们经常需要对数据进行传输,而有些敏感信息的传输需要进行加密处理,防止数据泄露。
比如姓名、手机号、身份证号(简称三要素)等的传输。
现在我们要对三方数据进行测试,需提供三要素给对方,对方反馈相应标签给我们。
此时需要对三要素进行加密,且不同的三方机构对加密方式有不同要求,需按机构的要求进行数据提供。
本文梳理出三方数据测试常见的加密方式,不管机构需要哪一种,都可以快速地实现。
Python中常见加密方式
安装包
不同加密方式实现
3.1 生成三要素数据
3.2 对三要素进行MD5加密
3.3 对三要素进行SHA256加密
3.4 对三要素进行AES加密

Python中常见的加密方式有以下几种:
哈希加密:如MD5、SHA1、SHA256等。这种加密方式将原始数据(通常是字符串)转换为固定长度的散列值。这是一种单向过程,即一旦数据被哈希,它不能被“解密”回原始数据。
对称加密:如AES、DES等。这种加密方式使用相同的密钥进行加密和解密。
非对称加密:如RSA、DSA等。这种加密方式使用一对密钥,一个用于加密,另一个用于解密。通常,一个是公钥,可以公开分享,另一个是私钥,需要保密。
Base64编码:严格来说,Base64并不是一种加密算法,它更多是一种编码方式。但是,由于它可以将信息转换为看起来像是随机字符的字符串,所以有时被用于简单的“加密”。
本文介绍三方数据测试常用的MD5、SHA256、AES加密。

AES加密需安装pycryptodome包。打开cmd,安装语句如下:
pip install pycryptodome -i https://pypi.tuna.tsinghua.edu.cn/simple

1 生成三要素数据
首先生成三要素数据(纯虚构)进行测试,具体代码如下:
import pandas as pddate = pd.DataFrame([['杨幂', '43052219980512', '13166456975'], ['杨紫', '43052219940413', '13166456976'], ['刘诗雯', '43052220010318', '13166456977']], columns=['姓名', '身份证号', '手机号'])date得到结果:
2 对三要素进行MD5加密
接着对三要素进行MD5加密,代码如下:
import hashlib as hbmethod = 'md5'column_list = ['姓名', '身份证号', '手机号']df = date.copy()for i in column_list:if method == 'md5':df[i + '_MD5'] = df[i].map(lambda x: hb.md5(str(x).encode('utf-8')).hexdigest())if method == 'sha256':df[i + '_SHA256'] = df[i].map(lambda x:hb.sha256(str(x).encode('utf-8')).hexdigest())df其中,method中填入想加密的方式,选md5。
column_list中填入数据框中想用method方法加密的列。
得到结果:
从结果知数据框中新增了对应加密的列。 3 对三要素进行SHA256加密
接着对三要素进行SHA256加密,代码如下:
import hashlib as hbmethod = 'sha256'column_list = ['姓名', '身份证号', '手机号']df = date.copy()for i in column_list:if method == 'md5':df[i + '_MD5'] = df[i].map(lambda x: hb.md5(str(x).encode('utf-8')).hexdigest())if method == 'sha256':df[i + '_SHA256'] = df[i].map(lambda x:hb.sha256(str(x).encode('utf-8')).hexdigest())df其中method中填入想加密的方式,选sha256。
column_list中填入数据框中想用method方法加密的列。
得到结果:
从结果知数据框中新增了对应加密的列,且数据长度比MD5加密要长。 经数据统计发现MD5加密后长度为32,SHA256加密后长度为64。
4 对三要素进行AES加密
AES加密最常用的模式就是ECB模式和CBC模式,俩者区别就是ECB不需要iv偏移量,而CBC需要。
1.ECB模式加密,代码如下:
from Crypto.Cipher import AESpassword = b'1234567812345678'text = b'abcdefghijklmnop'aes = AES.new(password, AES.MODE_ECB)en_text = aes.encrypt(text)print("密文:",en_text)den_text = aes.decrypt(en_text)print("明文:",den_text)password:密钥,b表示转换密码为bytes类型。
text:需加密的内容。
aes:创建一个aes对象,指定加密模式为ECB。
aes.encrypt:对text进行加密。
aes.decrypt:对加密内容进行解密。
得到结果:
密文:b"^\x14\xf4nfb)\x10\xbf\xe9\xa9\xec'r\x85&"明文:b'abcdefghijklmnop'这里有两个需要注意的点,大家可以自行测试。
注1:密钥必须为16字节或16字节倍数的字节型数据。
注2:明文必须为16字节或者16字节倍数的字节型数据,如果不够16字节需要进行补全。
2.CBC模式加密,代码如下:
from Crypto.Cipher import AESpassword = b'1234567812345678'iv = b'1234567812345678'text = b'abcdefghijklmnop'aes = AES.new(password, AES.MODE_CBC, iv)en_text = aes.encrypt(text)print("密文:",en_text)aes = AES.new(password,AES.MODE_CBC, iv)den_text = aes.decrypt(en_text)print("明文:",den_text)password:密钥,b表示转换密码为bytes类型。
iv:偏移量。
text:需加密的内容。
aes.encrypt:对text进行加密。
aes.decrypt:对加密内容进行解密。
得到结果:
密文:b't\xe6\xbfy\xef\xd7\x83\x11G\x95\x9d_\xcd\xab\xc7\xf8'明文:b'abcdefghijklmnop'3.对三要素进行aes加密
首先定义加密函数,代码如下:
from Crypto.Cipher import AESimport base64import binascii# 数据类class MData():def __init__(self, data = b"",characterSet='utf-8'):# data肯定为bytesself.data = dataself.characterSet = characterSetdef saveData(self,FileName):with open(FileName,'wb') as f:f.write(self.data)def fromString(self,data):self.data = data.encode(self.characterSet)return self.datadef fromBase64(self,data):self.data = base64.b64decode(data.encode(self.characterSet))return self.datadef fromHexStr(self,data):self.data = binascii.a2b_hex(data)return self.datadef toString(self):return self.data.decode(self.characterSet)def toBase64(self):return base64.b64encode(self.data).decode()def toHexStr(self):return binascii.b2a_hex(self.data).decode()def toBytes(self):return self.datadef __str__(self):try:return self.toString()except Exception:return self.toBase64()### 封装类class AEScryptor():def __init__(self,key,mode,iv = '',paddingMode= "NoPadding",characterSet ="utf-8"):'''构建一个AES对象key: 秘钥,字节型数据mode: 使用模式,只提供两种,AES.MODE_CBC, AES.MODE_ECBiv:iv偏移量,字节型数据paddingMode: 填充模式,默认为NoPadding, 可选NoPadding,ZeroPadding,PKCS5Padding,PKCS7PaddingcharacterSet: 字符集编码'''self.key = keyself.mode = modeself.iv = ivself.characterSet = characterSetself.paddingMode = paddingModeself.data = ""def __ZeroPadding(self,data):data += b'\x00'while len(data) % 16 != 0:data += b'\x00'return datadef __StripZeroPadding(self,data):data = data[:-1]while len(data) % 16 != 0:data = data.rstrip(b'\x00')if data[-1] != b"\x00":breakreturn datadef __PKCS5_7Padding(self,data):needSize = 16-len(data) % 16if needSize == 0:needSize = 16return data + needSize.to_bytes(1,'little')*needSizedef __StripPKCS5_7Padding(self,data):paddingSize = data[-1]return data.rstrip(paddingSize.to_bytes(1,'little'))def __paddingData(self,data):if self.paddingMode == "NoPadding":if len(data) % 16 == 0:return dataelse:return self.__ZeroPadding(data)elif self.paddingMode == "ZeroPadding":return self.__ZeroPadding(data)elif self.paddingMode == "PKCS5Padding" or self.paddingMode == "PKCS7Padding":return self.__PKCS5_7Padding(data)else:print("不支持Padding")def __stripPaddingData(self,data):if self.paddingMode == "NoPadding":return self.__StripZeroPadding(data)elif self.paddingMode == "ZeroPadding":return self.__StripZeroPadding(data)elif self.paddingMode == "PKCS5Padding" or self.paddingMode == "PKCS7Padding":return self.__StripPKCS5_7Padding(data)else:print("不支持Padding")def setCharacterSet(self,characterSet):'''设置字符集编码characterSet: 字符集编码'''self.characterSet = characterSetdef setPaddingMode(self,mode):'''设置填充模式mode: 可选NoPadding,ZeroPadding,PKCS5Padding,PKCS7Padding'''self.paddingMode = modedef decryptFromBase64(self,entext):'''从base64编码字符串编码进行AES解密entext: 数据类型str'''mData = MData(characterSet=self.characterSet)self.data = mData.fromBase64(entext)return self.__decrypt()def decryptFromHexStr(self,entext):'''从hexstr编码字符串编码进行AES解密entext: 数据类型str'''mData = MData(characterSet=self.characterSet)self.data = mData.fromHexStr(entext)return self.__decrypt()def decryptFromString(self,entext):'''从字符串进行AES解密entext: 数据类型str'''mData = MData(characterSet=self.characterSet)self.data = mData.fromString(entext)return self.__decrypt()def decryptFromBytes(self,entext):'''从二进制进行AES解密entext: 数据类型bytes'''self.data = entextreturn self.__decrypt()def encryptFromString(self,data):'''对字符串进行AES加密data: 待加密字符串,数据类型为str'''self.data = data.encode(self.characterSet)return self.__encrypt()def __encrypt(self):if self.mode == AES.MODE_CBC:aes = AES.new(self.key,self.mode,self.iv)elif self.mode == AES.MODE_ECB:aes = AES.new(self.key,self.mode)else:print("不支持这种模式")returndata = self.__paddingData(self.data)enData = aes.encrypt(data)return MData(enData)def __decrypt(self):if self.mode == AES.MODE_CBC:aes = AES.new(self.key,self.mode,self.iv)elif self.mode == AES.MODE_ECB:aes = AES.new(self.key,self.mode)else:print("不支持这种模式")returndata = aes.decrypt(self.data)mData = MData(self.__stripPaddingData(data),characterSet=self.characterSet)return mData接着调用函数对三要素进行加密,代码如下:
password = b"1234567812345678"iv = b'1111111122222222'aes = AEScryptor(password, AES.MODE_CBC, iv, paddingMode= "ZeroPadding", characterSet='utf-8')df = date.copy()def str_ase(wd):wd = wdrData = aes.encryptFromString(wd)return rData.toBase64()df['姓名_ase'] = df['姓名'].apply(str_ase)df['身份证号_ase'] = df['身份证号'].apply(str_ase)df['手机号_ase'] = df['手机号'].apply(str_ase)dfpassword:密钥,可自行更改。
iv:偏移量。
str_aes:对字符进行ase加密的函数。
得到结果:
可以发现和MD5、SHA256一样,都在后面增加了aes加密的列。 最后测试对aes加密的姓名进行解密,看是否和明文一致,代码如下: rData = aes.decryptFromBase64(df['姓名_ase'][0])print("明文:",rData)得到结果:
明文:杨幂可以发现结果是一致的。
至此,Python对三要素进行加密实现已讲解完毕,如想了解更多Python函数,可以翻看公众号中“学习Python”模块相关文章。
【限时免费进群】群内讨论学习Python、玩转Python、风控建模、人工智能、数据分析相关问题,还提供招聘内推信息、优秀文章、学习视频,也可交流工作中遇到的相关问题。需要的朋友添加微信号19967879837,加时备注想进的群,比如风控建模。
一文囊括风控模型搭建(原理+Python实现),持续更新。。。


限时免费进群
19967879837
添加微信号、手机号



