WAL 加密模块设计

假设集群里已经存在表级透明加密模块,在此基础上设计一个高性能、高易用性的 WAL 加密模块。 WAL 加密的难点几乎不在"加密"本身,而在两件事:同一个 8KB 页会被反复重写,以及恢复路径要在拿不到 catalog 的时候就能解密。下面按设计决策的顺序展开。 1 威胁模型 先划清边界,因为它直接决定后面几个取舍。 要防的:磁盘 / 备份 / 归档介质被拖走;DBA 之外的运维人员直接读 pg_wal/;WAL 归档到对象存储。 不防的:有 root 权限的在线攻击者(内存里必然有明文)、旁路攻击。 1.1 为什么不用 dm-crypt 了事 如果只是防"介质丢失",块设备加密(LUKS/dm-crypt)性价比高得多。在数据库内核里做 WAL 加密,真正的理由只有三个: 密钥要由数据库自己管,不能落在 OS 层(密评 / 国测要求); 归档件要天然带密; 和已有的表级 TDE 共用一套密钥体系。 设计要始终对齐这三个理由,否则很容易做成一个又慢、又没多大意义的模块。 1.2 FPI 是必须堵的洞 既然表级 TDE 已经存在,那么 FPI(full page image)就是个必堵的泄漏点。 如果 TDE 是在 smgr 层做的(缓冲区里是明文、写盘时加密),那么 WAL 里的 FPI 记录的是明文页 —— 加密表的数据会原封不动地漏进 WAL。 只要集群里存在任何一张加密表,WAL 加密就必须强制开启,不能是两个独立开关。 实现上做成一个集群级的 data_encryption = on,或者至少让 CREATE ENCRYPTION POLICY 在 WAL 加密未开启时直接报错。这是易用性设计里最重要的一条:不要把一个"配错了就静默泄密"的组合留给用户。 ...

September 7, 2026 · 4 min · 684 words · Me

Vastbase 数据库研发过程安全分析报告

August 14, 2026 · 0 min · 0 words · Me

c++

