背景
环境
python 3.7.9
mysql 5.8
centos7
需求
工作需要使用python脚本获取mysql数据库表信息SM2解密、随机生成密码后SM2加密插入数据库
代码
数据库
两个表,一个表存储用户的账户、密码
另一个表存储用户的状态
代码设计
类与函数的定义
一共两个类一个方法。
第一个类是SM2相关功能的封装,里面定义了两个函数:加密、解密(类初始化函数不算)
第二个类是mysql数据的相关操作,定义了四个函数:获取表user_status用户信息、更新表tb_userinfo信息、查询表tb_userinfo信息、初始化表user_status信息
最后,一个方法是随机生成密码,供mysql数据更新密码使用
主函数逻辑
配置SM2的公私钥
配置目标数据
获取表user_status的用户信息判断用户状态是否为“Y”,是则生成随机密码,然后加密插入表tb_userinfo,并将用户的状态重置为"N”,最后再查询表tb_userinfo的用户密码解密,方便校验。
源码
import string
import random
import mysql.connector
from gmssl import sm2
from base64 import b64encode, b64decode
def generate_random_password(length=8):
"""生产随机密码"""
characters = string.ascii_letters + string.digits + string.punctuation
passwd = ''.join(random.choice(characters) for _ in range(length))
return passwd
class sm2_handle():
def __init__(self, SM2_PRIVATE_KEY, SM2_PUBLIC_KEY):
self.sm2_crypt = sm2.CryptSM2(public_key=SM2_PUBLIC_KEY, private_key=SM2_PRIVATE_KEY)
# 加密
def encrypt(self, encrypt_info):
encode_info = self.sm2_crypt.encrypt(encrypt_info.encode(encoding="utf-8"))
encode_info = b64encode(encode_info).decode()
return encode_info
# 解密
def decrypt(self, decrypt_info):
# 通过base64解码成二进制bytes
decode_info = b64decode(decrypt_info.encode())
# 解码并重新将二进制编码转化为字符串
decode_info = self.sm2_crypt.decrypt(decode_info).decode(encoding="utf-8")
return decode_info
class db_operation():
def __init__(self, host='192.168.17.150', username='test', password='12345678', database='arealist'):
"""连接数据库并修改指定用户的密码"""
self.cnx = mysql.connector.connect(
host=host,
user=username,
password=password,
database=database
)
def get_userinfo(self):
cursor = self.cnx.cursor()
try:
select_query = "SELECT * FROM user_status"
cursor.execute(select_query)
# 获取查询结果
results = cursor.fetchall()
# 遍历结果
for row in results:
# 每行数据以元组形式返回,根据列索引获取对应的值
print("username: {}\tStatus: {}".format(row[1], row[2]))
return results
except mysql.connector.Error as err:
print("查询时发生错误:{}".format(err))
finally:
# 关闭游标和数据库连接
cursor.close()
self.cnx.close()
def update_query(self, update_usr, new_password):
# 创建游标对象
cursor = self.cnx.cursor()
try:
# 更新指定用户密码
update_query = "UPDATE tb_pwdict SET password = '{}' WHERE username = '{}'".format(new_password, update_usr)
cursor.execute(update_query)
# 提交更改
self.cnx.commit()
print("用户{}的密码已成功修改成为:{}".format(update_usr, new_password))
except mysql.connector.Error as err:
print("修改密码是发生错误:{}".format(err))
finally:
# 关闭游标和数据库连接
cursor.close()
self.cnx.close()
def select_query(self, select_usr):
# 创建游标对象
cursor = self.cnx.cursor()
results = []
try:
# 查询指定用户密码
select_query = "SELECT username,password FROM tb_pwdict WHERE username = '{}'".format(select_usr)
cursor.execute(select_query)
# 获取查询结果
results = cursor.fetchall()
# 遍历结果
for row in results:
# 每行数据以元组形式返回,根据列索引获取对应的值
print("username:{}\tPasswd:{}".format(row[0], row[1]))
except mysql.connector.Error as err:
print("查询时发生错误:{}".format(err))
finally:
# 关闭游标和数据库连接
cursor.close()
self.cnx.close()
return results
def init_userinfo(self, update_usr):
cursor = self.cnx.cursor()
try:
# 重置用户状态
update_query = "UPDATE user_status SET status = 'N' WHERE username = '{}'".format(update_usr)
cursor.execute(update_query)
# 获取查询结果
self.cnx.commit()
except mysql.connector.Error as err:
print("查询时发生错误:{}".format(err))
finally:
# 关闭游标和数据库连接
cursor.close()
self.cnx.close()
if __name__ == '__main__':
# sm2的公私钥
SM2_PRIVATE_KEY = '00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'
SM2_PUBLIC_KEY = 'B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'
# 数据库处理
host = '192.168.17.150'
username = 'test'
password = "12345678"
database = 'arealist'
# 获取用户列表信息(特权用户状态‘N’代表特权用户未使用,‘Y’代表特权用户已经使用过)
db1 = db_operation()
userinfo = db1.get_userinfo()
for usrinfo in userinfo:
if usrinfo[2] == 'Y':
# 生成随机密码
pw = generate_random_password()
# 密码SM2加密
sm2_ins = sm2_handle(SM2_PRIVATE_KEY, SM2_PUBLIC_KEY)
new_pw = sm2_ins.encrypt(pw)
# 数据库更新密码并重置用户状态为’N‘
update_usr = usrinfo[1]
db2 = db_operation()
db2.update_query(update_usr, new_pw)
db3 = db_operation()
db3.init_userinfo(update_usr)
print("更新的用户:{}\t加密密码:{}\t未加密密码:{}".format(update_usr, new_pw, pw))
# 获取用户密码并解密
db4 = db_operation()
rs = db4.select_query(usrinfo[1])
orig_pw = rs[0][1]
print("original passwd: ", sm2_ins.decrypt(orig_pw))