# 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 # 安装DCAP组件 wget -qO- https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key \ | sudo gpg --dearmor -o /usr/share/keyrings/intel-sgx.gpg echo "deb [arch=amd64 signed-by=/usr/share/keyrings/intel-sgx.gpg] \ https://download.01.org/intel-sgx/sgx_repo/ubuntu focal main" \ | sudo tee /etc/apt/sources.list.d/intel-sgx.list sudo apt update sudo apt install libsgx-dcap-ql libsgx-dcap-quote-verify \ libsgx-enclave-common libsgx-urts libsgx-dcap-default-qpl \ sgx-aesm-service # 安装Open Enclave SDK依赖 wget -qO- https://packages.microsoft.com/keys/microsoft.asc \ | sudo gpg --dearmor -o /usr/share/keyrings/microsoft-oe.gpg echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft-oe.gpg] \ https://packages.microsoft.com/ubuntu/20.04/prod focal main" \ | sudo tee /etc/apt/sources.list.d/openenclave.list sudo apt update sudo apt install open-enclave vim ~/.bashrc # vim 打开后,将以下内容插入 export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/opt/openenclave/share/pkgconfig export CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}:/opt/openenclave/lib/openenclave/cmake export PATH=${PATH}:/opt/openenclave/bin export OE_SDK_PATH=/opt/openenclave source ~/.bashrc ``` ### 1.2 PostgreSQL安装 现版本为PostgreSQL-14.2 ```shell # 解压 PG tar -xzvf postgresql_final.tar.gz # 将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 订阅 PCS 服务 登录 PCS 服务官网,在`Manage Subscription` 中查看 API 密钥 `https://api.portal.trustedservices.intel.com/products#product=liv-intel-software-guard-extensions-provisioning-certification-service` ```shell //PCCS server address "pccs_url": "https://api.trustedservices.intel.com/sgx/certification/v4/" // To accept insecure HTTPS certificate, set this option to false ,"use_secure_cert": true // API key for accessing Intel Trusted Services ,"api_key": "得到的api_key" ``` ### 1.4 配置 Enclave 签名密钥对 ```shell sudo mkdir -p /etc/encryptsql/enclave # 生成 3072-bit RSA 私钥 sudo openssl genrsa -3 -out /etc/encryptsql/enclave/sign_enclave_private.pem 3072 # 从私钥导出公钥 sudo openssl rsa -in /etc/encryptsql/enclave/sign_enclave_private.pem -pubout \ -out /etc/encryptsql/enclave/sign_enclave_public.pem # 权限 sudo chmod 777 /etc/encryptsql/enclave/sign_enclave_private.pem sudo chmod 777 /etc/encryptsql/enclave/sign_enclave_public.pem ``` ### 1.5 配置数据库 ```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 # 配置 KeyDistribution 后台接收服务(由 postmaster 启动) 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 [OPTIONS]; --DESCRIPTION: 轮换指定表的数据加密密钥(DEK) --OPTIONS: --TK 仅轮换表密钥 --CK 轮换指定列密钥,多个列名用逗号分隔 --ALL 轮换所有密钥(表密钥+所有列密钥) --EXAMPLES: ROTATE DEK NOW table_name -TK; ROTATE DEK NOW table_name -CK colname1,colname2; ROTATE DEK NOW table_name -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