需求:
1 :员工在填写用户的手机号时,直接填写,在django后台中输入
2:当员工在后台确认要存储到数据库时,后台将会把手机号进行加密存储,当数据库被黑之后,手机号字段为加密字符
3:员工在后台中进行查看客户手机号时,需要正常显示,非加密状态
4:直接把公钥和私钥存放到代码里面,不要额外读取存储公钥私钥
5:为何有该需求,请参考《个人信息保护法》
1安装加密插件
pip install rsa
该命令将会安装(2024年1月17日)
1:插件名=pyasn1,版本=pyasn1-0.5.1
2:插件名=rsa,版本=rsa-4.9
2生成加密文件
请自行创建a.py文件,运行以下代码 python a.py
from Crypto.PublicKey import RSAfrom Crypto.Cipher import PKCS1_OAEPimport binascii# 生成RSA密钥对key = RSA.generate(2048)public_key = key.publickey()# 将公钥和私钥保存到本地文件with open('public_key.pem', 'wb') as f:f.write(public_key.export_key())with open('private_key.pem', 'wb') as f:f.write(key.export_key())
这时已经在a.py的相同路径中创建了公钥和私钥的文件
3安装读取加密插件
pip install cryptography
4:在django项目中应用
models.py文件中代码如下
# -------------------------------------------------------------------------------------# 手机号加密插件from cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives import serialization, hashesfrom cryptography.hazmat.primitives.asymmetric import paddingimport base64# -------------------------------------------------------------------------------------class Order(models.Model):id = models.BigAutoField(primary_key=True, unique=True, verbose_name='订单id', )shoujihao = models.TextField(verbose_name='客户手机号码', max_length=30000, blank=True)# -------------------------------------------------------------------------------------# 手机号解密def get_shoujihao(self):# 1:获取到数据库中的字符串 a# 2:把字符串转换成字节类型 b# 3:对字节b进行解密为 c# 4:返回cif len(self.shoujihao)>=20:shoujihao1=self.shoujihaoshoujihao1 = base64.b64decode(shoujihao1)# 读取私钥文件private_key="""-----BEGIN RSA PRIVATE KEY-----MIIEowIBAAKCAQEAp4vQEgBPcCy09xmJDVFxjuYk+USqBNgUxIHF4+E9Vot1rDWUncFSIERsEqTq9wIlVsgiVtRJ/0FxHLIgZPlFvRRUh0JjxkpddYAK+EKK2gySoiE8kUwomeYpILg/pAxtSoRBbUqtE/sTQZM2sOM07FYrz/Q8oVBN1Au3/LwOOAFf6R/5lFBJCutS/wAuvydwxlTjuNp4PF4Tc65qaF+35VE0IvcOByahAPRqI4TqFb/UOidJ1Xc4HPIwmtkeYYRyqDgZun2tdQ0iQm7A7lN9TkP6qoKbTRI9ySoBHs4SJXy8r63rxPRgkjEsVR/hcsZAt7LHjNnZKWd8b1yi0AO56QIDAQABAoIBABya/xUXtvheta3rju32bgY5Dm59le6aSt9rDbOUuPF+AYL7qepOP5yROgdr3075b5ETveMnvxOE45BD7Ep5EbpQzobCY8EO4MqHKDhPOiA03dMvDAV9pH/0Hyj+NCVo1r8OehI0Gf1LlHPRc9i7DgXcx4GrgC+Fg6g0sP7GR8IxWKkT1rHNWWjqaWh3HlBbJhdrZpxjKbCqTjKMImrgPKDi1An0NNHJyQe42XNgmOAMoCRUvP8skLveyYDQ2+LCeTjnmOD0WTMlwlt3ulu4MjKh/wMAj7dxguonK97C01n0utP+k0KdkOP+rBNazEF2roY2FrcYr+n1MgTsQDECG1JVtYVP1Tuyb3pgoQKBgC9SV/Ft1K4T8e/AiTrF07SCn8BEZOZ0BDI69+lBcYh1CPXBt1M0a+T+M1mwCVWxYrapfVismesnIiVQO+n2AehdDyvE1krkHRTQCUYDPkM7efPek9WBWHy6dbEPJ+mMDs1P5mVOV7MJEGQMtE01BO/KoQ74fePrbaFDwHkUnzuBAoGBAJIpUUmDMnkMzr5HPw1rtZEjkR0k+EQXU3jeaKA1TjqRoli1ApUpBB11ekDfPc/BqzRSIkACEijwdnf7NhQveCAiE+aj5NiGkwS/zjX9S96v0qK5SFil6y+cEXv1GMN54aCmiHWBGq86tOKjV9M4hnlVpuRJPeHi52nAyHpJfmB7-----END RSA PRIVATE KEY-----"""key = serialization.load_pem_private_key(private_key.encode(), password=None, backend=default_backend())decrypted_data = key.decrypt(shoujihao1, padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),algorithm=hashes.SHA256(), label=None))# decrypted_data 的类型为字节decrypted_data=decrypted_data.decode('utf-8')# decrypted_data.decode()之后的类型为字符串shoujihao1=decrypted_dataprint("类型")print(type(decrypted_data))print(decrypted_data)# 打印解密后的消息color_code = 'green'return format_html('{}', color_code, shoujihao1)else:color_code = 'green'return format_html('-', color_code, )get_shoujihao.short_description = '手机号'
admin.py文件中代码如下
# -------------------------------------------------------------------------------------# 手机号加密插件from cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives import serialization, hashesfrom cryptography.hazmat.primitives.asymmetric import paddingimport base64# -------------------------------------------------------------------------------------# -------------------------------------------------------------------------------------class Order_salesmanAdmin(admin.ModelAdmin):# -------------------------------------------------------------------------------------# 手机号加密显示 和手机号显示# 设置录入后台中展示的数据字段list_display = ['id','shoujihao', 'get_shoujihao',]def save_model(self, request, obj, form, change):if not obj.pk:obj.userid = UserProfile.objects.get(user=request.user)# 客户手机号加密存储shoujihao1 = obj.shoujihaoif len(shoujihao1) == 11:# 1:在admin后台中,允许用户输入的是字符串类型的数据# 2:加密之后得到的是字节类型,# 3:把字节类型的编码为utf-8的字符串类型 存储在数据库中# 读取公钥文件public_key = """-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp4vQEgBPcCy09xmJDVFxjuYk+USqBNgUxIHF4+E9Vot1rDWUncFSIERsEqTq9wIlVsgiVtRJ/0FxHLIgZPlFTkP6qoKbTRI9ySoBHs4SJXy8r63rxPRgkjEsVR/hcsZAt7LHjNnZKWd8b1yi0AO56QIDAQAB-----END PUBLIC KEY-----"""key = serialization.load_pem_public_key(public_key.encode(), backend=default_backend())encrypted_data = key.encrypt(shoujihao1.encode(),padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),algorithm=hashes.SHA256(), label=None))# 加密后的数据类型 encrypted_data 字节类型encrypted_data=base64.b64encode(encrypted_data).decode('utf-8')# decode为utf-8之后的数据类型为字符串类型,这样才可以在字符字段中存储# print("decode之后的数据类型")# print(type(encrypted_data))# print(encrypted_data)obj.shoujihao =encrypted_data# -------------------------------------------------------------------------------------if not change:obj.userid = UserProfile.objects.get(user=request.user)else:obj.updated_userid = UserProfile.objects.get(user=request.user)obj.save()super().save_model(request, obj, form, change)# -------------------------------------------------------------------------------------