1 容器 1.1 基本概念 c++ stl 对象 指针 引用 迭代器 容器接口 1.1 接口 // 1.1 vector —— 动态数组 vector<int> v = {1, 2, 3}; v.push_back(4); // 末尾添加 v.pop_back(); // 删除末尾 v.size(); // 元素个数 v.empty(); // 是否为空 v[0]; // 随机访问(无边界检查) v.at(0); // 随机访问(边界检查) v.front(); v.back(); // 首/尾元素 v.clear(); // 清空 // 1.2 deque —— 双端队列 deque<int> d = {1, 2}; d.push_front(0); // 头插 d.push_back(3); // 尾插 d.pop_front(); // 头删 d.pop_back(); // 尾删 d.front(); d.back(); // 首/尾访问 d.size(); d.empty(); // 1.3 list —— 双向链表 list<int> l = {1, 2, 3}; l.push_front(0); l.push_back(4); l.pop_front(); l.pop_back(); l.remove(2); // 删除所有值为2的元素 l.size(); l.empty(); l.front(); l.back(); // 1.4 set —— 有序唯一集合 set<int> s = {3, 1, 4, 1}; // 实际存储 {1,3,4} s.insert(2); // 插入 s.erase(3); // 删除指定值 s.find(4); // 查找,返回迭代器,未找到返回 end() s.count(1); // 计数(0或1) s.size(); s.empty(); // 允许重复元素用 multiset,接口基本相同 // 1.5 map —— 有序键值对 map<string, int> ages; ages["Alice"] = 25; // 插入/修改;注意:若 key 不存在,[] 会自动插入一个默认值(0) ages["Bob"] = 30; ages.erase("Alice"); // 删除 ages.find("Bob"); // 查找,不想触发自动插入就用 find 而不是 [] ages.count("Tom"); // 计数 ages.size(); ages.empty(); // 允许重复key用 multimap,接口基本相同 // 1.6 unordered_set —— 哈希无序集合 unordered_set<int> us = {3, 1, 4, 1}; us.insert(2); us.erase(4); us.find(3); // O(1) 查找 us.count(1); us.size(); us.empty(); // 1.7 unordered_map —— 哈希无序键值对 unordered_map<string, int> scores; scores["Tom"] = 95; scores["Jerry"] = 88; scores.erase("Tom"); scores.find("Jerry"); scores.count("Bob"); scores.size(); scores.empty(); // 1.8 stack —— 栈(LIFO) stack<int> st; st.push(1); // 入栈 st.push(2); st.top(); // 查看栈顶 st.pop(); // 出栈(无返回值) st.empty(); st.size(); // 1.9 priority_queue —— 优先队列(默认最大堆) priority_queue<int> pq; pq.push(5); pq.push(1); pq.push(10); pq.top(); // 最大元素(10) pq.pop(); // 移除堆顶 pq.empty(); pq.size(); // 想要最小堆:priority_queue<int, vector<int>, greater<int>> minPq; // 1.10 pair —— 两个值的组合,不用专门定义 struct pair<string, int> p1 = {"Alice", 25}; p1.first; // "Alice" p1.second; // 25 pair<int, int> p2 = make_pair(1, 2); // 另一种构造写法 // 1.11 string —— 字符串(可以当成 char 的容器,替代 char* + strcpy/strcat 那一套) string s2 = "hello"; s2 += " world"; // 拼接 s2.size(); s2.length(); // 长度(两个等价) s2.empty(); s2[0]; // 下标访问 s2.substr(1, 3); // 从下标1开始取3个字符,"ell" s2.find("wor"); // 查找子串,返回起始下标,找不到返回 string::npos s2.replace(0, 5, "Hi"); // 替换 s2.append("!"); // 追加 to_string(42); // int -> string stoi("123"); // string -> int s2.c_str(); // 要传给 C 函数(如 fopen)时转成 const char* // 1.12 array —— 固定大小数组(比原生C数组多了 .size() 等接口,但不能动态扩容) array<int, 3> a = {1, 2, 3}; a.size(); a[0]; a.fill(0); // 全部填充为0 1.2 其他 对所有容器通用 ...

August 13, 2026 · 4 min · 782 words · Me

VexDB 数据库安全自评价报告

版本号 日期 修改说明 编制人 审核人 1.0 2026.07.24 完成初稿 沈坤 - 1、核心资产 VexDB 的核心资产分为七类,覆盖数据、结构、访问、运行、审计、内存和密码资源,是数据库安全保护的主要对象。 核心资产 资产内容 资产价值 数据资产 业务数据、用户数据、交易数据等存储内容 数据库核心资源。泄露、篡改或丢失影响业务安全 数据库结构资产 模式、表、字段、索引、视图、存储过程、函数、约束等 描述数据组织和业务逻辑。非法修改影响业务正确性 数据库管理资产 用户、角色、权限、配置参数、安全策略等 控制访问范围和运行行为。错误配置影响整体安全 数据库运行资产 实例、进程、数据文件、日志文件及计算存储资源 支撑数据库服务运行。破坏导致服务不可用 数据库操作记录资产 访问日志、审计记录、运行日志、管理操作记录等 支撑安全分析、事件追踪和责任认定 数据库内存资产 内存中的业务数据、缓存、会话信息和认证凭证 运行过程中的敏感信息。泄露可能导致数据或凭证暴露 密码与密钥资产 加密密钥、口令摘要、认证凭证等密码资源 支撑身份认证和数据保护。泄露可能导致安全机制失效 核心资产的机密性、完整性和可用性,决定数据库安全运行和业务连续性。 2、安全风险和应对措施 VexDB 面临外部攻击、内部误操作、权限滥用和运行环境异常等风险,可能导致非法访问、数据泄露、数据篡改、身份冒用和服务不可用。主要风险与应对措施如下。 安全风险 风险描述 应对措施 非法访问风险 非授权主机连接数据库,获取非法访问入口 网络防火墙 身份认证风险 弱口令、凭证泄露或认证缺陷导致身份冒用 身份认证 通信安全风险 网络传输被窃听、伪造、重放或篡改 安全传输 权限控制风险 权限配置不当或权限提升导致越权访问 访问控制 数据安全风险 数据存储、传输、处理过程中发生泄露或篡改 透明加密、驱动加密、机密计算、动态脱敏、数据防篡改 密钥安全风险 密钥泄露、丢失或生命周期管理不足导致保护失效 密钥管理 操作追溯风险 数据访问和管理操作缺少记录,无法有效追责 数据库审计、数据防篡改 服务可用性风险 恶意请求或资源异常消耗导致性能下降或服务中断 资源安全 运行环境风险 不可信环境或异常运行环境导致数据暴露风险 驱动加密、机密计算、密钥管理 VexDB 通过网络防护、身份认证、访问控制、数据保护、密码保护、安全审计和资源管理等能力,降低非法访问、数据泄露、数据篡改和服务不可用等安全风险。 3、安全机制 VexDB 从接入、传输、访问、存储、计算、合规六个维度构建防御模型,各安全机制相互独立又相互配合。 ...

