《openGauss全密态与防篡改账本数据库:云上数据安全与可信的新范式》

openGauss 推出 全密态计算(Fully Encrypted Database)防篡改账本数据库(Ledger DB) ,以"可信执行环境 + 分布式校验账本"为核心,实现了从"数据安全"到"数据可信"的跨越。

全密态计算:数据不解密也能算

全密态计算的目标是:

"让数据在加密状态下完成读写、查询与计算,让数据库管理员也无法窥视明文。"

该图展示了 openGauss 在加密驱动层、数据库内核层、可信执行环境三层结构下的数据流动路径:

  1. Application API:上层业务以明文形式提交 SQL;

  2. ODBC/JDBC 驱动:负责将明文转为密文;

  3. User-Side 加密模块:在客户端完成加密,不传输明文;

  4. GaussDB Kernel:在密文状态下执行查询;

  5. TEE(可信执行环境) :在隔离硬件区域中进行明文计算;

  6. REE(Rich Execution Environment) :处理密文操作,保障性能。

数据全程密文传输与计算,服务器端不保存任何明文密钥。

三层密钥机制与加密流程

密钥体系包括三类:

  1. 根密钥(Root Key)

  2. 存储于操作系统密钥管理模块(如 secGear、EulerOS KMS);主密钥(Master Key)

  3. 由客户端生成并通过可信通道传输给数据库内核;列加密密钥(Column Encryption Key, CEK) 绑定特定列或字段,实现细粒度数据加密。

加密流程如下:

  1. 客户端层加密:数据在本地通过 CEK 加密;

  2. 传输层保护:通过 SSL / TEE 通道加密传输;

  3. 数据库层计算:在密文状态下完成等值或范围查询。

密态计算数据流:从加密到查询的全过程

实例查询:

SQL 复制代码
SELECT c1 FROM table WHERE c1 > 123;

1 客户端使用 CEK 加密常量 123 → 0xfe31da05;

2 加密请求通过 SSL 通道发送至 openGauss;

3 GaussDB 在 REE 环境执行密文比较;

4 若启用硬件 TEE,则在安全 enclave 中执行明文运算;

5 返回结果时再由客户端解密展示。

这样,服务器端即使被攻破,也无法推导出真实业务数据。

防篡改账本数据库:可信可追溯的事务链

账本数据库是在传统事务数据库(ACID)基础上扩展的加密时间链系统

具备以下特性:

  1. 增量校验算法:每个 Checkpoint 均记录增量变更哈希;

  2. 一致性验证:任意节点可快速校验账本一致性;

  3. 分布式存储:账本切片(slice1, slice2, ...)支持跨节点互审。

账本表结构demo:

SQL 复制代码
CREATE TABLE audit_ledger (  
    tx_id BIGINT,  
    operator TEXT,  
    action TEXT,  
    ts TIMESTAMP  
) WITH (ledger = 'on');  

数据写入时自动生成链式哈希:

SQL 复制代码
TX_HASH: 8fe91ac9cde0...  
PREV_HASH: 3ae15f477b81...  

系统自动维护账本链关系,支持"不可篡改、可追溯"的历史查询。

校验与恢复

SQL 复制代码
-- 验证账本完整性  
SELECT ledger_verify('audit_ledger');  

输出:

SQL 复制代码
Ledger verified: OK (no tampering detected)  

即使主机遭到破坏,备机账本链仍能完整恢复

可信执行环境(TEE)与密态计算协同

openGauss 的全密态能力与 secGear + Kunpeng + EulerOS 深度集成,形成"软硬一体化可信执行环境":

这种"TEE + 数据库"的设计使得密文计算在硬件隔离空间执行,从而实现加密计算性能提升 2.3×,泄露风险趋近于零

落地实践: 密态计算 + 账本审计一体化方案

一、 环境与库初始化(openGauss)

你已有可用的 openGauss 集群即可,以下命令均在 gsql 客户端执行。若是容器/单机版,只要能 gsql -d postgres -p 5432 -r 进库即可。

SQL 复制代码
# 连接(请替换端口/用户/密码)  
gsql -d postgres -p 5432 -U omm -r  

1) 建业务库与专用 schema、角色

SQL 复制代码
-- 业务数据库  
CREATE DATABASE secure_demo;  
\c secure_demo;  
   
-- 应用专用 schema 与角色  
CREATE SCHEMA IF NOT EXISTS secure AUTHORIZATION CURRENT_USER;  
CREATE ROLE app_rw LOGIN PASSWORD 'AppSecret!123';  
GRANT USAGE ON SCHEMA secure TO app_rw;  

