实验概述

实验场景:模拟某企业员工信息存储系统,需对员工敏感数据(手机号、家庭地址、薪资)进行加密存储,并为不同部门人员分配不同访问权限。

一、文件加密(AES-256-CBC)

重点:防物理窃取

  • 密钥生成:密码经PBKDF2万次迭代+随机盐值派生256位密钥,盐值与密文同存,确保相同密码加密结果不同
  • 加密过程:文件分16字节块,每块与前一密文块链接(CBC模式),末尾用PKCS7填充
  • 安全价值:密钥正确才可逆,无认证机制时错误密钥会静默生成损坏文件(需HMAC防范)

二、数据库字段加密(MySQL内置)

重点:防DBA窥探

  • 函数机制AES_ENCRYPT()将手机号/地址等敏感字段加密为二进制VARBINARY类型存储,密钥由应用层传递
  • 字段设计:密文长度=原文+填充,需预留充足存储空间(如phone用VARBINARY(128))
  • 安全价值:数据库文件被盗后,无密钥无法解密;权限控制可阻止未授权用户调用解密函数

三、访问控制模型(列级权限)

重点:防内部越权

  • 模型结构:用户→角色→权限,MySQL通过mysql.columns_priv表实现列级SELECT控制
  • 权限分配:hr_read仅授(id,name,phone,address)查询权,hr_write授全表DML权,sys_admin授数据库DDL权
  • 安全价值:即使知道解密密钥,无列权限也无法查询薪资;职责分离确保最小权限原则

综合纵深防御

文件加密(防外部)+ 字段加密(防内部)+ 访问控制(防越权)= 存储阶段完整保护链

实验步骤,实验结果与问题解决

模块一:文件加密存储(AES-256-CBC)

步骤1:安装加密依赖库

执行pip install pycryptodome(AES加密库)。

步骤2:编写AES文件加密脚本

新建Python脚本aes_file_encrypt.py,代码如下:

from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Random import get_random_bytes
import os

BLOCK_SIZE = 16
SALT_SIZE = 16
ITERATIONS = 10000

def derive_key(password, salt):
    """从密码派生AES密钥(256位)"""
    return PBKDF2(password, salt, dkLen=32, count=ITERATIONS)

def encrypt_file(input_path, output_path, password):
    """加密文件"""
    # 生成盐值和初始化向量
    salt = get_random_bytes(SALT_SIZE)
    iv = get_random_bytes(BLOCK_SIZE)
    
    # 派生密钥
    key = derive_key(password, salt)
    
    # 创建AES加密器
    cipher = AES.new(key, AES.MODE_CBC, iv)
    
    # 读取文件内容并填充(PKCS7填充)
    with open(input_path, "rb") as f:
        data = f.read()
    padding = BLOCK_SIZE - (len(data) % BLOCK_SIZE)
    data += bytes([padding]) * padding
    
    # 加密数据
    encrypted_data = cipher.encrypt(data)
    
    # 保存加密文件(盐值+IV+密文)
    with open(output_path, "wb") as f:
        f.write(salt + iv + encrypted_data)
    
    print(f"文件加密完成!加密文件已保存至:{output_path}")

if __name__ == "__main__":
    # 配置路径和密码
    input_file = "D:/data_security/exp2/employee_info.xlsx"
    output_file = "D:/data_security/exp2/employee_info_encrypted.aes"
    password = "CC@2025"
    
    encrypt_file(input_file, output_file, password)


步骤3:编写AES文件解密脚本

  • 新建Python脚本aes_file_decrypt.py,代码如下:
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
import os

BLOCK_SIZE = 16
SALT_SIZE = 16
ITERATIONS = 10000

def derive_key(password, salt):
    return PBKDF2(password, salt, dkLen=32, count=ITERATIONS)

def decrypt_file(input_path, output_path, password):
    """解密文件"""
    # 读取加密文件(盐值+IV+密文)
    with open(input_path, "rb") as f:
        salt = f.read(SALT_SIZE)
        iv = f.read(BLOCK_SIZE)
        encrypted_data = f.read()
    
    # 派生密钥
    key = derive_key(password, salt)
    
    # 创建AES解密器
    cipher = AES.new(key, AES.MODE_CBC, iv)
    
    # 解密并去除填充
    decrypted_data = cipher.decrypt(encrypted_data)
    padding = decrypted_data[-1]
    decrypted_data = decrypted_data[:-padding]
    
    # 保存解密文件
    with open(output_path, "wb") as f:
        f.write(decrypted_data)
    
    print(f"文件解密完成!解密文件已保存至:{output_path}")

