大数据安全技术实验:数据加密存储与细粒度访问控制
实验概述
实验场景:模拟某企业员工信息存储系统,需对员工敏感数据(手机号、家庭地址、薪资)进行加密存储,并为不同部门人员分配不同访问权限。
一、文件加密(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
登录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),表级防"物"(磁盘失窃)。
访问控制是数据安全的守门员:即使加密被破解,无授权用户依然无法访问;即使账号被盗,最小权限限制攻击范围。实验中的"加密+权限"组合,构建了纵深防御体系,是等保合规与数据安全法落地的核心技术手段。
更多推荐
所有评论(0)