二、 表结构设计:密态存储 + 等值索引 + 账本表

我们采用应用侧 AES-GCM 加密 ,数据库里只存密文 ;为了支持等值查询 ,额外存一列不可逆的等值检索键 (HMAC/Hash),并在该列上建索引。审计方面,用一张链式账本表 记录每次操作的摘要哈希,触发器自动写入,支持之后的链式校验

1) 业务数据表(只存密文,不落明文)

SQL 复制代码
SET search_path TO secure;  
   
-- 用户信息密态表:不保存明文  
-- name_hash:等值检索键(HMAC/MD5/其他不可逆摘要),用于 WHERE 等值查询  
-- name_ct/phone_ct:AES-GCM 密文(密钥/nonce 在客户端管理,不入库)  
CREATE TABLE secure.user_info_secure (  
    id          BIGSERIAL PRIMARY KEY,  
    name_hash   CHAR(64)        NOT NULL,     -- 64位十六进制串(示例用 SHA-256 的 hex)  
    name_ct     BYTEA           NOT NULL,     -- 姓名密文  
    phone_ct    BYTEA           NOT NULL,     -- 手机密文  
    created_at  TIMESTAMP       NOT NULL DEFAULT now()  
);  
   
-- 等值查询索引(命中 name_hash)  
CREATE INDEX idx_user_info_name_hash ON secure.user_info_secure (name_hash);  

2) 账本表(链式哈希,防篡改)

SQL 复制代码
-- 简洁的账本表:每条业务变更都会记一条 "区块"  
-- prev_hash 串起链路,curr_hash 为本次区块哈希(含前一个区块哈希、当前行摘要、时间戳等)  
CREATE TABLE secure.audit_ledger (  
    block_id    BIGSERIAL PRIMARY KEY,  
    table_name  TEXT        NOT NULL,  
    op          TEXT        NOT NULL,       -- INSERT / UPDATE / DELETE  
    row_pk      BIGINT      NOT NULL,       -- 目标行主键(user_info_secure.id)  
    row_digest  CHAR(32)    NOT NULL,       -- 该行摘要(使用 md5 以避免扩展依赖)  
    prev_hash   CHAR(32)    NOT NULL,  
    curr_hash   CHAR(32)    NOT NULL,  
    op_at       TIMESTAMP   NOT NULL DEFAULT now()  
);  
   
-- 保存全局"上一个区块哈希";我们用一张仅 1 行的小表做"链头指针"  
CREATE TABLE secure.audit_head (  
    id      INT PRIMARY KEY,  
    tip     CHAR(32) NOT NULL        -- 最新区块哈希  
);  
INSERT INTO secure.audit_head (id, tip) VALUES (1, md5('genesis'));  -- 创世 tip 

3) 触发器:自动写账本区块

SQL 复制代码
-- 生成当前行的摘要(把关键字段序列化后 md5)  
CREATE OR REPLACE FUNCTION secure.digest_user_row(_id BIGINT, _name_ct BYTEA, _phone_ct BYTEA)  
RETURNS CHAR(32)  
LANGUAGE plpgsql AS $$  
DECLARE  
  s TEXT;  
BEGIN  
  -- 注意:我们不把密钥相关信息落库;仅对密文进行摘要  
  s := _id || ':' || encode(_name_ct, 'hex') || ':' || encode(_phone_ct, 'hex');  
  RETURN md5(s);  
END;  
$$;  
   
-- 写入账本区块:prev_hash = audit_head.tip;curr_hash = md5(prev_hash || row_digest || op || now)  
CREATE OR REPLACE FUNCTION secure.append_ledger(_tbl TEXT, _op TEXT, _pk BIGINT, _row_digest CHAR(32))  
RETURNS VOID  
LANGUAGE plpgsql AS $$  
DECLARE  
  prev CHAR(32);  
  now_hash CHAR(32);  
BEGIN  
  SELECT tip INTO prev FROM secure.audit_head WHERE id=1 FOR UPDATE;  
  now_hash := md5(prev || _row_digest || _op || now()::text);  
   
  INSERT INTO secure.audit_ledger(table_name,op,row_pk,row_digest,prev_hash,curr_hash)  
  VALUES(_tbl,_op,_pk,_row_digest,prev,now_hash);  
   
  UPDATE secure.audit_head SET tip = now_hash WHERE id=1;  
END;  
$$;  
   
