Skip to content

PostgreSQL 透明数据加密

pgcrypto 扩展实现

pgcrypto 扩展简介

pgcrypto是PostgreSQL的官方扩展,提供了数据加密、哈希和签名功能。虽然它不是真正的TDE,但可以用于实现列级或行级加密。

安装和启用 pgcrypto

bash
# 安装 pgcrypto 扩展(如果未安装)
# 在Debian/Ubuntu上
sudo apt-get install postgresql-<version>-pgcrypto

# 在RHEL/CentOS上
sudo yum install postgresql<version>-contrib

# 在PostgreSQL中创建扩展
psql -c "CREATE EXTENSION IF NOT EXISTS pgcrypto;"

使用 pgcrypto 进行列级加密

sql
-- 创建带加密列的表
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    password_hash BYTEA NOT NULL,
    sensitive_data BYTEA NOT NULL
);

-- 插入数据时加密
INSERT INTO users (username, password_hash, sensitive_data)
VALUES (
    'admin',
    crypt('password123', gen_salt('bf')),
    pgp_sym_encrypt('sensitive information', 'encryption_key')
);

-- 查询数据时解密
SELECT 
    id, 
    username,
    pgp_sym_decrypt(sensitive_data, 'encryption_key') AS sensitive_data
FROM users;

pgcrypto 的局限性

  • 不是真正的透明加密,需要修改SQL语句
  • 加密解密操作消耗CPU资源
  • 不支持索引加密
  • 管理密钥困难
  • 无法防止特权用户访问

pgsodium 扩展实现

pgsodium 扩展简介

pgsodium是基于libsodium库的PostgreSQL扩展,提供了更现代、更安全的加密功能,支持透明数据加密。

安装和启用 pgsodium

bash
# 安装依赖
# 在Debian/Ubuntu上
sudo apt-get install libsodium-dev

# 在RHEL/CentOS上
sudo yum install libsodium-devel

# 编译安装 pgsodium
# 从GitHub克隆源代码
git clone https://github.com/michelp/pgsodium.git
cd pgsodium
make && sudo make install

# 在PostgreSQL中创建扩展
psql -c "CREATE EXTENSION IF NOT EXISTS pgsodium;"

使用 pgsodium 进行透明数据加密

sql
-- 生成主密钥
SELECT pgsodium.create_key();

-- 创建加密表
CREATE TABLE sensitive_data (
    id SERIAL PRIMARY KEY,
    data TEXT
) WITH (
    encryption = 'pgsodium'
);

-- 插入数据(自动加密)
INSERT INTO sensitive_data (data) VALUES ('sensitive information');

-- 查询数据(自动解密)
SELECT * FROM sensitive_data;

pgsodium 的优势

  • 基于现代加密库libsodium
  • 支持透明数据加密
  • 提供多种加密算法
  • 支持密钥管理
  • 性能优于pgcrypto

pg_tde 扩展实现(PostgreSQL 14+)

pg_tde 扩展简介

pg_tde是PostgreSQL 14及以上版本的TDE扩展,提供了完整的透明数据加密功能,支持数据文件、WAL文件和临时文件的加密。

安装和配置 pg_tde

bash
# 从GitHub克隆源代码
git clone https://github.com/EnterpriseDB/pg_tde.git
cd pg_tde

# 编译安装
gmake PG_CONFIG=/path/to/pg_config
gmake PG_CONFIG=/path/to/pg_config install

配置 pg_tde

  1. 修改 postgresql.conf
txt
# 启用 pg_tde 扩展
shared_preload_libraries = 'pg_tde'

# 配置加密算法
pg_tde.cipher = 'aes-256-cbc'

# 配置密钥管理
pg_tde.key_provider = 'file'
pg_tde.key_file = '/path/to/keyfile'
  1. 初始化密钥
bash
# 生成主密钥
pg_tde_keygen -f /path/to/keyfile -a aes-256-cbc

# 设置密钥文件权限
chmod 600 /path/to/keyfile
chown postgres:postgres /path/to/keyfile
  1. 重启 PostgreSQL
bash
sudo systemctl restart postgresql
  1. 创建加密表空间
sql
-- 创建加密表空间
CREATE TABLESPACE encrypted_ts 
    LOCATION '/path/to/encrypted_ts' 
    WITH (encryption = 'on');

-- 在加密表空间中创建表
CREATE TABLE encrypted_table (
    id SERIAL PRIMARY KEY,
    data TEXT
) TABLESPACE encrypted_ts;

pg_tde 版本支持

PostgreSQL 版本pg_tde 支持情况
14.x支持
15.x支持
16.x支持
17.x支持

云服务提供商的 TDE 支持

AWS RDS PostgreSQL

  • TDE 实现:使用AWS Key Management Service (KMS) 管理密钥
  • 加密范围:数据文件、备份、只读副本和快照
  • 配置方法:创建DB实例时启用加密选项
  • 密钥管理:支持AWS KMS密钥轮换