July 29, 2026 · 8 min · 1634 words · Me

数据库安全 防篡改

CREATE SCHEMA s1 WITH BLOCKCHAIN; CREATE TABLE s1.t1(c1 INT, c2 TEXT); \d s1.t1 \d blockchain.s1_t1_hist INSERT INTO s1.t1 VALUES(1, 'aa'), (3, 'bb'), (7, 'cc'), (10, 'dd'); SELECT *,hash FROM s1.t1; SELECT * FROM blockchain.s1_t1_hist; # hahs_ins,hash_del,pre_hash SELECT * FROM gs_global_chain; # relnsp,relname,relhash,globalhash,txcommand SELECT ledger_hist_check('s1', 't1'); SELECT ledger_gchain_check('s1', 't1'); 分布式 CREATE SCHEMA s1 WITH BLOCKCHAIN; CREATE TABLE s1.t1(c1 INT, c2 TEXT); SELECT create_distributed_table('s1.t1', 'c1'); INSERT INTO s1.t1 VALUES(1, 'aa'), (2, 'bb'), (3, 'cc'), (7, 'dd'), (10, 'ee'); SELECT *,hash FROM s1.t1; SELECT * FROM blockchain.s1_t1_hist; -- hahs_ins,hash_del,pre_hash, 其中,pre_hash没用上,无作用 SELECT * FROM gs_global_chain; -- relnsp,relname,relhash,globalhash,txcommand SELECT * FROM ledger_hist('s1', 't1'); SELECT * FROM ledger_gchain(); SELECT ledger_hist_check('s1', 't1'); SELECT ledger_hist_archive('s1', 't1'); SELECT ledger_hist_repair('s1', 't1'); SELECT ledger_gchain_check('s1', 't1'); SELECT ledger_gchain_archive(); SELECT ledger_gchain_repair('s1', 't1'); 集中式 CREATE SCHEMA s1 WITH BLOCKCHAIN; CREATE TABLE s1.t1(c1 INT, c2 TEXT); INSERT INTO s1.t1 VALUES(1, 'aa'), (2, 'bb'), (3, 'cc'), (7, 'dd'), (10, 'ee'); SELECT *,hash FROM s1.t1; SELECT * FROM blockchain.s1_t1_hist; SELECT * FROM gs_global_chain; SELECT ledger_hist_check('s1', 't1'); SELECT ledger_hist_archive('s1', 't1'); SELECT ledger_hist_repair('s1', 't1'); SELECT ledger_gchain_check('s1', 't1'); SELECT ledger_gchain_archive(); SELECT ledger_gchain_repair('s1', 't1'); -- 下面2个函数,不用适配,别动代码,告诉我当前表现 -- SELECT * FROM ledger_hist('s1', 't1'); -- SELECT * FROM ledger_gchain(); CREATE SCHEMA s1 WITH BLOCKCHAIN; CREATE TABLE s1.t1(c1 INT, c2 TEXT); ...

July 29, 2026 · 2 min · 327 words · Me

国测 claude