-- 三类 DML 的行级触发器  
CREATE OR REPLACE FUNCTION secure.tg_user_info_ledger()  
RETURNS TRIGGER  
LANGUAGE plpgsql AS $$  
DECLARE  
  d CHAR(32);  
BEGIN  
  IF TG_OP = 'INSERT' THEN  
    d := secure.digest_user_row(NEW.id, NEW.name_ct, NEW.phone_ct);  
    PERFORM secure.append_ledger('user_info_secure','INSERT',NEW.id,d);  
    RETURN NEW;  
  ELSIF TG_OP = 'UPDATE' THEN  
    d := secure.digest_user_row(NEW.id, NEW.name_ct, NEW.phone_ct);  
    PERFORM secure.append_ledger('user_info_secure','UPDATE',NEW.id,d);  
    RETURN NEW;  
  ELSIF TG_OP = 'DELETE' THEN  
    d := secure.digest_user_row(OLD.id, OLD.name_ct, OLD.phone_ct);  
    PERFORM secure.append_ledger('user_info_secure','DELETE',OLD.id,d);  
    RETURN OLD;  
  END IF;  
END;  
$$;  
   
CREATE TRIGGER trg_user_info_ledger  
AFTER INSERT OR UPDATE OR DELETE ON secure.user_info_secure  
FOR EACH ROW EXECUTE FUNCTION secure.tg_user_info_ledger();  

三、 验证/审计工具 SQL(链式自校验)

SQL 复制代码
-- 1) 检查链路是否连续(curr_hash->prev_hash)  
WITH RECURSIVE chain AS (  
  SELECT block_id, prev_hash, curr_hash  
  FROM secure.audit_ledger  
  WHERE block_id = (SELECT min(block_id) FROM secure.audit_ledger)  
  UNION ALL  
  SELECT l.block_id, l.prev_hash, l.curr_hash  
  FROM secure.audit_ledger l  
  JOIN chain c ON l.prev_hash = c.curr_hash  
)  
SELECT COUNT(*) AS blocks_on_chain, (SELECT COUNT(*) FROM secure.audit_ledger) AS total_blocks  
FROM chain;  
   
-- 2) 重算每个区块的 curr_hash 并比对,检测是否被篡改  
SELECT block_id,  
       curr_hash AS stored,  
       md5(prev_hash || row_digest || op || op_at::text) AS recomputed,  
       (curr_hash = md5(prev_hash || row_digest || op || op_at::text)) AS ok  
FROM secure.audit_ledger  
ORDER BY block_id;  

四、 业务侧密态等值查询:Python 端完整代码

采用 cryptography 实现 AES-256-GCM

HMAC-SHA256 生成 name_hash(等值检索键,可重复、不可逆,用于 WHERE 匹配);

明文只在客户端内存 出现,openGauss 仅保存密文与 hash。

sql 复制代码
# requirements:  
#   pip install psycopg2-binary cryptography  
   
import os  
import hmac  
import hashlib  
import secrets  
import psycopg2  
from cryptography.hazmat.primitives.ciphers.aead import AESGCM  
   
DSN = "dbname=secure_demo user=omm password=YourPass host=127.0.0.1 port=5432"  
   
# === 客户端密钥(Demo:本地环境变量/文件;生产环境请接入 KMS/TEE) ===  
# 数据加密密钥(DEK) & HMAC 密钥  
DEK = os.environ.get("DEK_HEX") or secrets.token_hex(32)   # 32 bytes => AES-256  
HMK = os.environ.get("HMK_HEX") or secrets.token_hex(32)   # 32 bytes for HMAC-SHA256  
   
aesgcm = AESGCM(bytes.fromhex(DEK))  
hmac_key = bytes.fromhex(HMK)  
   
def hmac_sha256_hex(msg: bytes) -> str:  
    return hmac.new(hmac_key, msg, hashlib.sha256).hexdigest()  
   
def aes_gcm_encrypt(plaintext: bytes) -> bytes:  
    nonce = secrets.token_bytes(12)  # GCM 标准 96-bit nonce  
    ct = aesgcm.encrypt(nonce, plaintext, associated_data=None)  
    return nonce + ct  # 拼接存库:nonce|ciphertext|tag  
   
def aes_gcm_decrypt(blob: bytes) -> bytes:  
    nonce, ct = blob[:12], blob[12:]  
    return aesgcm.decrypt(nonce, ct, associated_data=None)  
   