Azure Database for PostgreSQL

  • TDE 实现:使用Azure Key Vault管理密钥
  • 加密范围:数据文件、备份、复制链接和异地备份
  • 配置方法:在服务器安全设置中启用TDE
  • 密钥类型:支持服务管理密钥和客户管理密钥

Google Cloud SQL for PostgreSQL

  • TDE 实现:使用Google Cloud KMS管理密钥
  • 加密范围:数据文件、备份和复制
  • 配置方法:自动启用,无需手动配置
  • 密钥管理:支持客户管理加密密钥 (CMEK)

TDE 性能影响

性能开销因素

  • 加密算法:AES-256比AES-128开销大
  • IO 模式:随机IO比顺序IO影响更大
  • 硬件配置:CPU性能、存储类型和网络带宽
  • 工作负载:写入密集型工作负载影响更大
  • 加密范围:全库加密比表空间加密开销大

性能测试结果

  • CPU 使用率:增加5%-15%的CPU开销
  • IOPS:降低5%-10%的IOPS
  • 延迟:增加10%-20%的延迟
  • 吞吐量:降低5%-15%的吞吐量

性能优化建议

  • 选择合适的加密算法:根据安全需求和性能要求选择AES-128或AES-256
  • 使用高性能存储:SSD或NVMe存储可以缓解TDE的性能影响
  • 优化硬件配置:增加CPU核心数,提高CPU频率
  • 分区表优化:将热点数据和冷数据分离,只加密敏感数据
  • 合理配置缓存:增加shared_buffers和effective_cache_size

TDE 最佳实践

密钥管理

  • 密钥轮换策略:定期轮换主密钥和数据加密密钥
  • 密钥备份:将密钥备份到安全的离线位置
  • 密钥访问控制:限制密钥的访问权限,仅允许授权用户访问
  • 密钥审计:记录密钥的使用和变更日志
  • 密钥生命周期管理:建立密钥的创建、使用、轮换和销毁流程

部署架构

  • 分层密钥架构:使用主密钥加密数据加密密钥,避免直接使用主密钥加密数据
  • 物理隔离:将密钥存储在与数据库服务器物理隔离的位置
  • 多区域部署:在不同区域部署密钥管理服务,提高可用性
  • 灾难恢复:确保密钥管理服务有足够的冗余和恢复机制

安全考虑

  • 特权用户访问:TDE无法防止数据库管理员或超级用户访问明文数据
  • 内存中的数据:TDE仅加密磁盘上的数据,内存中的数据仍为明文
  • 网络传输:TDE不加密网络传输中的数据,需要配合SSL/TLS使用
  • 备份加密:确保备份数据也被加密,避免数据泄露
  • 审计日志:启用审计日志,记录数据访问和密钥使用情况

监控和维护

  • 监控加密状态:定期检查数据库和表空间的加密状态
  • 监控性能指标:跟踪CPU使用率、IOPS和延迟等性能指标
  • 定期测试解密:确保密钥可以正常解密数据
  • 更新扩展:及时更新TDE扩展和PostgreSQL版本
  • 制定应急计划:建立密钥丢失或损坏的应急恢复计划

TDE 与其他加密方式的比较

加密方式实现方式透明性加密范围性能开销适用场景
TDE数据库级加密完全透明数据文件、索引、WAL中等全库加密需求
列级加密pgcrypto 扩展需修改SQL特定列敏感列加密
应用层加密应用代码实现不透明应用层端到端加密
文件系统加密操作系统级透明整个文件系统简单加密需求

常见问题(FAQ)

Q1: PostgreSQL 社区版支持原生TDE吗?

A1: 截至PostgreSQL 17,社区版尚未内置原生TDE支持。但可以通过第三方扩展如pg_tde、pgsodium或商业解决方案实现TDE功能。PostgreSQL社区正在积极开发原生TDE功能,预计未来版本会提供支持。

Q2: TDE 会影响备份和恢复吗?

A2: TDE对备份和恢复过程有以下影响:

  • 备份文件会自动加密,恢复时需要相应的密钥
  • 逻辑备份(如pg_dump)导出的是明文数据,需要单独加密
  • 物理备份(如pg_basebackup)会保留加密状态
  • 恢复时需要确保密钥可用,否则无法恢复数据

Q3: 如何迁移使用TDE的数据库?

A3: 迁移使用TDE的数据库需要注意:

  • 确保目标服务器已配置相同的TDE扩展和密钥管理
  • 迁移密钥或生成新密钥并重新加密数据
  • 使用物理备份迁移时,需要确保密钥一致
  • 使用逻辑备份迁移时,目标服务器需要重新配置TDE

Q4: TDE 可以防止SQL注入攻击吗?

A4: TDE不能防止SQL注入攻击。TDE仅加密磁盘上的数据,而SQL注入攻击发生在数据库处理SQL语句时,此时数据已在内存中解密。防止SQL注入需要使用参数化查询、输入验证和最小权限原则。