VSCode Claude Code 扩展配置 本文记录如何在 VSCode 中配置 Claude Code 扩展,接入第三方(海量/glm)模型服务,无需在本机维护环境变量,扩展启动时自动注入。 配置位置 VSCode 用户级配置文件: Windows:%APPDATA%\Code\User\settings.json (即 C:\Users\<用户名>\AppData\Roaming\Code\User\settings.json) macOS:~/Library/Application Support/Code/User/settings.json Linux:~/.config/Code/User/settings.json 打开方式:VSCode 中按 Ctrl + , 打开设置 → 右上角「打开设置 (JSON)」图标,或直接 Ctrl + Shift + P 输入 Preferences: Open User Settings (JSON)。 完整配置 将以下内容合并进 settings.json(注意 JSON 语法,最后一项末尾不要多逗号): { "claudeCode.environmentVariables": [ { "name": "ANTHROPIC_BASE_URL", "value": "http://172.16.105.104:3000" }, { "name": "ANTHROPIC_AUTH_TOKEN", "value": "sk-hR1tQQloyPW0ax9b7404D51285Ae4737A118457535Fc33Ae" }, { "name": "ANTHROPIC_MODEL", "value": "glm-5.2" }, { "name": "ANTHROPIC_DEFAULT_OPUS_MODEL", "value": "glm-5.2" }, { "name": "ANTHROPIC_DEFAULT_SONNET_MODEL", "value": "glm-5.2" }, { "name": "ANTHROPIC_DEFAULT_HAIKU_MODEL", "value": "glm-5" }, { "name": "CLAUDE_CODE_SUBAGENT_MODEL", "value": "glm-5" }, { "name": "CLAUDE_CODE_EFFORT_LEVEL", "value": "max" } ], "claudeCode.preferredLocation": "panel" } 环境变量说明 变量名 作用 说明 ANTHROPIC_BASE_URL API 基础地址 指向第三方中转服务(兼容 Anthropic 协议)。海量外网网关示例:http://172.16.105.104:3000 ANTHROPIC_AUTH_TOKEN 鉴权令牌 中转服务下发的 sk-xxx,等价于官方的 API Key ANTHROPIC_MODEL 默认模型 主对话使用的模型 ANTHROPIC_DEFAULT_OPUS_MODEL Opus 档模型 覆盖官方 Opus 映射,通常设为最强模型 ANTHROPIC_DEFAULT_SONNET_MODEL Sonnet 档模型 覆盖官方 Sonnet 映射,日常主力 ANTHROPIC_DEFAULT_HAIKU_MODEL Haiku 档模型 覆盖官方 Haiku 映射,轻量快模型,用于补全/摘要 CLAUDE_CODE_SUBAGENT_MODEL 子 Agent 模型 Task/Explore 等子任务使用的模型,建议用快模型省钱 CLAUDE_CODE_EFFORT_LEVEL 推理强度 max 表示最高推理强度(思考最深),可选 low/medium/high/max 扩展项 claudeCode.preferredLocation:控制 Claude Code 面板的默认停靠位置,可选 panel(底部面板)或 editor(作为编辑器标签页)。 ...

July 27, 2026 · 2 min · 336 words · Me

国测 vexdb