def insert_user(name: str, phone: str):  
    name_hash = hmac_sha256_hex(name.encode("utf-8"))  
    name_ct   = aes_gcm_encrypt(name.encode("utf-8"))  
    phone_ct  = aes_gcm_encrypt(phone.encode("utf-8"))  
    with psycopg2.connect(DSN) as conn, conn.cursor() as cur:  
        cur.execute("""  
            INSERT INTO secure.user_info_secure (name_hash, name_ct, phone_ct)  
            VALUES (%s, %s, %s)  
            RETURNING id;  
        """, (name_hash, psycopg2.Binary(name_ct), psycopg2.Binary(phone_ct)))  
        uid = cur.fetchone()[0]  
        print(f"insert ok, id={uid}")  
   
def query_user_by_name(name: str):  
    name_hash = hmac_sha256_hex(name.encode("utf-8"))  
    with psycopg2.connect(DSN) as conn, conn.cursor() as cur:  
        cur.execute("""  
            SELECT id, name_ct, phone_ct, created_at  
            FROM secure.user_info_secure  
            WHERE name_hash = %s  
            ORDER BY id;  
        """, (name_hash,))  
        rows = cur.fetchall()  
        result = []  
        for uid, name_ct, phone_ct, ts in rows:  
            name_pt  = aes_gcm_decrypt(bytes(name_ct)).decode("utf-8")  
            phone_pt = aes_gcm_decrypt(bytes(phone_ct)).decode("utf-8")  
            result.append((uid, name_pt, phone_pt, ts))  
        return result  
   
def update_phone(name: str, new_phone: str):  
    name_hash = hmac_sha256_hex(name.encode("utf-8"))  
    phone_ct  = aes_gcm_encrypt(new_phone.encode("utf-8"))  
    with psycopg2.connect(DSN) as conn, conn.cursor() as cur:  
        cur.execute("""  
            UPDATE secure.user_info_secure  
               SET phone_ct = %s  
             WHERE name_hash = %s;  
        """, (psycopg2.Binary(phone_ct), name_hash))  
        print(f"update rows = {cur.rowcount}")  
   
def delete_user(name: str):  
    name_hash = hmac_sha256_hex(name.encode("utf-8"))  
    with psycopg2.connect(DSN) as conn, conn.cursor() as cur:  
        cur.execute("DELETE FROM secure.user_info_secure WHERE name_hash=%s;", (name_hash,))  
        print(f"delete rows = {cur.rowcount}")  
   
if __name__ == "__main__":  
    # 写入两条密态数据  
    insert_user("张三", "13800000001")  
    insert_user("李四", "13800000002")  
   
    # 等值查询(库端匹配 hash,客户端解密展示)  
    print("查询 张三:", query_user_by_name("张三"))  
   
    # 更新与删除(触发器会自动写账本区块)  
    update_phone("张三", "13912345678")  
    print("查询 张三:", query_user_by_name("张三"))  
   
    delete_user("李四")  

运行结果

sql 复制代码
insert ok, id=1  
insert ok, id=2  
查询 张三: [(1, '张三', '13800000001', datetime.datetime(2025, 11, 1, 10, 33, 47, ...))]  
update rows = 1  
查询 张三: [(1, '张三', '13912345678', datetime.datetime(2025, 11, 1, 10, 33, 47, ...))]  
delete rows = 1  

结语

openGauss 通过 全密态计算 + 账本数据库 + TEE 硬件安全, 构建了可实现"数据不解密可计算,交易全程可追溯 "的数据库安全体系。它不仅满足政务、金融、能源等行业的高安全需求,更为 AI 大模型提供了安全可信的数据底座。未来,openGauss 将成为云上"可信计算 + 数据智能"融合的关键引擎,让数据真正做到:"可用不可见,可查可证,可控可审。 "

相关推荐
Z***u6591 小时前
MySQL物联网开发
数据库·mysql
J***79391 小时前
MySQL语音识别案例
数据库·mysql·语音识别
y***86691 小时前
MySQL语音识别开发
数据库·mysql·语音识别
u***09642 小时前
MySQL索引优化
数据库·mysql
q***08742 小时前
MySQL压缩版安装详细图解
android·mysql·adb
A***27952 小时前
MySQL外键约束导致的删除失败问题
数据库·mysql
格格步入2 小时前
线上问题:MySQL NULL值引发的投诉
后端·mysql
dessler2 小时前
MYSQL-物理备份(xtrabackup)使用指南
linux·数据库·mysql
5***26202 小时前
MySQL存储过程优化实例
数据库·mysql