Q5: 如何测试TDE是否正常工作?

A5: 可以通过以下方法测试TDE:

  • 使用hex编辑器查看数据文件,确认内容已加密
  • 尝试在没有密钥的情况下启动数据库,确认无法访问数据
  • 检查数据库日志,确认TDE已成功加载和配置
  • 使用pg_controldata命令查看数据库的加密状态

Q6: TDE 对复制有什么影响?

A6: TDE对复制的影响:

  • 主从复制:从服务器需要相同的TDE配置和密钥
  • 逻辑复制:复制的数据是明文,需要在目标服务器重新加密
  • 流复制:WAL文件已加密,从服务器需要解密才能应用
  • 跨版本复制:需要确保TDE扩展版本兼容

Q7: 如何处理密钥丢失的情况?

A7: 密钥丢失是严重问题,可能导致数据永久丢失。处理方法:

  • 立即使用备份密钥恢复
  • 如果没有备份密钥,数据将无法恢复
  • 建立密钥备份和恢复流程,避免密钥丢失

Q8: TDE 支持哪些加密算法?

A8: 不同的TDE实现支持不同的加密算法:

  • pgcrypto:支持AES、DES、3DES、Blowfish等
  • pgsodium:支持ChaCha20、AES-GCM等
  • pg_tde:支持AES-128、AES-192、AES-256
  • 云服务提供商:通常支持AES-256

Q9: TDE 可以和其他安全功能结合使用吗?

A9: 是的,TDE可以与其他安全功能结合使用:

  • SSL/TLS:加密网络传输数据
  • 行级安全性(RLS):限制数据访问权限
  • 审计日志:记录数据访问和操作
  • 最小权限原则:限制用户权限
  • 数据掩码:屏蔽敏感数据

Q10: 如何评估是否需要使用TDE?

A10: 评估是否需要TDE的考虑因素:

  • 数据敏感性:是否包含敏感数据如个人信息、财务数据
  • 合规要求:是否需要满足GDPR、HIPAA等合规要求
  • 性能影响:应用是否能承受TDE带来的性能开销
  • 管理成本:是否有足够的资源管理密钥和TDE配置
  • 安全需求:是否需要防止物理磁盘被盗导致的数据泄露

TDE 配置示例

使用 pgsodium 配置 TDE

sql
-- 1. 创建扩展
CREATE EXTENSION IF NOT EXISTS pgsodium;

-- 2. 生成主密钥
SELECT pgsodium.create_key();

-- 3. 创建加密表空间
CREATE TABLESPACE encrypted_ts 
    LOCATION '/var/lib/postgresql/15/encrypted_ts';

-- 4. 加密表空间
SELECT pgsodium.encrypt_tablespace('encrypted_ts');

-- 5. 创建加密表
CREATE TABLE sensitive_data (
    id SERIAL PRIMARY KEY,
    data TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) TABLESPACE encrypted_ts;

-- 6. 插入测试数据
INSERT INTO sensitive_data (data) VALUES 
    ('sensitive information 1'),
    ('sensitive information 2'),
    ('sensitive information 3');

-- 7. 查询测试数据
SELECT * FROM sensitive_data;

检查加密状态

sql
-- 检查表空间加密状态
SELECT 
    spcname, 
    pg_tablespace_location(oid) as location,
    pgsodium.is_tablespace_encrypted(oid) as is_encrypted
FROM pg_tablespace;

-- 检查表的加密状态
SELECT 
    relname, 
    tablespace,
    pgsodium.is_table_encrypted(oid) as is_encrypted
FROM pg_class
WHERE relname = 'sensitive_data';

性能测试示例

使用 pgbench 测试 TDE 性能

bash
# 创建测试数据库
createdb pgbench_test

# 初始化 pgbench 测试数据
pgbench -i -s 10 pgbench_test

# 测试未加密数据库性能
pgbench -c 10 -j 4 -t 10000 pgbench_test

# 启用 TDE 并创建加密表空间
psql -d pgbench_test -c "CREATE TABLESPACE encrypted_ts LOCATION '/var/lib/postgresql/15/encrypted_ts'"
psql -d pgbench_test -c "SELECT pgsodium.encrypt_tablespace('encrypted_ts')"

# 迁移测试数据到加密表空间
psql -d pgbench_test -c "ALTER TABLE pgbench_accounts SET TABLESPACE encrypted_ts"
psql -d pgbench_test -c "ALTER TABLE pgbench_branches SET TABLESPACE encrypted_ts"
psql -d pgbench_test -c "ALTER TABLE pgbench_history SET TABLESPACE encrypted_ts"
psql -d pgbench_test -c "ALTER TABLE pgbench_tellers SET TABLESPACE encrypted_ts"

# 测试加密数据库性能
pgbench -c 10 -j 4 -t 10000 pgbench_test