-- cn: 50000 -- dn1: 50005 -- dn2: 50010 vsql -d postgres -p 50000 -r SELECT * FROM PG_DIST_NODE; CREATE TABLE t1(c1 INT, c2 TEXT); SELECT create_distributed_table('t1', 'c1'); -- 创建8个分片,dn1和dn2,每个dn有4个分片,即4个表,表名为 t1_$oid SELECT * FROM pg_dist_shard; -- min和max是hash之后的值 SELECT * FROM pg_dist_shard_placement; SELECT * FROM pg_dist_partition; INSERT INTO t1 VALUES(1, 'aa'), (3, 'bb'), (7, 'cc'), (10, 'dd'); vsql -d postgres -p 50005 -r SELECT oid,relname FROM pg_class WHERE relname like '%t1%'; vsql -d postgres -p 50010 -r SELECT oid,relname FROM pg_class WHERE relname like '%t1%'; # cn SELECT create_distributed_table('t1', 'c1'); # --> shard 1 (dn1) SELECT worker_apply_shard_ddl_command (12042, 'CREATE TABLE public.t1 (c1 integer, c2 text) WITH (orientation=row, compression=no, fillfactor=80)'); # dn1 worker_apply_shard_ddl_command ddlnode = ParseTreeNode(sql) RelayEventExtendNames(ddlnode, sharid) # 在语法解析树中,把t1名称,修改为t1_$shardid ProcessUtilityParseTree SELECT worker_apply_shard_ddl_command (12042, 'ALTER TABLE public.t1 OWNER TO shenkun'); # --> shard 2 (dn2) SELECT worker_apply_shard_ddl_command (12043, 'CREATE TABLE public.t1 (c1 integer, c2 text) WITH (orientation=row, compression=no, fillfactor=80)'); SELECT worker_apply_shard_ddl_command (12043, 'ALTER TABLE public.t1 OWNER TO shenkun'); # --> shared 3 (dn1) ... # --> 一共8个分片,每个分片2条SQL! # cn INSERT INTO t1 VALUES(1,'aa'),(3,'bb'),(7,'cc'),(10,'dd'); exec_simple_query pg_parse_query pg_analyze_and_rewrite pg_plan_query [planner hook] distributed_planner CreateDistributedPlan CreateModifyPlan RouterInsertJob (deferredPruning=true) # 返回 CustomScan PortalStart ExecutorStart [DVecExecutorStart] DVecExecutorStart BeginCustomScan → DVecBeginScan DVecBeginModifyScan RegenerateTaskListForInsert BuildRoutesForInsert FindShardInterval ActiveShardPlacementList RebuildQueryStrings DeparseTaskQuery AppendShardIdToName # 生成改名后SQL PortalRun ExecutorRun [ExecutorRun_hook] DVecExecutorRun ExecCustomScan DVecExecScan AdaptiveExecutor RunDistributedExecution ... SendRemoteCommand StartRemoteTransactionBegin BeginTransactiionCommand # 生成:BEGIN ISOLATION LEVEL READ COMMITTED; AssignDistributedTransactionIdCommand # 生成:SELECT assign_distributed_transaction_id(0,20,'...'); SendRemoteCommand # 一次发送2条事务SQL SendRemoteCommand PQsendQuery # INTO t1_$shardid .. CoordinatedRemoteTransactionsPrepare .. SendRemoteCommand # 发送 REPARE TRANSACTION .. SendRemoteCommand # 发送 COMMIT PREPARED .. # --> shard 1 (dn1) BEGIN ISOLATION LEVEL READ COMMITTED; SELECT assign_distributed_transaction_id(0,20,'...'); INSERT INTO public.t1_12042 AS dvec_table_alias (c1, c2) VALUES (1,'aa'::text) REPARE TRANSACTION 'dvecx_...'; COMMIT PREPARED 'dvecx_...'; # 执行分布式事务 INSERT INTO public.t1_12042 AS dvec_table_alias (c1, c2) VALUES (1,'aa'::text) # --> shard 2 (dn2) INSERT INTO public.t1_12043 AS dvec_table_alias (c1, c2) VALUES (10,'dd'::text) # --> shared 3 (d1) ... # --> 一共8个分片,其中4个分片,各收到1条INSERT语句 # 多行在同一分片,INSERT语句合并 # cn SELECT * FROM t1 WHERE c1 > 10; exec_simple_query pg_parse_query pg_analyze_and_rewrite pg_plan_query [planner hook] distributed_planner CreateDistributedPlan GetRouterPlanType (一造 multi-shard fan-out(非 router 计划)) MultiLogicalPlanCreate (logical planner:建逻辑计划) CreatePhysicalDistributedPlan (physical planner) ├─ 为命中的每个分片建一个 Task(本表 8 个分片 → 8 个 Task) UpdateTaskQueryString DeparseTaskQuery deparse_shard_query AppendShardIdToName # t1 → t1_<shardId> # SELECT * + c1,c2 ; WHERE c1>10 → (c1 OPERATOR(pg_catalog.>) 10) # 包成 CustomScan 返回 PortalStart ExecutorStart [DVecExecutorStart] DVecExecutorStart BeginCustomScan → DVecBeginScan PortalRun ExecutorRun [ExecutorRun_hook] DVecExecutorRun ExecCustomScan DVecExecScan AdaptiveExecutor RunDistributedExecution AssignTasksToConnectionsOrWorkerPool # 8 个 Task 分给 DN1/DN2 的连接 ConnectionStateMachine StartRemoteTransactionBegin *发送: BEGIN + assign(每条 DN 连接首次用,只发一次) BeginTransactionCommand # 生成: BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED AssignDistributedTransactionIdCommand # 生成: SELECT assign_distributed_transaction_id(...) SendRemoteCommand → PQsendQuery *两条合并成一条发出 # 发送: SELECT c1,c2 FROM t1_<shardId> WHERE (c1>10) # DN1 上 4 条 (12042/12044/12046/12048), DN2 上 4 条 (COMMIT) RemoteTransactionCommit SendRemoteCommand → PQsendQuery # 只读 → 普通 COMMIT(无 PREPARE/COMMIT PREPARED,无 2PC) # COMMIT # --> shard 1 (dn1) SELECT c1, c2 FROM public.t1_12042 t1 WHERE (c2 OPERATOR(pg_catalog.>) 'cc'::text) SELECT * FROM t1 WHERE c2 > 'cc'; 密态: cn CREATE TABLE t1 (c1 ..) INSERT INTO t1 VALUES (..) SELECT c1,c2 FROM t1 WHERE .. dn CREATE TABLE t1_$shardid (c1 ..) INSERT INTO t1_$shardid VALUES (..) # values的值不变 SELECT c1,c2 FROM t1_$shardid WHERE .. # WHERE子句不变