if __name__ == "__main__":
    input_file = "D:/data_security/exp2/employee_info_encrypted.aes"
    output_file = "D:/data_security/exp2/employee_info_decrypted.xlsx"
    password = "DataSec@2024"
    
    try:
        decrypt_file(input_file, output_file, password)
    except Exception as e:
        print(f"解密失败:{str(e)}(可能是密码错误或文件损坏)")


步骤4:验证文件加密效果

准备employee_info.xlsx文件,包含员工姓名、手机号、家庭地址、薪资等字段;

运行加密脚本,生成employee_info_encrypted.aes(二进制密文文件);

尝试用Excel打开加密文件,无法识别(验证加密有效性);

运行解密脚本,输入正确密码,成功恢复原始文件;

检验内容

输入错误密码,观察解密失败提示。

模块二:MySQL数据库字段级加密存储

步骤1:CentOS 7服务器安装配置MySQL 8.0

A06-Xshell使用教程 - 教程合集 - 八方网域

登录Xshell连接CentOS 7服务器

执行以下命令安装MySQL:

安装依赖

yum install -y wget

下载MySQL仓库

wget https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm

因为使用NAT模式无法解析DNS

我们世界使用ssh传输

安装仓库

rpm -ivh mysql80-community-release-el7-3.noarch.rpm

安装MySQL

yum install -y mysql-community-server

所有 yum 官方源都需要 DNS,但你的 DNS 出口被封,所以即使 MySQL repo 安装成功了,yum 也无法解析。

我们直接使用MySQL 官方已经提供的离线安装包

解压 RPM 包

cd /root
tar -xvf mysql-8.0.39-1.el7.x86_64.rpm-bundle.tar

按顺序安装所有依赖包

rpm -ivh mysql-community-common-8.0.39-1.el7.x86_64.rpm
rpm -ivh mysql-community-client-plugins-8.0.39-1.el7.x86_64.rpm
rpm -ivh mysql-community-libs-8.0.39-1.el7.x86_64.rpm
rpm -ivh mysql-community-client-8.0.39-1.el7.x86_64.rpm
rpm -ivh mysql-community-icu-data-files-8.0.39-1.el7.x86_64.rpm
rpm -ivh mysql-community-server-8.0.39-1.el7.x86_64.rpm

简化版一键安装

rpm -ivh mysql-community-*.{rpm,el7.x86_64.rpm} --force --nodeps *# 或更精确:*

rpm -ivh mysql-community-{common,client-plugins,libs,client,icu-data-files,server}-8.0.39-1.el7.x86_64.rpm

报错处理MySQL与MariaDB库冲突,先卸载MariaDB

重新安装尝试

启动MySQL服务

systemctl start mysqld

查看初始密码

grep "temporary password" /var/log/mysqld.log

e?Y#*i_Pr6sH

登录MySQL并修改root密码:

mysql -u root -p  # 输入初始密码

ALTER USER 'root'@'localhost' IDENTIFIED BY 'MySql@CC2025'; FLUSH PRIVILEGES;


步骤2:创建加密存储表并插入数据

执行建表语句(敏感字段加密存储):

创建数据库

CREATE DATABASE employee_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

使用数据库

USE employee_db;

创建员工表(敏感字段加密)

CREATE TABLE employee ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) NOT NULL, phone VARBINARY(128) NOT NULL, address VARBINARY(256) NOT NULL, salary VARBINARY(64) NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP );


插入加密数据(密钥:EmpSecKey2024):

INSERT INTO employee (name, phone, address, salary) VALUES ('张三', AES_ENCRYPT('13800138000', 'EmpSecKey2024'), AES_ENCRYPT('北京市朝阳区建国路88号现代城A座1001室', 'EmpSecKey2024'), AES_ENCRYPT('15000', 'EmpSecKey2024')), ('李四', AES_ENCRYPT('13900139000', 'EmpSecKey2024'), AES_ENCRYPT('上海市浦东新区陆家嘴金融中心银城中路200号', 'EmpSecKey2024'), AES_ENCRYPT('18000', 'EmpSecKey2024')), ('王五', AES_ENCRYPT('13700137000', 'EmpSecKey2024'), AES_ENCRYPT('广州市天河区珠江新城花城大道68号', 'EmpSecKey2024'), AES_ENCRYPT('16000', 'EmpSecKey2024')), ('赵六', AES_ENCRYPT('13600136000', 'EmpSecKey2024'), AES_ENCRYPT('深圳市南山区科技园南区高新南一道', 'EmpSecKey2024'), AES_ENCRYPT('12000', 'EmpSecKey2024'));


