python进行SM2加密解密及mysql数据库交互

背景

环境

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))









  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值