Files
encryptsql/readme.md
blue-lemon0104 46fa58f6f8 merge
2026-04-07 15:45:41 +08:00

511 lines
16 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Enc-db配置方法
## 1. 安装环境
> Ubuntu 20.04
> gcc version 9.4.0
### 1.1 依赖项
```shell
sudo apt-get update
sudo apt-get install -y build-essential libreadline-dev zlib1g-dev libssl-dev libxml2-dev libxslt-dev cmake
sudo apt-get install -y make automake libtool git
sudo apt-get install -y libssl-dev libboost-all-dev lzip
sudo apt-get install -y protobuf-compiler libprotobuf-dev
sudo apt-get install -y libjsoncpp-dev
# 安装gmp依赖
wget https://gmplib.org/download/gmp/gmp-6.2.1.tar.lz
tar -xf gmp-6.2.1.tar.lz
cd gmp-6.2.1
CFLAGS="-fPIC" ./configure
make -j4
sudo make install
# 安装log4cpp日志
wget http://sourceforge.net/projects/log4cpp/files/log4cpp-1.1.3.tar.gz
tar -xvzf log4cpp-1.1.3.tar.gz
cd log4cpp
./configure
make
sudo make install
# 安装国密依赖
git clone https://github.com/guanzhi/GmSSL.git
cd GmSSL
mkdir build
cd build
cmake ..
make
make test
sudo make install
```
### 1.2 PostgreSQL安装
现版本为PostgreSQL-14.2
```shell
# 下载安装PostgreSQL-14.2
wget https://ftp.postgresql.org/pub/source/v14.2/postgresql-14.2.tar.gz
tar -xzvf postgresql-14.2.tar.gz
# 解压本项目EncDB并放到postgresql-14.2/src/interfaces/libpq路径下
unzip encryptsql.zip
cp -r encryptsql/ postgresql-14.2/src/interfaces/libpq/
# 将pg编译到/usr/local/postgresql路径下
sudo mkdir /usr/local/postgresql
cd postgresql-14.2
./configure --enable-debug --enable-cassert --prefix=/usr/local/postgresql CFLAGS=-O0
sudo make -j `nproc`
# 编译encdb
cd src/interfaces/libpq/encryptsql/
rm -f ../Makefile
cp replaced_file/Makefile.libpq.14 ../Makefile
rm -f ../../../bin/psql/Makefile
cp replaced_file/Makefile.psql.14 ../../../bin/psql/Makefile
cp replaced_file/fe-exec.14.c ../
rm ../fe-exec.c
mv ../fe-exec.14.c ../fe-exec.c
sudo mkdir -p /etc/encryptsql/enclave
sudo cp config.json /etc/encryptsql/
ln -s ../../../include db_include
rm -rf build
mkdir build && cd build
cmake .. \
-DENCRYPTSQL_INSTALL_DIR=/usr/local/postgresql \
-DENCRYPTSQL_CONFIG_DIR=/etc/encryptsql \
-DDK_SERVER_HOST=127.0.0.1 \
-DDK_SERVER_PORT=9443
sudo make -j `nproc`
cd ../../../../../
cmake --build src/interfaces/libpq/encryptsql/build --target enclave.signed.so -j"$(nproc)"
cp /etc/encryptsql/enclave.signed.so src/interfaces/libpq/encryptsql/build/lib/enclave.signed.so
make install
sudo rm /usr/local/postgresql/lib/libudf.so
sudo cp src/interfaces/libpq/encryptsql/build/lib/libudf.so /usr/local/postgresql/lib
sudo rm /usr/local/postgresql/lib/libencryptsql.so
sudo cp src/interfaces/libpq/encryptsql/build/lib/libencryptsql.so /usr/local/postgresql/lib
sudo cp src/interfaces/libpq/encryptsql/createudf.sql /usr/local/postgresql/
sudo cp src/interfaces/libpq/encryptsql/map.json /etc/encryptsql
sudo cp src/interfaces/libpq/encryptsql/mask_funcs.sql /usr/local/postgresql/
sudo cp src/interfaces/libpq/encryptsql/build/bin/backup /usr/local/postgresql/bin/
sudo cp src/interfaces/libpq/encryptsql/build/bin/restore /usr/local/postgresql/bin/
# 创建cmk存储路径
sudo mkdir -p /etc/encryptsql/kms_test
sudo cp src/interfaces/libpq/encryptsql/src/KMS/domainkey /etc/encryptsql/kms_test/
cd /etc/encryptsql
sudo chmod 777 map.json
# 创建kms_root根密钥相关文件
sudo mkdir -p /etc/encryptsql/kms_root
cd /etc/encryptsql/kms_root
sudo head -c 16 /dev/urandom > frag_a
sudo head -c 16 /dev/urandom > frag_b
sudo head -c 16 /dev/urandom > frag_c
```
### 1.3 配置数据库
```shell
cd /usr/local/postgresql
sudo mkdir data
sudo useradd -m -s /bin/bash postgres
sudo passwd postgres
sudo chown postgres:postgres data
su postgres
vim ~/.bashrc
#vim打开后 将下面export开头内容插入到内部并保存
export PGHOME=/usr/local/postgresql
export PGDATA=$PGHOME/data
export PGPORT=5432
export PGUSER=postgres
export PATH=$PGHOME/bin:$PATH:$HOME/bin
export LD_LIBRARY_PATH=$PGHOME/lib
source ~/.bashrc
initdb
vim /usr/local/postgresql/data/postgresql.conf
# vim 打开后,将下面内容加入到尾部
shared_preload_libraries = 'keydist_receiver'
keydist.listen_host = '127.0.0.1'
keydist.listen_port = '9443'
keydist.enclave_signed_path = '/new_enc/postgresql-14.2/src/interfaces/libpq/encryptsql/build/bin/tls_server_enclave.signed'
pg_ctl start
su root
cd bin
./psql -U postgres
```
## 2. 使用说明
### 2.1 功能准备
```sql
create user dekmaster with password 'secure_password';
create database dekmaster owner dekmaster;
GRANT ALL PRIVILEGES ON DATABASE dekmaster TO dekmaster;
\q
```
```shell
./psql -U dekmaster -d dekmaster
```
配置DEK表
```sql
create table dek_store(
username text,
db text,
t text,
c text,
dek text);
\q
```
### 2.2 测试使用
```shell
./psql -U postgres -d postgres
```
进入psql客户端
#### 1. 密钥创建、建表插入查询功能
```sql
--导入密态UDF函数
\i ../createudf.sql
--启动加密环境
--(enc status可查询数据库enc加密状态1为on开启中0为off已关闭)
enc on;
--创建CMK,并设置轮转周期(天)
create cmk -rotate_period=30;
--创建表
CREATE TABLE sample_table (
id int PRIMARY KEY,--数值明文
datetime date,--日期明文
name varchar(255) encrypted(eq),--字符密文,确定性加密
brand char(20) encrypted(rnd) NOT NULL,--字符密文,非确定性加密
amount int4 encrypted(eq, cal),--int4数值密文确定性加密+同态加密
price int8 encrypted(eq, cal),--int8数值密文确定性加密+同态加密
discount_price int8 encrypted(eq, cmp),--数值密文,确定性加密+保序加密
supplier_name varchar(255), --字符明文
supplier_address text
);
--插入数据
INSERT INTO sample_table VALUES
(1, '2024-03-29', 'Product_1', 'BMFTOEKLWR', 10000, 2000, 1699, 'Supplier_1', '2 Road, District_9'),
(2, '2023-12-27', 'Product_2', 'AZZPSNNNHP', 20000, 1000, 890, 'Supplier_2', '7 Road, District_6'),
(3, '2020-03-13', 'Product_2', 'RJBVWGLNMK', 22500, 599, 469, 'Supplier_3', '1 Road, District_4'),
(4, '2020-04-21', 'Product_2', 'QLLCNGBDSV', 20000, 1200, 1099, 'Supplier_3', '1 Road, District_4'),
(5, '2020-01-10', 'Product_3', 'CPSLKAILDA', 5000, 2599, 2180, 'Supplier_2', '7 Road, District_6'),
(6, '2024-05-02', 'Product_3', 'WKGWZKTNSC', 15000, 1990, 1690, 'Supplier_4', '8 Road, District_2'),
(7, '2022-11-30', 'Product_4', 'PKDVPUEUEL', 6000, 5999, 5399, 'Supplier_3', '1 Road, District_4'),
(8, '2020-06-28', 'Product_5', 'ORXMPSQCQK', 2000, 4999, 4321, 'Supplier_1', '2 Road, District_9'),
(9, '2022-02-24', 'Product_6', 'CYKQRZFHTZ', 20, 18000, 16990, 'Supplier_5', '12 Road, District_3'),
(10, '2021-05-27', 'Product_7', 'NZJQYDWQCQ', 4000, 2700, 1688, 'Supplier_2', '7 Road, District_6');
SELECT * FROM sample_table;
```
---
#### 2. 常用密文SQL计算功能
```sql
--------------------------------常用SQL语句功能测试----------------------------------
--插入查询自动加解密(1.2.1)、明文功能正常使用(1.4.1)、密文标准SQL功能支持(1.4.4)
----------------逻辑运算(1.2.2)---------------
--等值运算(=, !=, GROUP BY)、比较运算(>, <, >=, <=, BETWEEN...AND, ORDER BY, 升序ASC, 降序DESC)、析取合取(AND, OR)等
--等值运算**仅支持在eq加密字段**密文上执行
--比较运算**仅支持在cmp加密字段**密文上执行
DELETE FROM sample_table WHERE id > 8;
UPDATE sample_table SET amount = 3000 WHERE datetime = '2020-06-28';
SELECT * FROM sample_table;
SELECT * FROM sample_table WHERE supplier_name != 'Supplier_3' OR discount_price>=5000;
SELECT * FROM sample_table WHERE name = 'Product_2' AND discount_price < 1000;
SELECT * FROM sample_table WHERE discount_price BETWEEN 1000 AND 3000;
SELECT * FROM sample_table WHERE discount_price > 1500 ORDER BY discount_price DESC;
SELECT name, COUNT(*) AS nums FROM sample_table GROUP BY name;
----------------数值运算(1.2.3)---------------
--数学运算(+, -, *)、聚合函数(MAX, MIN, SUM, COUNT, POW)、混合类型运算(1.2.6)等
SELECT price,price+100 AS add_100 FROM sample_table WHERE name = 'Product_3';
SELECT amount,price,amount*price AS total_price FROM sample_table WHERE name = 'Product_4';
--int4, int8类型混合运算
SELECT amount,price,price + amount AS test_value FROM sample_table WHERE name = 'Product_4';
SELECT MAX(discount_price) AS max_value FROM sample_table;
SELECT MIN(discount_price) AS min_value FROM sample_table;
SELECT SUM(amount) AS sum_of_amount FROM sample_table WHERE id < 6;
SELECT COUNT(name) AS count_name FROM sample_table WHERE supplier_address != '2 Road, District_9';
```
---
#### 3. 密文索引功能
```sql
----------------------------------密文索引测试部分-----------------------------------
--密文索引能力比对(1.2.5): 验证支持构建高效密文索引
--在大量数据下才有所体现,这里仅作为功能展示
--关闭全表扫描
SET enable_seqscan TO off;
--建立索引前查询情况
explain analyze SELECT * FROM sample_table WHERE discount_price < 2000;
--在discount_price保序密文列上建立索引
CREATE INDEX idx_discount_price on sample_table(discount_price);
--建立索引后查询情况
explain analyze SELECT * FROM sample_table WHERE discount_price < 2000;
--在name确定性密文列上建立索引
explain analyze SELECT * FROM sample_table WHERE name = 'Product_2';
CREATE INDEX idx_name on sample_table(name);
explain analyze SELECT * FROM sample_table WHERE name = 'Product_2';
```
---
#### 4. 密钥轮转功能
```sql
---------------------------------密钥轮转测试部分------------------------------------
--密钥轮转(1.3.2): 现阶段支持CMK手动轮转和自动轮转DEK随之同步更新
--支持DEK的手动轮转表级DEK、列级DEK或两者均支持
--密钥用途唯一性(1.3.7): CMK仅用于加密DEK, DEK仅用于加密数据
--创建新表生成新DEK
CREATE TABLE t1(id int encrypted(eq));
--用DEK加密插入数据
INSERT INTO t1 VALUES (10),(20),(30);
SELECT * FROM t1;
--手动轮转CMK命令同步更新DEK信息(大小写均可)
rotate cmk now;
--更新DEK后查询正常解密数据
SELECT * FROM t1;
DROP TABLE t1;
--自动轮转CMK命令cmk rotate/rotation on/off/status; 开启/关闭/查询自动轮转(大小写均可)
--开启CMK自动轮转
cmk rotate on;
--查询CMK自动轮转状态
cmk rotate status;
--关闭CMK自动轮转
cmk rotate off;
--通过/new_enc/kms_test/CMK_auto_rotate_status.json文件持久化保存
--退出psql重新连接后状态仍保持
--USAGE: ROTATE DEK NOW <table_name> [OPTIONS];
--DESCRIPTION: 轮换指定表的数据加密密钥(DEK)
--OPTIONS:
--TK 仅轮换表密钥
--CK <cols> 轮换指定列密钥,多个列名用逗号分隔
--ALL 轮换所有密钥(表密钥+所有列密钥)
--EXAMPLES:
ROTATE DEK NOW users -TK;
ROTATE DEK NOW users -CK `name`,`email`;
ROTATE DEK NOW users -ALL;
```
---
#### 5. 列级密钥相关功能
现完成列密钥的create、insert、update、select语句
+ eq\eqsm4\rnd后面加 _c即可表示使用列密钥其他加密种类暂不支持
```sql
enc on;
-- CREATE TABLE
CREATE TABLE sample (
col1 decimal(10,2) encrypted(eq_c),
col2 text encrypted(rnd_c),
col3 text,
col4 decimal(10,2) encrypted(eqsm4_c),
col5 decimal(10,2) encrypted(eq,cmp,cal),
col6 decimal(10,2) encrypted(eq,cmp,cal)
);
-- 插入语句
INSERT INTO sample (col1, col2, col3, col4, col5, col6)
VALUES
(12.34, 'secret1', 'hello', 12.34, 90.12, 90.12),
(12.34, 'secret2', 'world', 12.34, 12.34, 12.34),
(12.34, 'secret3', 'nihao', 34.56, 34.56, 12.34),
(-0.1234567890, 'secret4', 'world', 99.9999999999, 11.1111111111, 22.2222222222);
```
---
#### 6. 密钥查询功能
现完成密钥查询功能提供查询CMK明密文的功能
输出username、cmk_data、rotate_period、is_primary_version、is_rotated信息
(DEK无感使用不提供查询接口)
```sql
enc on;
--查询CMK密文
describe cmk;
--查询CMK明文(解密后)
describe cmk -d;
-- 或
describe cmk -decrypt;
```
---
#### 7. 数据脱敏功能
现新增数据脱敏函数,函数集合在`mask_funcs.sql` 文件中;
+ 所有函数**统一返回**`text`**类型**NULL值返回NULL值
+ 默认是缺省规则(保留前a位和后b位)
+ UDF函数**明密文状态下均可使用**
+ `insert`插入时脱敏(**静态脱敏**)`select`查询时脱敏(**动态脱敏**)
- 也可`update`更新脱敏数据状态
具体函数如下:
```sql
SELECT mask('abcdefg', 2, 2) AS default, --缺省规则(前a后b)
mask_name('张三丰') AS name_cn, --中文名(后1)
mask_name('John Doe') AS name_en, --英文名(前1)
mask_nick('小海浪子') AS nick, --昵称(前1后1)
mask_email('bob@example.com') AS email, --邮箱(@后)
mask_mobile('13812345678') AS mobile, --手机号(前3后2)
mask_tel('010-88889999') AS tel, --固定电话(后2)
mask_idcard('11010519900307563X') AS idcard, --身份证号(前1后1)
mask_bankcard('6225888812345678') AS bank, --银行卡号(前4后4)
mask_plate('浙A12345') AS plate, --车牌(前2后2)
mask_ip('192.168.1.100') AS ip, --ip地址(前1字段)
mask_numeric(123.456) AS num, --数值取整(四舍五入)
mask_blank('anything') AS blank, --置空(直接替换为-)
mask_full('top secret') AS full; --全遮(保留长度,全替换为*)
--输出效果如下:
name_cn | name_en | nick | email |
---------+----------+------+---------------------+
** | J******* | * | *****@example.com |
mobile | tel | idcard |
------------+------------+-------------------+
138*****78 | ********99 | 1****************X |
bank | plate | ip |
----------------------+----------+-----------+
6225************5678 | A***45 | 192.*.*.* |
num | blank | def | full
------+-------+---------+-----------
123 | - | ab***fg | **********
```
+ 可在密态数据库中通过输入语句:
```sql
\i ../mask_funcs.sql
```
执行文件编写UDF
+ 也可以在进入psql界面之前通过输入命令
```bash
psql -f mask_funcs.sql
```
纳入版本库部署;
使用**静态脱敏**时,可在`insert` 时**直接调用函数**,例如:
```sql
CREATE TABLE customer (mobile text, email text);
INSERT INTO customer (mobile, email)
VALUES (mask_mobile('13812345678'),
mask_email('alice@example.com'));
SELECT * FROM customer;
```
+ 若客户端 SQL 里不能显式写函数,可在**在 BEFORE INSERT 触发器里改写 NEW 值**统一处理,让客户端原样插入明文,由数据库自动脱敏后落盘,例:
```sql
CREATE OR REPLACE FUNCTION trg_mask_customer()
RETURNS trigger
LANGUAGE plpgsql AS
$$
BEGIN
NEW.mobile := mask_mobile(NEW.mobile);
NEW.email := mask_email(NEW.email);
RETURN NEW;
END;
$$;
CREATE TRIGGER bi_customer
BEFORE INSERT ON customer
FOR EACH ROW
EXECUTE FUNCTION trg_mask_customer();
```
+ 客户端照旧 `INSERT INTO customer(mobile,email) VALUES('13812345678','alice@example.com');`,触发器会把列值替换成脱敏后的结果再写入.
使用**动态脱敏**时,通过生成列 / 视图,既保存原文又随时提供脱敏视图,
- 原数据写入真实列
- 建视图或在 SELECT 时调用脱敏函数,例:
```sql
CREATE VIEW v_customer AS
SELECT id,
mask_name(name) AS name,
mask_mobile(mobile) AS mobile,
mask_email(email) AS email
FROM customer;
```
# 备份命令
su root
/usr/local/postgresql/bin/backup postgres
# 导入命令
su root
/usr/local/postgresql/bin/restore postgres