查询原始数据(显示密文):

SELECT * FROM employee;  # phone、address、salary字段为二进制密文


查询解密数据(验证加密有效性):

USE employee_db;

SELECT id, name, CAST(AES_DECRYPT(phone, 'EmpSecKey2024') AS CHAR) AS phone, CAST(AES_DECRYPT(address, 'EmpSecKey2024') AS CHAR) AS address, CAST(AES_DECRYPT(salary, 'EmpSecKey2024') AS CHAR) AS salary, create_time FROM employee;


模块三:MySQL细粒度访问控制配置

步骤1:创建不同角色用户

登录MySQL(root用户),创建3个用户分别对应不同权限:

  • 只读用户(人力资源专员,只能查询非薪资字段)

CREATE USER IF NOT EXISTS 'hr_read'@'%' IDENTIFIED BY 'HrRead@123';

  • 读写用户(人力资源主管,可查询所有字段,可增删改员工信息)

CREATE USER IF NOT EXISTS 'hr_write'@'%' IDENTIFIED BY 'HrWrite@123';

  • 管理员用户(系统管理员,拥有所有权限)

CREATE USER IF NOT EXISTS 'sys_admin'@'%' IDENTIFIED BY 'SysAdmin@123';


步骤2:分配权限

为只读用户hr_read分配权限(仅查询非薪资字段):

GRANT SELECT (id, name, phone, address) ON employee_db.employee TO 'hr_read'@'%';


为读写用户hr_write分配权限(增删改查所有字段):

GRANT SELECT, INSERT, UPDATE, DELETE ON employee_db.employee TO 'hr_write'@'%';


为管理员用户sys_admin分配所有权限:

GRANT ALL PRIVILEGES ON employee_db.* TO 'sys_admin'@'%';


刷新权限:

FLUSH PRIVILEGES;


步骤3:验证访问控制有效性

用hr_read用户登录Navicat:

验证1:查询授权字段

  • SELECT id, name, phone, address FROM employee_db.employee;

预期结果:返回4条记录,phone和address显示为密文.

验证2:查询未授权字段

SELECT salary FROM employee_db.employee;

预期结果:报错

验证3:解密查询授权字段

SELECT id, name, CAST(AES_DECRYPT(phone, 'EmpSecKey2024') AS CHAR) AS phone_decrypted FROM employee_db.employee;

预期结果:phone显示为明文手机号

验证4:尝试插入数据

INSERT INTO employee_db.employee (name) VALUES ('测试');

预期结果:报错

用hr_write用户登录Navicat:

验证薪资字段解密查询

SELECT name, CAST(AES_DECRYPT(salary, 'EmpSecKey2024') AS CHAR) AS salary_decrypted FROM employee_db.employee;

预期结果:返回4条记录,正确显示薪资明文(15000, 18000, 16000, 12000)

验证更新加密字段操作

UPDATE employee_db.employee SET phone = AES_ENCRYPT('13600136000', 'EmpSecKey2024') WHERE name = '张三';

验证更新结果

SELECT name, CAST(AES_DECRYPT(phone, 'EmpSecKey2024') AS CHAR) AS phone_updated FROM employee_db.employee WHERE name = '张三';

用sys_admin用户登录Navicat:

验证数据库级操作权限

CREATE TABLE employee_db.test_table ( id INT PRIMARY KEY, test_data VARCHAR(50) );

验证表创建成功

SHOW TABLES FROM employee_db;

验证用户管理权限

删除用户(验证系统管理权限)

DROP USER 'hr_read'@'%'; *验证用户已删除*SELECT user, host FROM mysql.user WHERE user = 'hr_read';

恢复hr_read用户

删除后立即重建hr_read用户

CREATE USER 'hr_read'@'%' IDENTIFIED BY 'HrRead@123'; GRANT SELECT (id, name, phone, address) ON employee_db.employee TO 'hr_read'@'%'; FLUSH PRIVILEGES;

实验思考

字段级加密适用于精细化数据保护(如薪资字段单独加密),而表级加密适用于大规模全盘防护(如整库存储加密)。二者互补,字段级防"人"(DBA),表级防"物"(磁盘失窃)。

访问控制是数据安全的守门员:即使加密被破解,无授权用户依然无法访问;即使账号被盗,最小权限限制攻击范围。实验中的"加密+权限"组合,构建了纵深防御体系,是等保合规与数据安全法落地的核心技术手段。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