1 数据库加密的背景
1.1 数据库安全机制
应用将数据发送给数据库后,数据库组织数据,将数据存储在文件中,并提供一系列安全机制,保护数据安全。比如:

- 安全传输:基于TLS等安全协议,保证数据在应用与数据库之间传输的机密性、完整性等,避免攻击者对传输中的数据进行窃听、伪造、篡改等
- 身份认证:基于IP、口令、证书等鉴别用户身份,避免攻击者非法访问数据库
- 访问控制:通过多种访问控制机制,限制攻击者对数据库对象的的访问范围
- 安全审计:记录攻击者在数据库中执行的各项操作
- 数据脱敏:对隐私数据库进行脱敏处理,避免攻击者查看数据库中的隐私数据
- 数据防篡改:基于区块链等技术,记录数据变化情况,识别攻击者非法篡改磁盘上的数据库文件
1.2 数据泄露问题
在很多针对数据库的攻击行为中,攻击者可绕过上述数据库安全机制,直接从磁盘窃取数据,造成数据泄露问题。
为了规避此类问题,有效的方案是对数据进行加密,使攻击者仅能从磁盘获取数据密文,无法解密数据,从而解决数据泄露问题。
1.3 数据库加密方案分类
数据库加密方案较多,本博客仅介绍一些常见的,且适用于大部分场景的加密方案。
一、按加密位置分类
首先,按加密位置分类,可分为以下6种:

各方案的基本原理如下:
- 应用加密:应用先将数据加密,再使用SQL语句,将数据密文存储至数据库
- 全密态加密:数据库驱动识别并加密SQL语法中的数据,同时自动解密SQL查询结果。部分数据库产品提供此功能
- 网关或代理加密:在应用与数据库之间的中继节点中,比如代理或网关中,通过解析网络流量,自动识别与加解密流量中的数据,包括SQL语法中的数据与SQL查询结果。很多云服务、安全厂商提供此服务
- 加密函数:数据库内置加密函数或存储过程,应用可通过SQL语法主动调用加密函数。大部分数据库产品提供此功能
- 透明加密:数据库将数据存储至磁盘前,自动加密数据,数据库从磁盘读取数据时,自动解密数据。大部分数据库产品提供此功能
- 磁盘加密:操作系统处理磁盘读写请求时,自动加密与解密读写到的数据。部分操作系统或云存储服务提供此功能
二、按加密定义方式分类
上述加密方案中,按应用是否主动感知加密过程,可将其分为非自动加密与自动加密。
非自动加密
以应用加密为例,用户加密数据的流程如下:-- 1 首先,定义表 CREATE TABLE t1 (c1 TEXT, c2 TEXT); -- 2 假设需向t1中存储数据 (1, 'data1'),应用需要先将数据加密,在通过SQL语法将加密后的数据存储至数据库 -- 3 存储数据 INSERT INTO t1 VALUES ('encrypted[1]', 'encrypted[data1]'); -- 4 查询数据时,查询结果为数据密文,数据无法直接使用 SELECT * FROM t1; -- 查询结果为:('encrypted[1]', 'encrypted[data1]') -- 5 应用需自行解密查询结果,最终解密后得到原始数据 (1, 'data1')此类加密方案中,每次涉及数据读写操作时,都需要主动进行加密与解密,操作复杂。
自动加密
以透明加密为例,用户在创建数据对象时,比如创建表时,可为表设置加密数据:CREATE TABLE t1 (c1 INT, c2 TEXT) WITH (encrypt=on);然后,向数据库中存储时,数据自动加密存储t1表中的数据,从数据库查询t1表数据时,数据库自动解密数据,查询结果为明文。
INSERT INTO t1 VALUES (1, 'data1'); SELECT * FROM t1; -- 查询结果:(1, 'data1')此类加密方案中,用户无需关注加密与解密的过程,仅需为某些数据库对象设置加密属性。常见的自动加密方案中,可为以下几类数据库设置加密熟悉:
自动加密的对象
- 某个数据库,示例:
CREATE DATABASE db1 .. WITH (encrypt=on) - 某个命名空间,示例:
CREATE SCHEMA sch1 .. WITH (encrypt=on) - 某个表空间,示例:
CREATE TABLESPACE spc1 .. WITH (encrypt=on) - 某个表,示例:
CREATE TABLE t1 (c1 INT, c2 TEXT) .. WITH (encrypt=on) - 某个列,示例:
CREATE TABLE t1 (c1 INT encrypt, c2 TEXT)
- 某个数据库,示例:
1.4 数据泄露范围
应用向数据库存储与查询数据时,为解决数据可靠存储、高效查找等问题,数据库可能将数据存放在多个地方。