July 27, 2026 · 3 min · 517 words · Me

专利 全密态 索引

1 专利名称 一种基于可信执行环境的数据库密态索引访问方法、系统及介质 2 技术背景 全密态数据库:一种由数据库提供的安全特性,指数据库在处理数据的过程中,确保数据在传输、计算、存储等全生命周期阶段,于任何不可信的介质或环境中,始终处于加密状态。 全密态数据库实现方案:目前,业界较成熟的方案,是基于可信执行环境,实现全密态数据库,该方案主要分为2个模块:1)驱动加密:应用向数据库发送SQL语句时,应用侧的数据驱动自动加密SQL语句中的数据,数据库接收与处理数据密文。2)机密计算:数据库无法再密文上进行计算,将密文发送至可信执行环境(TEE)中,由可信模块完成解密与计算。 数据库索引结构:数据库中,最常见的索引为b+树索引。以tpcc测试模型为例,数据量低于100亿条时,b+树一般不超过4层。每一层的节点,即索引节点,是固定大小的page,分root index-page,internal index-page,leaf index-page。1个index-page中,存储多个index-item。其中,root和internal index-page中的index-item,存储数据和下一层index-page的位置。leaf index-page中的index-item,存储数据和table-page的位置。 加密性能:在加解密数据时,影响加密性能的因素中,加密次数的影响远高于数据长度。例如,1次加密8k数据,比40次加密200字节数据的性能高10+倍。 密态索引:在全密态数据库中,数据库只存储数据密文,在等值、范围查询等场景,为提高查询效率,避免全表扫描,需要在密文上构造索引。因此,需要见密文传输至可行执行环境TEE中,在TEE中临时解密数据,比较数据大小,构造索引。 现有方案缺陷:在构造密态索引时,现有方案存在以下缺陷:1)交互开销高:以索引元组为粒度,与TEE交互,交互次数多,交互开销高。2)加解密开销高:在索引页内比较元组大小时,需要多次解密索引元组。对于顶层的索引页,访问评率高,加解密频率也较高。3)内核修改多:为适配TEE,对索引构造、索引查询、并发控制等修改多,破坏生态兼容性等。 3 发明内容 发明目的:本发明针对在密文数据上构造索引、扫描索引的场景,提供一种通用的、高性能、低改造的方案,基于可信执行环境,大幅降低交互开销、加解密开销,并且,充分复用索引分裂、并发访问的机制,对内核侵入修改度低。 技术方案: 本发明的关键创新如下: 构造索引:应用插入数据时,驱动以字段为粒度,加密数据。数据库接收数据密文,TEE解密数据,构造索引,并以索引页为粒度,重新加密数据。 访问索引:结合索引的访问特点,每个index-item不独立加密与解密,每次以index-page为粒度加密与解密,降低加解密次数。 发送索引:数据库向TEE发生索引时,每次以index-page为粒度发送,降低交互次数。 缓存索引:在TEE中,针对索引中root和internal page访问频率高、修改频率低的特点,缓存解密后的page,降低解密次数、与TEE的交互次数。 内核改造:数据库中,访问索引时,只在需要比较大小时,才与TEE交互,保留已有索引分裂、并发访问机制。 以tpcc模型为例,当warhouse为10000时: 基表:bmsql_customer表中,数据行数为3亿,表大小约250G 索引:bmsql_customer主键索引中,index-item数为3亿,索引文件大小约9.5G,索引层数为4层,每层page数量分别:1、17、4400、114万,每个page中page-item数量约260个。插入1条数据,index-page平均分裂次数为0.0034次。 在该场景中,使用本发明的方案,考虑index-page分裂、TEE缓存偶尔未命中等所有可能产生额外交互、加密、解密的情况下: 场景 与TEE交互次数 加密次数(TEE内) 解密次数(TEE内) 插入1条数据 < 2.01 < 1.01 < 1.01 查询1条数据 < 2.01 0 < 1.01 删除1条数据 < 2.01 < 1.01 < 1.01 4 附图及附图的简单说明 4.1 密态索引结构 密态索引中,所有index-page中,只存储数据密文。在TEE中,以page为粒度加密,PageHeader、PageTail中,不存储用户数据,无需加密。 此处,以一个简单的3层索引为例,展示明文索引、密态索引的区别: 4.2 密态索引插入流程 在图1的示例中,向索引中插入1条数据,流程如下: 上述流程中,步骤12至20可通过缓存优化。以tpcc为例,index-item为3亿时,索引层数为4,索引文件大小约9.5G,root page数为1,internal page数为17+4000,缓存大小为31.38MB。 5 具体实施方式 5.1 创建密态索引 管理员:创建密钥 CREATE DATA KEY dk1(..); 数据库驱动:通过密钥服务或密码机生成密钥,缓存密钥,向数据库发送密钥信息 数据库:在系统表中,存储密钥信息,包括:密钥名、密钥Oid等。 管理员:创建加密表和索引:CREATE TABLE t1(c1 INT ENCRYPTED BY dk1, c2 TEXT),CREATE INDEX i1 ON t1(c1); 数据库:存储加密信息,包括:表名、列名、密钥名等。 5.2 向索引插入1条数据 前置条件:已创建密态索引 应用:连接数据库 数据驱动:连接数据库,查询加密信息、密钥信息,并缓存 数据库驱动:从密钥服务或密码机获取密钥,与可信执行环境建立安全通道,并传输密钥 可信执行环境:缓存密钥 应用:向数据库存储数据:INSERT INTO t1 VALUES (13, ‘data1’); 数据库驱动:对SQL进行语法解析,识别加密列字段,并加密字段,并改写SQL:INSERT INTO t1 VALUESS (cipher[13], ‘data1’); 数据库:向基表t1插入数据(cipher[13], ‘data1’),准备构造索引 数据库:向TEE中,发送密文 cipher[13] 可信执行环境:解密cipher[13],获取明文(13) 可信执行环境:查找缓存的root page,如果未找到,请求数据库发送root page,解密并缓存root page 可信执行环境:在root page中,二分查找,获取internal page位置 可信执行环境:查找缓存的internal page,如果未找到,请求数据库发送internal page,解密并缓存internal page 可信执行环境:在internal page中,二分查找,获取leaf page位置 可信执行环境:请求数据库发送leaf page。解密leaf page 可信执行环境:如果leaf page已满,触发分裂流程,此处不展开说明 可信执行环境:在leaf pag中,二分查找,获取插入位置 可信执行环境:在leaf page中,插入数据(13, 基表t1中13的存储位置) 可信执行环境:加密leaf page,向数据库返回加密后的leaf page 数据库:重新存储加密后的leaf page 5.3 从索引中查找1条数据 查询流程,与插入流程大部分一致: ...

