需求:
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
# 方法一
# pip install rsa
import rsa
# 生成公钥和私钥
# 使用rsa插件生成2048位加密
# 公钥 public_key
# 私钥 private_key
(public_key, private_key) = rsa.newkeys(2048)
# # # 将公钥和私钥保存到本地文件
# 导出公钥和私钥到文件
with open('public_key.pem', mode='wb') as public_file:
public_file.write(public_key.save_pkcs1('PEM'))
with open('private_key.pem', mode='wb') as private_file:
private_file.write(private_key.save_pkcs1('PEM'))
方法二
安装cryptography生成加密,会比仅用rsa快一点
pip install cryptography
#安装cryptography会自动安装cryptography,cffi,pycparser
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import 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的相同路径中创建了公钥和私钥的文件
#生成私钥如下
# -----BEGIN RSA PRIVATE KEY-----
# MIIEqQIBAAKCAQEAjItx/es/uoRA8OsH/1S5l6jYX/lTjJVsm3RId169zZTMwkq1
# 8sxFM1v/k1pLeHXokoTa5h6VWFQBgdNV7siGF5Jesrp3cDJQawj32Um31cwBiPGw
# pQlW8q68uz4jbCu9AGFOPQMQrVF3KTNHv8YFJt83Ug5ByxGbpoopA3cZJi1la0LM
# A2QFHgolgGooiIbn8+MP6B8ovk05aKnZJwQvthIp7F+73CEEfC0alLkn5+cPMD+Y
# 5zuCCUwVKZWpQierQIy6Shxu/gQ1zoB0Jnycl2pTR7hJ4hiWxKSz8aPzv5h4+ZGh
# 2Ou3FdaFTnL85fLbrSsugqS8bGV6teR4QPoVqwIDAQABAoIBAGD4baRGxmfIjI4t
# fA0dxhfv9aryekULbC4uIznJcqf/vO9pYPSvICf5l/NxX5UztU4ywF36SAzzmT6c
# NDRWwr5MzW3/3hzZekb/nxKbHG41HfIA4GJeeVFkYu/GReaCnxs+CB9sl/sdtFwG
# 98BHvpI9fQvurlKQSRYIXaoeiWYzsBKxBq4rCgpcgd3wYqhu9QrlhLbUDfF0Vr97
# UK6sqckJ01rV1UFSNK5UpBGRNQ/UrLKYjxxIYnDqjTf7UofOzuaeLfTMHy5+o4mB
# Pkh911h/pC/cCePlhcvz07GGyslntscoi/HCK5TLdaFBkeyVttN9Agxxl3siG6ux
# 1rQ2r1ECgYkAun5oomGfEo9Tmxr6TlDqwg3aeD62vgVxjJ5DRHJ832nsfA+VI9uQ
# iD951AntPURLQdAFIr2W6146KyIBPGo/kS/cT29gbutDI9ws90AT7KySBs2E2jjH
# 8hUxrXSdxVZTEdWFpkRUSj9i+N49uoT4HLHncgWJ1BkXYibTG5QcLyaYq39AL2GO
# ZwJ5AMDs+y5OSf4hgUNUYGl3J2X3RG8lpPG/kHKn6onekWni7WIEr6bD8fAPaptv
# 5XkYYsWxB9iG7MupCnzTX4IONy9ALs0UoY9STkPWV4l9qoOMatH9rW1jyRQD28Tp
# qNuAGlYBPQFaqv7I5QhJ6Wqe94tGMWfX+2rsHQKBiQCz1/NPpJSicVVO3lVD8QRy
# 3qkwDEpuNRGraXO1LjL9wEgt21kXm0VmHtB9ipUd4B4y+Uf6mJpRoCy4K7LFcDCc
# 8mqir+VvEbFNg6ZZSZHtSv4HUWosh1VKPuYJP8xl4Tl6mU6paHtgnn/zP16H4HLk
# OSvY6T5hK1FBde9fSRVk4vOXbr+W8Z1BAnhgzwoD5HkwsrNgi9iNU6NLgVavx14L
# iSr8vdHtOOgTEDI6O0vBDRY8dh/yu6WUrG3z8a+UMbBlSf/fP1nvsx5x8W0Kr82a
# U5y+YbIvZgXIWQ/JK9h4yde+2WjQWMfIzXFpstlf8pVXoIt9K0mbnQVut9xW1YRt
# 1OkCgYgkkw7Tlf0ASZ5mkpy07MplV6h2umoP2IgDtZWzVJBqI1fbvKuqHgCr/0w+
# wlWF/fOGnKdjIO1EWUJ6RRYC10V57iSHUhncv0X0OxlbedFtuo0UX0FfpYbJNkzU
# PhQ4uT1geCltZZwRMAMSKERUErCRKkwuxOIUx9bZ4NsXABhDzegcNh66nimE
# -----END RSA PRIVATE KEY-----
# 生成公钥如下
# -----BEGIN RSA PUBLIC KEY-----
# MIIBCgKCAQEAjItx/es/uoRA8OsH/1S5l6jYX/lTjJVsm3RId169zZTMwkq18sxF
# M1v/k1pLeHXokoTa5h6VWFQBgdNV7siGF5Jesrp3cDJQawj32Um31cwBiPGwpQlW
# 8q68uz4jbCu9AGFOPQMQrVF3KTNHv8YFJt83Ug5ByxGbpoopA3cZJi1la0LMA2QF
# HgolgGooiIbn8+MP6B8ovk05aKnZJwQvthIp7F+73CEEfC0alLkn5+cPMD+Y5zuC
# CUwVKZWpQierQIy6Shxu/gQ1zoB0Jnycl2pTR7hJ4hiWxKSz8aPzv5h4+ZGh2Ou3
# FdaFTnL85fLbrSsugqS8bGV6teR4QPoVqwIDAQAB
# -----END RSA PUBLIC KEY-----
3安装读取加密插件
pip install cryptography
4:在django项目中应用
models.py文件中代码如下
# -------------------------------------------------------------------------------------
# 手机号加密插件
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
import 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:返回c
if len(self.shoujihao)>=20:
shoujihao1=self.shoujihao
shoujihao1 = base64.b64decode(shoujihao1)
# 读取私钥文件
private_key="""-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAp4vQEgBPcCy09xmJDVFxjuYk+USqBNgUxIHF4+E9Vot1rDWU
ncFSIERsEqTq9wIlVsgiVtRJ/0FxHLIgZPlFvRRUh0JjxkpddYAK+EKK2gySoiE8
kUwomeYpILg/pAxtSoRBbUqtE/sTQZM2sOM07FYrz/Q8oVBN1Au3/LwOOAFf6R/5
lFBJCutS/wAuvydwxlTjuNp4PF4Tc65qaF+35VE0IvcOByahAPRqI4TqFb/UOidJ
1Xc4HPIwmtkeYYRyqDgZun2tdQ0iQm7A7lN9TkP6qoKbTRI9ySoBHs4SJXy8r63r
xPRgkjEsVR/hcsZAt7LHjNnZKWd8b1yi0AO56QIDAQABAoIBABya/xUXtvheta3r
ju32bgY5Dm59le6aSt9rDbOUuPF+AYL7qepOP5yROgdr3075b5ETveMnvxOE45BD
7Ep5EbpQzobCY8EO4MqHKDhPOiA03dMvDAV9pH/0Hyj+NCVo1r8OehI0Gf1LlHPR
c9i7DgXcx4GrgC+Fg6g0sP7GR8IxWKkT1rHNWWjqaWh3HlBbJhdrZpxjKbCqTjKM
ImrgPKDi1An0NNHJyQe42XNgmOAMoCRUvP8skLveyYDQ2+LCeTjnmOD0WTMlwlt3
ulu4MjKh/wMAj7dxguonK97C01n0utP+k0KdkOP+rBNazEF2roY2FrcYr+n1MgTs
QDECG1JVtYVP1Tuyb3pgoQKBgC9SV/Ft1K4T8e/AiTrF07SCn8BEZOZ0BDI69+lB
cYh1CPXBt1M0a+T+M1mwCVWxYrapfVismesnIiVQO+n2AehdDyvE1krkHRTQCUYD
PkM7efPek9WBWHy6dbEPJ+mMDs1P5mVOV7MJEGQMtE01BO/KoQ74fePrbaFDwHkU
nzuBAoGBAJIpUUmDMnkMzr5HPw1rtZEjkR0k+EQXU3jeaKA1TjqRoli1ApUpBB11
ekDfPc/BqzRSIkACEijwdnf7NhQveCAiE+aj5NiGkwS/zjX9S96v0qK5SFil6y+c
EXv1GMN54aCmiHWBGq86tOKjV9M4hnlVpuRJPeHi52nAyHpJfmB7
-----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_data
print("类型")
print(type(decrypted_data))
print(decrypted_data)
# 打印解密后的消息
color_code = 'green'
return format_html('<span style="color:{};">{}</span>', color_code, shoujihao1)
else:
color_code = 'green'
return format_html('<span style="color:{};">-</span>', color_code, )
get_shoujihao.short_description = '手机号'
admin.py文件中代码如下
# -------------------------------------------------------------------------------------
# 手机号加密插件
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
import 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.shoujihao
if len(shoujihao1) == 11:
# 1:在admin后台中,允许用户输入的是字符串类型的数据
# 2:加密之后得到的是字节类型,
# 3:把字节类型的编码为utf-8的字符串类型 存储在数据库中
# 读取公钥文件
public_key = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp4vQEgBPcCy09xmJDVFx
juYk+USqBNgUxIHF4+E9Vot1rDWUncFSIERsEqTq9wIlVsgiVtRJ/0FxHLIgZPlF
TkP6qoKbTRI9ySoBHs4SJXy8r63rxPRgkjEsVR/hcsZAt7LHjNnZKWd8b1yi0AO5
6QIDAQAB
-----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 <class 'bytes'> 字节类型
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)
# -------------------------------------------------------------------------------------