全密态数据库可以用于多方数据融合计算,支持数据所有者授权第三方使用数据参与计算,实现联合营销等多种场景。
场景介绍
以某数据平台公司业务场景为例,该平台通过合法渠道,经用户授权后,收集了用户信息,生成用户画像表(portrait),可以授权第三方(例如保险公司)使用数据进行多方数据融合计算,实现联合营销。
手机号(phone) | 年龄(age) | 是否有车(have_car) | 年消费金额(annual_consume) |
13900001111 | 29 | N | 20000 |
13900002222 | 34 | Y | 10000 |
上表中数据仅为示例。
保险公司希望借助数据平台公司的数据,帮助保险公司发展潜在用户,例如向有车一族定向推送车辆保险。
联合查询应满足:
未授权时,联合查询SQL失败,提示无权限。
签发BCL查询授权,联合查询SQL成功,并返回密文结果。
签发BCL解密授权,授权结果方可以解密得到明文结果。
多方数据融合计算流程示例
本文以个人隐私保护中的保险公司为例进行举例,请先参见个人隐私保护完成相关配置。
数据平台公司
DBA创建用户和数据库表。
-------- 创建用户 -------- -- 数据平台公司 CREATE USER ly; -- 为数据平台公司创建用户画像表 CREATE TABLE portrait ( phone enc_text, age enc_int4, have_car enc_text, annual_consume enc_int8 ); -- 授权数据平台公司访问数据表 GRANT ALL ON portrait TO ly;
注册数据平台公司账号。
说明EncDB Tool工具将会基于传入的参数自动生成SQL语句,您需要将生成的SQL在数据库中执行。
./genEncdbSQLCommand.sh -r MEK_PROVISION --mek sample/default_mek_ly.bin -e default_enclave_public_key.pem -c ${cipher_suite} # 获取数据平台公司MEKID,可以通过SQL查询获得:SELECT encdb_get_current_mek_id(); # 本文以6953973016013340672为例 mekid_ly = 6953973016013340672 ./genEncdbSQLCommand.sh -r BCL_REGISTER --mekid ${mekid_ly} --mek sample/default_mek_ly.bin --puk sample/usr_puk_ly.pem --pri sample/usr_pri_ly.pem -c ${cipher_suite}
平台公司为用户画像表创建加密密钥。
说明如下命令需使用
ly
用户执行。命令中的
encdb.dek_xxx()
和encdb.keyname_xxx()
为类型转换函数,更多用法,请参见类型转换函数说明。
-- 创建一个dek,记录groupid,例如 fd89d386-ee00-4e0e-9e5f-66efb4c124aa SELECT encdb.dek_generate(encdb.keyname_generate('ly','demo','public','portrait','phone')); -- 此处仅为示例,同步给所有列,即共用一个dek SELECT encdb.dek_copy_keyname(encdb.keyname_generate('ly','demo','public','portrait','age'),encdb.keyname_generate('ly','demo','public','portrait','phone')); SELECT encdb.dek_copy_keyname(encdb.keyname_generate('ly','demo','public','portrait','have_car'),encdb.keyname_generate('ly','demo','public','portrait','phone')); SELECT encdb.dek_copy_keyname(encdb.keyname_generate('ly','demo','public','portrait','annual_consume'),encdb.keyname_generate('ly','demo','public','portrait','phone'));
正常情况下,不允许用户直接通过SQL加密数据(不安全),用户需要明确授权该行为。
编辑BCL内容,将目标dek的授权范围(包括groupid)更新到BCL中。
./setGroupIdBCL.sh -l fd89d386-ee00-4e0e-9e5f-66efb4c124aa
说明本示例中的
fd89d386-ee00-4e0e-9e5f-66efb4c124aa
仅为示例,实际取值请从如下命令中获取:SELECT encdb.dek_generate(encdb.keyname_generate('ly','demo','public','portrait','phone'));
签发BCL。
./genEncdbSQLCommand.sh -r BCL_ISSUE --subject_sign --spriv sample/usr_pri_ly.pem --spuk sample/usr_puk_ly.pem --ipuk sample/usr_puk_ly.pem --bcl sample/bcl_for_ly_insert.txt -c ${cipher_suite} ./genEncdbSQLCommand.sh -r BCL_ISSUE --issuer_sign --ipriv sample/usr_pri_ly.pem --spuk sample/usr_puk_ly.pem --ipuk sample/usr_puk_ly.pem --bcl sample/bcl_for_ly_insert.txt -c ${cipher_suite}
数据平台公司写入数据。
说明如下命令需使用
ly
用户执行。INSERT INTO portrait VALUES(encdb.enc_text_encrypt('13900001111',encdb.keyname_generate('ly','demo','public','portrait','phone')), encdb.enc_int4_encrypt('29',encdb.keyname_generate('ly','demo','public','portrait','age')), encdb.enc_text_encrypt('N',encdb.keyname_generate('ly','demo','public','portrait','have_car')), encdb.enc_int8_encrypt('2',encdb.keyname_generate('ly','demo','public','portrait','annual_consume'))); INSERT INTO portrait VALUES(encdb.enc_text_encrypt('13900002222',encdb.keyname_generate('ly','demo','public','portrait','phone')), encdb.enc_int4_encrypt('34',encdb.keyname_generate('ly','demo','public','portrait','age')), encdb.enc_text_encrypt('Y',encdb.keyname_generate('ly','demo','public','portrait','have_car')), encdb.enc_int8_encrypt('1',encdb.keyname_generate('ly','demo','public','portrait','annual_consume')));
保险公司
保险公司销售部门为了向有车一族推送车辆保险,发起联合查询:
SELECT * FROM person ps JOIN portrait pt ON ps.phone = pt.phone WHERE hava_car = 'Y';
保险公司销售部门授权encrypt权限。
编辑BCL内容,将目标dek的授权范围(包括groupid)更新到BCL中。
./setGroupIdBCL.sh -s 7903d109-f3e0-4f3e-b815-3682cb8bd6db
说明本示例中的
7903d109-f3e0-4f3e-b815-3682cb8bd6db
仅为示例,销售使用默认密钥进行加密,对应groupid可以通过如下命令查询:# 获取销售部门账号MEKID,以2715553450389700608为例 SELECT encdb_get_current_mek_id(); # 获取groupid SELECT groupid FROM encdb.encdb_internal_dek_table WHERE mekid = 2715553450389700608;
签发BCL。
./genEncdbSQLCommand.sh -r BCL_ISSUE --subject_sign --spriv sample/usr_pri_sale.pem --spuk sample/usr_puk_sale.pem --ipuk sample/usr_puk_sale.pem --bcl sample/bcl_for_sale_insert.txt -c ${cipher_suite} ./genEncdbSQLCommand.sh -r BCL_ISSUE --issuer_sign --ipriv sample/usr_pri_sale.pem --spuk sample/usr_puk_sale.pem --ipuk sample/usr_puk_sale.pem --bcl sample/bcl_for_sale_insert.txt -c ${cipher_suite}
保险公司销售部门查询数据。
销售部门未得到数据平台公司授权,使用数据平台公司数据:
说明如下命令需使用
ins_sale
用户执行。SELECT * FROM person ps JOIN portrait pt ON ps.phone = pt.phone WHERE pt.have_car = encdb.enc_text_encrypt('Y',encdb.keyname_generate('ins_sale','demo', Null, Null, Null)); WARNING: -- encdb -- -- Untrusted log -- 4 - src/core/untrusted/src/encdb_untrusted_enclave.cpp,256,encdb_ecall: Select BCL (subject_mekid: 2715553450389700608, issuer_mekid: 6953973016013340672) from table fail - returned 0xfa030000 ERROR: pg_enc_cmp_eq: encrypted type equal errno: fa030000
说明如果出现
ERROR: permission denied for table portrait
的错误时,执行GRANT SELECT ON portrait TO ins_sale;
授权访问表。销售部门获得数据平台公司及数据部门授权后,使用数据平台公司数据。
销售部门向平台公司发起授权,平台公司审批后,签发授权。
# 销售部门发起授权请求:SUBJECT申请方签名确认 ./genEncdbSQLCommand.sh -r BCL_ISSUE --subject_sign --spriv sample/usr_pri_sale.pem --spuk sample/usr_puk_sale.pem --ipuk sample/usr_puk_ly.pem --bcl sample/bcl_ly_for_sale_select.txt -c ${cipher_suite} # 平台公司审批后确认授权、并签发BCL:ISSUER授权方签名确认 ./genEncdbSQLCommand.sh -r BCL_ISSUE --issuer_sign --ipriv sample/usr_pri_ly.pem --spuk sample/usr_puk_sale.pem --ipuk sample/usr_puk_ly.pem --bcl sample/bcl_ly_for_sale_select.txt -c ${cipher_suite}
销售部门向数据部门发起授权,数据部门审批后,签发授权。
# 销售部门发起授权请求:SUBJECT申请方签名确认 ./genEncdbSQLCommand.sh -r BCL_ISSUE --subject_sign --spriv sample/usr_pri_sale.pem --spuk sample/usr_puk_sale.pem --ipuk sample/usr_puk_data.pem --bcl sample/bcl_data_for_sale_select.txt -c ${cipher_suite} # 数据部门审批后确认授权、并签发BCL:ISSUER授权方签名确认 ./genEncdbSQLCommand.sh -r BCL_ISSUE --issuer_sign --ipriv sample/usr_pri_data.pem --spuk sample/usr_puk_sale.pem --ipuk sample/usr_puk_data.pem --bcl sample/bcl_data_for_sale_select.txt -c ${cipher_suite}
销售部门可以正确执行联合查询拿到密文计算结果。
说明如下命令需使用
ins_sale
用户执行。SELECT * FROM person ps JOIN portrait pt ON ps.phone = pt.phone WHERE pt.have_car = encdb.enc_text_encrypt('Y',encdb.keyname_generate('ins_sale','demo', Null, Null, Null)); -- 可以查询得到联合查询密文结果