Files
STP/docs/architecture/招标系统-加密-开发使用.md

397 lines
21 KiB
Markdown
Raw Permalink 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.
# 滨化集团智慧招标平台(STP)数据安全机制设计
---
## 1. 总体安全策略与目标
为确保招标全流程数据的机密性、完整性和可用性,针对内外部威胁(包括具备服务器操作权限的开发人员、DBA、运维人员),建立 **“数据全程加密、密钥动态漂移、权限最小化、AI按需脱敏”** 的纵深防御体系。所有加密与密钥管理均在应用层和内存中实现。
**核心目标**
- **防窥探**:即使攻击者获得服务器操作权限,也无法直接读取数据库中的招标敏感数据(如投标报价、专家打分、关联关系图谱)。
- **防泄露**:静态文件加密存储,传输全程TLS 1.3加密,密钥在内存中动态漂移,杜绝落盘。
- **防越权**:前后端双重权限校验,AI Agent仅能通过流程状态门控获取被授权数据,禁止通过对话方式旁路获取受限信息。
- **可审计**:所有数据访问、密钥迁移、AI调用行为均记录不可篡改日志(使用哈希链+数字签名代替区块链)。
---
## 2. 密钥管理机制:内存动态漂移 + 应用层分割
### 2.1 设计原则
- **密钥永不落盘**:加密密钥(数据密钥、文件密钥)仅在服务器内存中生成和存储,禁止写入任何持久化存储(磁盘、SSD、数据库)。
- **动态漂移**:密钥的存储内存地址每隔若干小时随机迁移,同时变更密钥本身(旧密文使用旧密钥解密后使用新密钥重加密),降低内存被暴力扫描窃取的风险。
- **密钥分割**:单条数据密钥被分割为2~3个分片,保存在不同进程/容器的内存区域,使用时分片聚合,用完即时销毁。
### 2.2 具体实现
| 组件 | 技术方案 |
| :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **数据加密密钥 (DEK)** | 每条招标项目、投标文件、专家评分记录使用独立 DEK。DEK 由应用服务在内存中随机生成,永不落盘。DEK 的密文可存储于数据库,但主密钥仅在内存中。 |
| **主密钥 (MEK)** | 每个微服务实例启动时,从配置中心读取一个种子口令,通过 PBKDF2 派生出一个 32 字节的主密钥,仅存于内存。该主密钥用于加密所有 DEK。主密钥不漂移,但服务重启时会重新派生。 |
| **密钥分割** | 不使用复杂的秘密共享算法,简化实现:将 32 字节 DEK 切分为两段各 16 字节,分别存放于两个不同微服务容器的内存中。需要解密时,两个片段临时聚合,用完后立即清零。 |
| **内存漂移调度器** | 独立微服务 `KeyDrifter`,每 4 小时(可配置)触发:<br>1. 扫描所有活跃 DEK 标识;<br>2. 生成新的随机内存地址(不同进程/堆区域),生成新 DEK;<br>3. 从旧地址读取旧 DEK,解密数据后用新 DEK 重加密,并将加密后 DEK 存回数据库;<br>4. 更新内存索引,清零旧内存区域。 |
| **内存保护** | 使用 `mlock()` 系统调用锁定内存页,防止被 swap 到磁盘;使用 `mprotect()` 设置非执行权限;敏感内存区域使用 `zeroize` 库在释放前覆盖。 |
### 2.3 密钥生命周期
```
[生成] 首次写入加密字段时,由应用服务生成 DEK(随机字节) → 分割为两片段 → 分片存入不同服务内存。
[使用] 业务服务请求解密 → 聚合分片 → 解密后立即销毁聚合缓存。
[漂移] KeyDrifter 锁住当前进程内存 → 新内存区生成新 DEK → 复制数据并重加密 → 更新数据库中的密文(DEK 仍使用同一个 MEK 加密存储) → 释放旧区。
[销毁] 项目归档期满后,删除 DEK 内存引用,内存页清零,数据库中对应的加密 DEK 字段标记为已删除(但物理数据无法解密)。
```
---
## 3. 静态数据加密
### 3.1 数据库加密
| 加密粒度 | 实施方案 |
| :-------- | :----------------------------------------------------------------------------------- |
| **透明加密** | 使用磁盘加密作为基础防护,防止物理磁盘被盗。但透明加密不防止 DBA 直接读取数据库文件,因此仍需字段级加密。 |
| **字段级加密** | 对极端敏感字段采用应用层字段加密:每个字段使用独立 DEK,DEK 密文存储在同一行的单独列中。加密算法:AES-256-GCM,附加认证数据(AAD)为表名+行ID。 |
| **索引混淆** | 加密字段不能直接用于条件查询,采用确定性加密生成可搜索的盲索引,盐值也存在于内存中,定期轮换并重建索引。 |
### 3.2 静态文件加密
所有上传文件(投标书PDF、资质扫描件、专家承诺书、音视频记录)采用信封加密:
1. 每个文件随机生成文件密钥,内存中保存。
2. 使用 FEK 对文件进行AES-256-GCM加密,分块上传(每块 4MB),每块独立加密。
3. FEK 使用主密钥加密后,作为文件元数据的一部分存储于对象存储的 `metadata` 字段或单独数据库表。
4. 文件在对象存储中始终处于密文状态,即使直接拷贝也无法读取。
5. 文件访问时,应用服务器从内存中获取 MEK → 解密 FEK → 用 FEK 解密文件流 → 传输给授权前端,不落地。
### 3.3 备份与快照加密
- 数据库备份、对象存储快照必须使用独立的备份密码。
- 备份密钥由双人控制(分段存储于两个保险柜),恢复时需要两人输入各自的密码段。
---
## 4. 传输加密与 API 安全
### 4.1 全链路 TLS 1.3
- 所有对外服务(前端、API、Webhook)强制启用 TLS 1.3,禁用弱密码套件。
- 使用内部 CA 签发服务端证书,客户端验证服务端证书指纹。
- 服务间调用(微服务、AI Agent)采用 mTLS,双向认证。
### 4.2 API 请求签名
- 对外 API(供应商、第三方系统)需使用 OAuth2.0 Client Credentials 获取 token,请求头携带 `Authorization: Bearer <jwt>`
- 对关键操作(上传投标、修改报价)额外要求 **请求签名**`HMAC-SHA256(requestBody + timestamp + nonce, clientSecret)`,服务器校验签名及时间窗口(≤ 5 分钟)。
### 4.3 前端通信加密增强
- WebSocket 传输实时打分数据时,在 TLS 之上再次进行应用层非对称加密(使用服务器公钥加密 payload),即使 TLS 被中间人破解,也无法直接解析业务数据。
---
## 5. 前后端权限隔离与角色端口设计
### 5.1 角色与端口映射
平台为不同角色分配独立的访问端口(或子域名),并在网关层绑定最小权限策略:
### 5.2 前后端双重权限校验
- **前端**:登录后获取 JWT,JWT 中仅包含角色和用户 ID,不包含任何权限矩阵。前端根据角色代码展示不同菜单,但关键按钮(如“查看报价”)仍需要后端二次确认。
- **后端**:每个 API 调用都会执行 **Policy Enforcement Point (PEP)**,根据用户 ID + 资源 ID 查询:
- 用户是否属于该项目的相关角色(如:该专家是否被分配到该项目评委组)
- 当前流程状态是否允许访问该资源(例如:开标前任何人不能查看报价文件)
- 使用 **Casbin****OPA** 实现动态规则引擎,规则可热更新。
---
## 6. AI Agent 安全隔离与按需数据访问
### 6.1 角色独立 AI Agent 架构
每个角色(供应商、专家、招标专员、审批人、管理员)分别部署一个独立的 AI Agent 容器,使用不同的 API Key 和身份凭证。Agent 之间的内存和密钥完全隔离。
### 6.2 流程驱动的数据门控
Agent 在调用任何业务数据前,必须通过统一数据网关验证请求合法性。网关检查:
1. **角色匹配**:Agent 的 JWT 中角色声明是否与目标数据要求一致。
2. **流程状态**:查询招标项目的工作流引擎当前状态,根据前述“状态门控”决定是否放行。
3. **数据脱敏**:即使允许访问,返回的数据也会根据角色自动脱敏(如专家 Agent 只能看到技术标中隐去供应商名称的版本)。
**调用时序示例**(专家 Agent 获取技术标):
```mermaid
sequenceDiagram
participant ExpertAgent
participant DataGateway
participant WorkflowEngine
participant FileService
ExpertAgent->>DataGateway: GET /tender/T001/tech_bid?projectId=...
DataGateway->>WorkflowEngine: query project stage
WorkflowEngine-->>DataGateway: stage = "evaluating"
DataGateway->>DataGateway: 校验专家是否属于该项目评委组(内存中缓存)
DataGateway->>FileService: 获取加密文件流
FileService-->>DataGateway: 密文流 + 解密用 FEK(内存获取)
DataGateway->>DataGateway: 解密 -> 移除供应商名称、Logo(NLP 脱敏)
DataGateway-->>ExpertAgent: 脱敏后的技术标
```
### 6.3 AI 对话隔离:防止越狱查询
当流程状态为“数据不可见”时,AI Agent 进入教学/流程提醒模式:
- Agent 的上下文(system prompt)强制注入:`当前阶段禁止透露任何项目数据,包括报价、投标人名称、评分。若用户询问数据,统一回答:“暂未到查看时间,请等待系统通知。如需帮助,请描述您的问题(如:如何上传文件?)”。`
- 后端增加对话内容审计:每次用户询问,AI Agent 先将问题发送至越狱检测服务(基于语义相似度和正则),命中敏感词(“报价”、“分数”、“谁中标了”)且当前流程禁止时,直接拦截并记录异常日志。
- 对于普通操作教学(“如何修改密码”),使用独立的“小滨-助手”知识库(不含任何项目数据),不涉及数据查询。
**架构示意**
```
用户对话 → API网关 → 角色Agent → [对话安全过滤器] → 若允许,则查询数据网关;否则,仅调用公共知识库RAG。
```
### 6.4 Agent 调用审计
- 记录每个 Agent 发起的每一次数据请求(包括时间、项目ID、请求参数、返回数据指纹)。
- 审计日志写入哈希链日志表,防止管理员篡改。
---
## 7. 防开发人员/DBA 窥探的硬性措施
即使开发人员拥有服务器 root 权限或数据库管理员权限,也无法直接读取明文敏感数据。
### 7.1 数据库层面
- **应用层加密**:数据库管理员看到的 `price_enc` 字段是 Base64 乱码,没有内存中的 DEK 无法解密。
- **数据库连接账户隔离**:DBA 使用的 `root` 账户无法访问应用表(通过数据库行级安全策略 RLS 禁止),应用使用单独的 `app_user` 账户,该账户密码存放在配置中心(如 Vault),开发人员无法直接获取。
- **查询审计**:数据库审计插件记录所有 `SELECT` 操作,若发现 DBA 批量查询加密字段,自动告警并冻结账户。
### 7.2 服务器与内存
- **禁止交互式 shell**:生产服务器禁止开发人员直接 SSH 登录,所有操作必须通过堡垒机 + 动态令牌,且操作全程录像。
- **内核安全模块**:使用 SELinux/AppArmor 限制只有 `stp-app` 进程可读取 `/proc/self/mem` 中特定内存区域,其他进程(包括开发人员启动的调试器)无权限。
- **内存转储禁止**:内核参数设置 `vm.dumpable = 0`,防止 `ptrace``gcore` 导出内存内容。
- **动态漂移**:密钥每 4 小时迁移到不同进程内存,攻击者即使获得了某一时刻的内存快照,也只能看到已失效的密钥或分片。
### 7.3 开发与调试环境
- **脱敏数据镜像**:开发测试环境使用完全脱敏的伪造数据(通过数据脱敏工具生成),不包含真实供应商、报价。
- **密钥沙盒**:开发环境使用独立的种子口令,无法接触生产密钥。
- **CI/CD 隔离**:构建流水线中使用的变量(如数据库密码)来自 Vault 动态 secret,构建完成后立即失效。
---
## 8. 审计与监控(无区块链,改用哈希链)
### 8.1 审计日志保护(哈希链 + 数字签名)
不使用区块链,而是采用 **哈希链 + 数字签名** 保证日志不可篡改:
- 每条审计日志记录包含:`id``时间``操作者``操作内容``数据指纹`
- 每条日志的 `prev_hash` 字段指向前一条日志的哈希。
- 每小时,系统对当前哈希链的最新哈希值,使用审计专用私钥进行签名,并将签名值保存到外部(如另一个数据库表或文件)。
- 验证时,重新计算哈希链,比对签名。
### 8.2 审计内容范围
| 审计对象 | 采集内容 | 保留期限 | 存储方式 |
| :--- | :--- | :--- | :--- |
| 用户访问日志 | 谁、何时、从哪个 IP、访问了哪个 API、返回了哪类数据(脱敏后指纹) | 7 年 | 哈希链日志表 + 离线归档 |
| 密钥操作日志 | 密钥生成时间、漂移时间、销毁时间、涉及的内存地址范围(经过哈希) | 3 年 | 加密存储,仅合规人员可读 |
| AI Agent 调用日志 | Agent 角色、请求参数、是否被拦截、越狱检测结果 | 3 年 | 同上 |
| 数据库 DDL/DML | 所有 `INSERT/UPDATE/SELECT` 敏感表记录 | 永久 | 同步至独立 SIEM |
| 异常告警 | 单用户异常访问、密钥漂移失败次数 | 实时推送 | 飞书/短信通知安全运维 |
---
## 9. 存证功能
### 9.1 存证目标与原则
- **独立存证表**:存证记录独立于业务数据库,使用哈希链防止篡改。
- **可信时间戳**:对关键存证事件,调用第三方可信时间戳服务赋予法律效力。
- **与加密机制协同**:存证哈希基于解密后的明文(但只传哈希,不传明文)。
### 9.2 存证范围与触发事件
| 阶段 | 存证事件 | 存证内容(哈希对象) | 触发时机 |
| :------- | :-------- | :---------------- | :----------- |
| **委托** | 招标委托单提交审批 | 委托单全文JSON | 用户点击“发起审批” |
| | 委托审批通过 | 审批记录+签字意见 | OA回调“审批完成” |
| **立项** | 招标方案确认 | 招标方案PDF | 立项审批通过 |
| | 供应商短名单确认 | 短名单(供应商ID+推荐理由) | 短名单审批完成 |
| **文件编制** | 招标文件定稿 | 招标文件PDF | 文件加密发布前 |
| | 澄清/修改公告 | 澄清文件PDF | 发布前 |
| **投标** | 投标文件上传完成 | 投标文件哈希+上传时间戳 | 供应商上传加密文件成功后 |
| | 保证金缴纳凭证 | 银行回单PDF | 支付网关回调成功 |
| **开标** | 开标记录 | 开标现场音视频文件哈希+关键截屏 | 开标结束时 |
| **评标** | 评委打分 | 每个评委的评分表(含打分项) | 评委提交评分 |
| | 偏离度复核记录 | AI提醒+评委确认意见 | 评委复核确认 |
| **定标** | 评标报告 | 评标报告PDF | 报告定稿 |
| | 中标结果审批 | 定标审批单+领导签字 | 定标审批通过 |
| **合同** | 合同签订 | 电子合同PDF | 双方电子签章完成 |
| **归档** | 全项目归档包 | 所有存证哈希组成的Merkle树根 | 归档完成时 |
### 9.3 存证技术方案
| 层级 | 技术 | 用途 | 成本 |
| :--- | :--- | :--- | :--- |
| **第一层:内部哈希链** | SHA-256 + 前后哈希引用 | 内部防止日志篡改,快速验证,无需外部依赖 | 无 |
| **第二层:可信时间戳** | 联合信任时间戳、腾讯云时间戳等 | 赋予法律效力,诉讼时可出证 | 按次收费,约1-5元/次(仅重大项目调用) |
### 9.4 存证数据结构
```json
{
"evidence_id": "E_20260602_001",
"project_id": "T2026001",
"event_type": "bid_submit",
"event_time": "2026-06-02T10:30:00Z",
"content_hash": "sha256:7b3d...f2a1",
"content_meta": {
"file_name": "技术标.pdf",
"file_size": 2048576,
"original_storage_path": "encrypted://minio/bucket/..."
},
"signature": {
"signer": "system_evidence",
"signature_value": "base64..."
},
"prev_evidence_hash": "E_20260601_099_hash",
"cur_hash": "sha256:...",
"timestamp_proof": "https://timestamp.com/verify?hash=..." // 可选,仅重大项目
}
```
### 9.5 存证流程(以投标文件上传为例)
```mermaid
sequenceDiagram
participant Supplier
participant STP_App
participant Encryptor
participant Evidence_Service
participant TimeStamp_API
Supplier->>STP_App: 上传加密投标文件
STP_App->>Encryptor: 获取文件明文(临时解密)
Encryptor-->>STP_App: 明文流
STP_App->>STP_App: 计算 SHA-256(明文)
STP_App->>Encryptor: 销毁明文流
STP_App->>Evidence_Service: 发送存证请求(含哈希、项目ID、事件类型)
Evidence_Service->>Evidence_Service: 计算当前哈希链
Evidence_Service->>Evidence_Service: 签名(使用存证专用私钥)
Evidence_Service->>TimeStamp_API: 提交哈希值(仅关键事件)
TimeStamp_API-->>Evidence_Service: 返回时间戳证明URL
Evidence_Service->>STP_App: 存证完成,返回 evidence_id
STP_App->>Supplier: 上传成功,存证ID已记录
```
### 9.6 验证与司法出证
- **内部验证**:在平台“存证验证”页面输入项目号,系统重新计算当前数据哈希,与存证哈希比对,显示“通过”或“篡改”。
- **司法出证**:管理员导出指定项目的完整存证包(含所有事件的哈希链、签名、时间戳证书),提交法院。法院可通过第三方时间戳官网核验。
---
## 10. 与现有加密方案的集成点
| 现有安全组件 | 存证集成方式 |
| :---------------- | :----------------------------------------------- |
| **内存密钥漂移** | 存证服务使用独立内存区域,不参与漂移。密钥仍由 MEK 保护,无KMS。 |
| **字段级加密** | 存证时对**解密后的业务含义**(如报价金额数字)进行哈希,解密过程在安全沙箱中完成,用完即毁。 |
| **文件加密存储** | 存证哈希基于文件**解密后内容**计算。验证时,先解密文件,再比对哈希。 |
| **AI Agent 数据门控** | AI Agent 不能查询存证哈希值,只能由审计角色访问存证服务。 |
| **前后端权限隔离** | 存证服务单独开放端口,仅审计角色和系统管理员可调用。 |
---
## 11. 应急响应与备份
### 11.1 密钥丢失恢复
主密钥(MEK)派生自种子口令。若所有服务内存崩溃导致 MEK 丢失:
- 使用离线备份的种子口令(分段保存在不同保险柜,需双人提供)重新派生 MEK。
- 数据库中存储的 DEK 密文(用 MEK 加密)可以恢复,因为 MEK 不变(种子相同)。
- 种子口令生成后,使用 Shamir 秘密共享分割为5份,交给5个不同负责人。恢复时需要至少3人提供片段。
### 11.2 数据备份
- 全量备份(加密)每天一次,保留30天。
- 增量备份每6小时一次。
- 备份密钥由种子口令派生,恢复时需双人授权。
- 备份恢复演习每季度一次。
### 11.3 入侵响应
检测到内存扫描、暴力破解、异常数据导出行为 → 自动触发 **应急模式**
- 冻结当前所有用户会话
- 强制销毁所有内存中的 DEK(触发全部数据锁定)
- 通知安全团队介入
---
## 附录:加密机制全流程数据流示意图
```mermaid
graph LR
subgraph Client
A[前端/供应商]
end
subgraph DMZ
B[API网关<br>TLS + 签名验证]
C[WAF]
end
subgraph K8s集群
subgraph UserService[用户服务]
D[认证服务<br>颁发JWT]
end
subgraph BizService[业务微服务]
E[招标服务]
F[投标服务]
G[评分服务]
end
subgraph KeyDrifter[KeyDrifter]
H[密钥漂移器<br>内存管理]
end
subgraph AIAgents[AI Agents]
I[独立角色Agent]
J[越狱检测器]
end
subgraph DataLayer[Data Layer]
K[(加密数据库<br>字段级密文)]
L[(加密对象存储<br>MinIO)]
end
subgraph EvidenceLayer[存证层]
M[存证服务]
N[(哈希链日志表)]
O[可信时间戳API<br>(可选)]
end
P[内存密钥池<br>(无KMS,应用管理)]
end
A --> B --> C --> D
C --> E
E <--> P
E --> K
F --> L
G --> P
H --> P
I --> J
I --> E
I --> G
E -.->|关键事件| M
F -.->|投标文件| M
G -.->|评分| M
M --> N
M -.-> O
```