July 15, 2026 · 1 min · 201 words · Me

国测 安全架构

4 安全架构 4.1 威胁模型 数据库运行在复杂的环境中,在计算、传输、存储数据等阶段,攻击者可利用硬件、软件等漏洞,威胁数据库安全。本文以数据库为核心,缩短攻击链路,排除攻击者身份演变、攻击阶段演进等因素,构造简化的威胁模型: 一、角色 黑客 内部运维人员 内部研发人员 系统维护人员 供应链 网络中间人 机房管理人员 二、动机 售卖获利 勒索获利 情报窃取 蓄意报复 规避审计 炫耀技能 人为过失 三、目标 鉴别数据 用户表 系统表 事务日志 审计日志 内存数据 配置文件 四、技术 不可信IP登录 默认账户攻击 过期账号攻击 弱口令攻击 密码泄露 暴力破解 凭证重放 内存凭证残留 流量伪造 流量重放 证书伪造 未授权访问 越权访问 权限提升 权限滥用 磁盘窃取 恶意软件 操作系统隔离失效 数据文件篡改 供应链后门 侧信道内存嗅探 调试工具滥用 特权用户窥探 审计日志伪造 攻击行为隐匿 恶意操作抵赖 合规审计证据缺失 五、分类 欺骗 篡改 否认 信息泄露 拒绝服务 权限提升 4.2 防御模型 针对威胁模型,本文从接入、传输、访问、存储、计算、合规6个维度,提供以下安全功能,构建防御模型: 接入安全:合法用户,才能接入数据库 网络防火墙 身份认证 传输安全:与数据库的通信数据, 安全传输 访问安全 访问控制 计算安全 驱动加密 机密计算 密码函数 存储安全 透明加密 合法合规 安全审计 动态脱敏 密钥管理 防御模型如下图所示: ...