1.5 数据库加密方案衡量标准
一、安全性
上一节中提到,在很多介质中均可找到数据,本文衡量数据库加密方案的安全性时,将加密范围作为首要参考。
| 介质 | 对象 | 应用加密 | 全密态加密 | 网关加密 | 内置函数加密 | 透明加密 | 磁盘加密 |
|---|---|---|---|---|---|---|---|
| 1 | SQL语句 | 1 | 1 | - | - | - | - |
| 2 | 数据库内存 | 1 | 1 | 1 | - | - | - |
| 3 | 表文件 | 1 | 1 | 1 | 1 | 1 | 1 |
| 4 | 索引文件 | 1 | 1 | 1 | 1 | 1 | 1 |
| 5 | 表物化视图文件 | 1 | 1 | 1 | 1 | - | 1 |
| 6 | 防篡改系统表文件 | 1 | 1 | 1 | - | - | 1 |
| 7 | 优化系统表文件 | 1 | 1 | 1 | 1 | - | 1 |
| 8 | 审计日志文件 | 1 | 1 | 1 | - | - | 1 |
| 9 | 运行日志文件 | 1 | 1 | 1 | - | - | 1 |
| 10 | 预写日志文件 | 1 | 1 | 1 | 1 | 1 | 1 |
| 11 | 回滚日志文件 | 1 | 1 | 1 | 1 | 1 | 1 |
| 12 | 物化节点文件 | 1 | 1 | 1 | 1 | - | 1 |
| 13 | SQL查询结果 | 1 | 1 | - | - | - | - |
| 14 | 内存置换文件 | 1 | 1 | 1 | - | - | 1 |
| 15 | 进程崩溃文件 | 1 | 1 | 1 | - | - | 1 |
| 16 | 主备复制流 | 1 | 1 | 1 | 1 | 1 | - |
| 17 | 分布式计划流 | 1 | 1 | 1 | - | - | - |
| 18 | 逻辑复制流 | 1 | 1 | 1 | 1 | - | - |
| 19 | 容灾复制流 | 1 | 1 | 1 | 1 | 1 | - |
| 20 | 逻辑备份文件 | 1 | 1 | 1 | - | - | - |
| 21 | 物理备份文件 | 1 | 1 | 1 | 1 | 1 | - |
二、可用性
加密范围过大,可能会导致数据库功能的可用性变低。例如,应用将数据加密,再将数据库密文存储在数据库中,当用户查询数据密文时,无法在数据密文上进行各类运算,比如:范围查询、模糊查询、排序等。
加密位置是否在执行模块之前,是影响数据可用性的主要因素。
- 在执行模块之前:执行模块将数据密文存至磁盘,并从磁盘读取数据密文,无法在数据密文上运算
- 在执行模块之后:执行模块处理的数据都是数据明文,执行模块可正常进行计算
三、高性能
四、易用性
五、低膨胀
1.5 各种数据库加密方案的对比
| 加密方案 | 安全性 | 可用性 | 高性能 | 易用性 | 低膨胀 |
|---|---|---|---|---|---|
| 应用加密 | |||||
| 全密态加密 | |||||
| 网关加密 | |||||
| 内置函数加密 | |||||
| 透明加密 | |||||
| 磁盘加密 |
1.2 加密方案
| 序号 | 加密方案 | 加密位置 | 加密原理 | 优点 | 缺点 | 示例 |
|---|---|---|---|---|---|---|
| 1 | 代理加密网关 | 应用客户端 - 应用服务端 | 数据丰富、改动量小 | 扩展性低、实现困难 | CASB代理网关 | |
| 2 | 应用服务端加密 | 应用服务端 | 调用加密API | 方案灵活 | 维护复杂 | 加密模块 |
| 3 | 加密中间件 | 应用服务端 - 数据库驱动 | - | - | - | - |
| 4 | 数据库加密网关 | 数据驱动 - 数据库服务端 | - | - | - | - |
| 5 | 数据库加密函数 | 数据库服务端 | - | - | - | - |
| 6 | 数据库外挂加密 | 数据库服务端 | 触发器、视图、外部程序 | - | - | - |
| 7 | 透明加密 | 数据库服务端 - 文件系统 | - | - | - | - |
| 8 | 文件加密 | 文件系统 | - | - | - | - |
| 9 | 磁盘加密 | 磁盘 | - | - | - | - |
1.3 方案评估标准
- 安全性:
- 功能完整性:
- 性能:
- 易用性:
- 可扩展性:
- 技术成熟度:
1.6 业界数据库加密方案
2 数据库加密的实现
2.0 通过编程访问数据
#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h"
#define Assert(condition) {if (!(condition)) { printf("ERROR: line %d\n", __LINE__); exit(0);} }
void demo()
{
PGconn *conn = PQconnectdb("host=localhost dbname=postgres"); Assert(conn == CONNECTION_OK);
PGresult *res = PQexec(conn, "CREATE TABLE t1 (c1 INT, c2 TEXT);"); Assert(PQresultStatus(res) == PGRES_COMMAND_OK);
res = Qexec(conn, "INSERT INTO t1 VALUES (1, 'data1'), (2, 'data2');"); Assert(PQresultStatus(res) == PGRES_COMMAND_OK);
res = Qexec(conn, "SELECT * FROM t1;"); Assert(PQresultStatus(res) == PGRES_TUPLES_OK);
int row;
for (row = 0; row < PQntuples(res); row++) {
printf("row: %d, data: %s\n", row, PQgetvalue(res, i, 1));
}
PGresult *res = PQexec(conn, "DROP TABLE t1;"); Assert(PQresultStatus(res) == PGRES_COMMAND_OK);
PQclear(res);
PQfinish(conn);
}
int main()
{
demo();
}
2.1 方案一:应用内加密
2.2 方案二:全密态加密
2.3 方案三:网关加密
2.4 方案四:数据库加密函数
2.5 方案五:透明加密
2.6 方案六:磁盘加密
参考
- 一文读懂十大数据存储加密技术.https://www.secrss.com/articles/30324