July 6, 2026 · 1 min · 154 words · Me

ai

# 角色 你是一名 PostgreSQL 16 内核开发工程师,精通 src/backend/access/transam 及相关模块源码。 # 约束 1. 所有回答必须严格基于 PostgreSQL 16 Release 源码。 2. 解释机制时,必须引用具体的 .c/.h 文件路径和关键函数名。 3. 涉及数据结构时,请给出 struct 定义所在的头文件及字段含义。 4. 禁止使用“可能”、“通常”等模糊词汇描述内核行为;若不确定或版本不符,请明确告知。 5. 代码片段必须标注来源文件及大致行号范围(或函数上下文)。 # 当前任务 - 请梳理 XactBegin() 到 XactCommit() 的核心调用链,重点说明 CriticalSection 的作用。 - 解释 PG16 中 clog (pg_xact) 的写入与刷盘时机,结合 TransactionIdSetPageStatus 函数分析。 - MVCC 快照获取逻辑在 GetSnapshotData 中是如何与活跃事务列表交互的? - 两阶段提交 (2PC) 在 PG16 中的状态持久化流程是什么?涉及哪些 WAL record 类型? # 输出格式 1. 核心流程图/调用链(文字描述即可) 2. 关键源码位置(文件:函数) 3. 设计意图与权衡(Why it is implemented this way) 4. 相关 GUC 参数及其对代码路径的影响

July 3, 2026 · 1 min · 78 words · Me
心情不好的时候可以点一下 🐱
×
🤖 Doubao AI ×
Hi! 我是你的技术助手。关于代码、架构或 Bug,随时问我!🚀