# 阿里云百炼机密推理服务

> English version: [README.md](README.md)

## 项目简介

CMaaS（Confidential Model as a Service，机密推理服务）是一套基于可信执行环境（TEE，例如 Intel TDX）构建的可验证推理解决方案。它通过 TEE 隔离、端到端加密以及远程证明等机制解决 AI 推理过程中的数据隐私问题。

系统从以下三个关键维度构建信任：**安全通道（Secure Channel）** 提供端到端加密的通信链路；**可证明节点（Attested Node）** 提供可验证的执行环境；**可验证代码（Verified Code）** 提供可审计的软件供应链证明。三者共同提供完整的安全保证：

- **端到端加密**：在 HTTPS 之上建立业务层加密通道，覆盖从客户端到机密推理节点的完整链路。每台节点随机生成根私钥用于会话密钥协商，每次会话独立派生临时密钥；所有密钥仅驻留于加密的易失性存储中，不落盘、不持久化，会话结束即销毁
- **安全加固与度量**：依托芯片级硬件隔离与软件加固双重机制，对启动链路及运行时环境实施全链路度量；块存储层面，根分区基于 Merkle Tree 机制保障完整性，数据分区采用一次性密钥加密保障机密性
- **软硬件透明度**：客户端直接访问 TEE 厂商验证硬件生成的远程证明报告真实性，并检查透明日志服务以确认服务端软件制品的完整性

## 如何使用

### 总览

CMaaS 客户端 SDK 将各类安全加固机制的复杂性抽象为简单易用的 API，开发者只需做极小的代码改动，就能在应用中集成机密推理能力。

- **SDK 库** (`sdk/`)：核心客户端实现，包含远程证明、验证与加密逻辑
- **CLI 工具** (`cmd/cmaas-client/`)：演示 SDK 用法的命令行工具
- **OpenAI 兼容代理** (`cmd/openai-proxy/`)：基于 SDK 的 HTTP 服务，对外暴露 `/v1/chat/completions`，使现有的 OpenAI 客户端（Python/JS SDK、vLLM 压测工具等）无需改动即可接入机密推理服务
- **Anthropic 兼容代理** (`cmd/anthropic-proxy/`)：基于 SDK 的 HTTP 服务，对外暴露 `/v1/messages`，使 Anthropic SDK 和 Claude Code 仅需修改 `base_url` 即可接入机密推理服务

SDK 通过高层 `Client` API 在内部管理四个核心方面：

1. **连接管理**：管理 WebSocket 连接，支持会话复用与自动重连
2. **TEE 远程证明**：验证 TEE Quote 签名与 EventLog 完整性，并通过公钥缓存降低负载均衡部署下的开销
3. **透明日志验证**：基于透明日志服务校验 release manifest，确保推理节点运行的是经过审计的已知软件版本
4. **加密请求**：基于 RA 进行密钥协商，并对所有推理数据进行端到端加密

该设计确保明文 prompt 与响应永远不离开客户端内存或 TEE 隔离内存，从而在整个推理生命周期中提供端到端机密性。

### 快速开始（CLI）

CMaaS CLI 既是一个参考实现，也是机密推理的测试工具。

#### 构建与运行

```bash
cd cmd/cmaas-client
go build

# 基础用法
export DASHSCOPE_API_KEY=your_api_key
./cmaas-client \
  --endpoint wss://dashscope.aliyuncs.com/api-ws/v1/inference \
  --model    <your-confidential-model-name> \
  --prompt   "What is confidential computing?" \
  --stream
```

#### CLI 参数

| 参数 | 是否必填 | 默认值 | 说明 |
|------|----------|--------|------|
| `--endpoint` | 是 | *(无)* | ModelStudio WebSocket 网关地址（例如 `wss://dashscope.aliyuncs.com/api-ws/v1/inference`） |
| `--model`    | 是 | *(无)* | 用于网关路由的模型名 |
| `--prompt`   | 是 | *(无)* | 待发送的推理 prompt |
| `--stream`   | 否 | `false` | 是否启用流式模式 |

**注意**：必须通过 `DASHSCOPE_API_KEY` 环境变量传入用于鉴权的 API Key。

### 快速开始（SDK）

`ChatCompletionRequest` 的采样参数（如 `Temperature`、`TopP`、`MaxTokens`）沿用 OpenAI Chat Completion API 的命名习惯，便于上手。SDK 同时支持函数/工具调用（`Tools`、`ToolChoice`、`ParallelToolCalls`）、推理类（reasoning）模型（`ReasoningContent`/`Reasoning` 字段以及 `ThinkingTokenBudget`），以及通过 `Deltas` / `ToolCallChunks` 通道支持结构化流式输出。

```go
client, _ := sdk.NewClient(&sdk.Options{
    Endpoint: "wss://dashscope.aliyuncs.com/api-ws/v1/inference", // ModelStudio WebSocket 网关
    APIKey:   os.Getenv("DASHSCOPE_API_KEY"),                     // ModelStudio API Key
    Model:    "your-model-name",                          // ModelStudio 上的模型名
})
defer client.Close()

completion, _ := client.Chat(context.Background(), &sdk.ChatCompletionRequest{
    Messages: []sdk.Message{
        {Role: "user", Content: "What is confidential computing?"},
    },
    MaxTokens:   sdk.Int(2048),   // 最大响应 token 数（按需调整）
    Temperature: sdk.Float(0.7),  // 采样温度（按需调整）
})

// 已解密的推理结果
fmt.Println("Response:", completion.Content)

// 查看远程证明结果
fmt.Printf("Verified At: %v\n", completion.Attestation.VerifiedAt)
fmt.Printf("TEE Type: %s\n", completion.Attestation.Bundle.TEEType)
```

#### 流式推理

```go
completion, _ := client.Chat(ctx, &sdk.ChatCompletionRequest{
    Messages: []sdk.Message{{Role: "user", Content: "Write a story"}},
    Stream:   true,
    MaxTokens:   sdk.Int(2048),
    Temperature: sdk.Float(0.7),
})

// 边到达边打印流式分片
for chunk := range completion.Chunks {
    fmt.Print(chunk)
}
fmt.Println() // 流结束后补换行

// 查看远程证明结果
fmt.Printf("Verified At: %v\n", completion.Attestation.VerifiedAt)
fmt.Printf("TEE Type: %s\n", completion.Attestation.Bundle.TEEType)
```

#### SDK 配置项

当前 SDK 通过一个简洁的 `Options` 结构体进行配置：

```go
sdk.NewClient(&sdk.Options{
    Endpoint string     // ModelStudio WebSocket 网关地址（必填）
    APIKey   string     // ModelStudio API Key（必填）
    Model    string     // ModelStudio 上的模型名（必填）

    ReuseSession   bool             // 是否启用连接复用（默认 false）
    PubKeyCacheTTL time.Duration    // 服务端公钥缓存 TTL（默认 12h，-1 表示禁用）

    TransparencyLogType           transparency.LogType  // 透明日志服务类型（默认 "rekor-v1"）
    TransparencyConfig            any                   // 透明日志服务的具体配置（默认使用内置值）
    TransparencyReportDir         string                // 透明审计报告目录（默认随操作系统而定）
    DisableTransparencyReport     bool                  // 关闭本地透明审计报告持久化
})
```

**字段详解**：

- **`ReuseSession`**：开启后，WebSocket 连接会在多次 `Chat()` 调用之间保持，减少重复握手开销，适合高吞吐场景。

- **`PubKeyCacheTTL`**：远程证明验证需要从 TEE 厂商拉取 collateral，并查询透明日志的 inclusion proof，可能引入显著时延。为降低开销，SDK 支持对已验证的服务端公钥进行缓存。在负载均衡部署中，客户端可能连接到多个后端节点，缓存机制可以显著加速对已验证节点的再次连接。如希望强制每次都执行完整验证，可将该值设为 `-1` 以禁用缓存。

- **`TransparencyLogType`**：指定用于校验 release manifest 的透明日志服务，默认为 `"rekor-v1"`（[Sigstore Rekor](https://docs.sigstore.dev/logging/overview/)）。Rekor 验证使用 SDK 内置的公钥。

- **`TransparencyConfig`**：与具体透明日志服务相关的配置。对于 `rekor-v1`，可传入 `*transparency.RekorV1ServiceConfig` 来覆盖默认的 Rekor 服务地址或校验公钥；置为 `nil` 则使用内置默认值。

- **`TransparencyReportDir`**：指定可审计的透明报告存储目录。为空时使用各操作系统的默认目录：
  - macOS：`~/Library/Application Support/dashscope-confidential-maas/transparency-reports/`
  - Linux：`$XDG_DATA_HOME/dashscope-confidential-maas/transparency-reports/`
  - Windows：`%APPDATA%\dashscope-confidential-maas\transparency-reports\`

- **`DisableTransparencyReport`**：设为 `true` 可关闭本地透明审计报告的持久化。

### 协议兼容 HTTP 代理

针对已经基于 OpenAI 或 Anthropic 协议构建的集成场景，本仓库提供了两个基于 SDK 封装的 HTTP 本地代理。每个代理会维护一个大小为 `--workers` 的 CMaaS 客户端池，所有 HTTP 请求会被多路复用到该池上，从而限制并发的机密会话数量、超出部分会排队。两个代理均关闭了会话复用，因此每个请求都会在独立的临时会话中完整执行一次 TEE 远程证明 / 密钥协商 / 透明日志验证，之后才会将明文返回给调用方。

> **注意**：两个代理都应运行在用户的可信环境中。

#### OpenAI 兼容代理 (`cmd/openai-proxy/`)

实现了 OpenAI HTTP API 的相应功能，支持流式输出、函数/工具调用、推理类模型功能（`reasoning_content`、`thinking_budget`、`enable_thinking`）。

```bash
cd cmd/openai-proxy
go build

export DASHSCOPE_API_KEY=your_api_key
./openai-proxy \
  --endpoint wss://dashscope.aliyuncs.com/api-ws/v1/inference \
  --model    <your-model-name> \
  --listen   :8080 \
  --workers  8
```

提供的端点：

- `POST /v1/chat/completions`  —— OpenAI Chat Completions（支持流式与非流式）
- `GET  /v1/models`            —— 极简模型列表（返回 `--model` 参数中的模型名）

参数：

| 参数 | 是否必填 | 默认值 | 说明 |
|------|----------|--------|------|
| `--endpoint`  | 是 | *(无)*  | CMaaS WebSocket 网关地址 |
| `--model`     | 是 | *(无)*  | 用于网关路由的模型名 |
| `--listen`    | 否 | `:8080` | HTTP 监听地址 |
| `--workers`   | 否 | `8`     | CMaaS 客户端池大小（= 最大并发请求数） |
| `--cache-ttl` | 否 | `12h`   | 服务端公钥缓存 TTL（`0` 表示禁用） |

启动前需要在环境中设置 `DASHSCOPE_API_KEY`。

`curl` 调用 chat 端点示例：

```bash
curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<your-model-name>",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user",   "content": "What is confidential computing?"}
    ],
    "temperature": 0.7,
    "max_tokens": 128,
    "stream": false
  }'
```

OpenAI Python SDK 调用 chat completions 示例：

```python
from openai import OpenAI

client = OpenAI(base_url="http://localhost:8080/v1", api_key="ignored")
resp = client.chat.completions.create(
    model="<your-model-name>",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user",   "content": "What is confidential computing?"},
    ],
    temperature=0.7,
    max_tokens=128,
)
print(resp.choices[0].message.content)
```

#### Anthropic 兼容代理 (`cmd/anthropic-proxy/`)

对外提供 Anthropic Messages API，使官方 Anthropic SDK 以及 Claude Code CLI 能够直接接入 CMaaS 后端。代理会把 Anthropic 协议翻译成 SDK 内部的 OpenAI 形态请求；同时把响应再翻译回 Anthropic 风格的流式事件（`message_start` / `content_block_*` / `message_delta` / `message_stop`）。

```bash
cd cmd/anthropic-proxy
go build

export DASHSCOPE_API_KEY=your_api_key
./anthropic-proxy \
  --endpoint wss://dashscope.aliyuncs.com/api-ws/v1/inference \
  --model    <your-model-name> \
  --listen   :8081 \
  --workers  8
```

提供的端点：

- `POST /v1/messages` —— Anthropic Messages API（支持流式与非流式）
- `GET  /v1/models`   —— 仅包含 `--model` 参数所指模型的列表

参数与 OpenAI 代理保持一致（`--endpoint` 与 `--model` 必填；`--listen` 默认 `:8081`；`--workers` 默认 `8`；`--cache-ttl` 默认 `12h`）。同样需要在环境中设置 `DASHSCOPE_API_KEY`。

Anthropic Python SDK 调用示例：

```python
import anthropic

client = anthropic.Anthropic(base_url="http://localhost:8081", api_key="ignored")
resp = client.messages.create(
    model="<your-model-name>",
    max_tokens=128,
    messages=[{"role": "user", "content": "What is confidential computing?"}],
)
print(resp.content[0].text)
```

两个代理在日志中都会打印每个请求的关联 ID（`chatcmpl-…` / `msg_…`），并与 CMaaS 的 `task_id` 一起输出，便于把客户端侧的报错追踪到对应的推理节点会话。

#### 远程证明结果

每次推理都会绑定一个 `AttestationResult`，提供该 TEE 服务端节点身份与完整性的可见信息：

- **`VerifiedAt`**：执行远程证明的时间戳
- **`Bundle`**：完整的 attestation bundle，包含 TEE 类型、服务端公钥、TEE evidence 和透明日志数据

调用 `result.TEEDetailsJSON()` 可以拿到 TEE 相关关键字段的 JSON 表示。对于当前支持的 Intel TDX 环境，包括：

- **MRTD**：TD 初始度量（VM 配置与初始代码的度量）
- **RTMR[0-3]**：固件、内核、应用等运行时度量寄存器
- **TD Attributes**：Trust Domain 的配置属性
- **Debug Enabled**：TEE 是否处于 debug 模式

#### 透明日志验证

> 透明日志验证进一步加强了信任链：它确保推理节点上运行的是经过审计的、可知版本的软件，而不仅仅是某段恰好能产生合法 TEE 度量的代码。

在密钥协商过程中，SDK 会自动执行以下透明日志验证步骤：

1. **校验日志条目完整性**：对每条 proof 条目验证其 DSSE 签名信封、RFC 6962 Merkle 包含证明，并依据透明日志公钥校验签名后的 checkpoint
2. **校验 Payload 哈希**：确认 release manifest 经过 JCS 规范化后的 SHA-256 与日志条目中记录的 payload 哈希一致
3. **校验 TEE 度量**：将 TEE evidence 中的度量值（对于 TDX：Quote 中的度量、EventLog 中的 UKI 哈希与容器摘要）与已验证的 release manifest 中的预期值进行比对

任一步骤失败时，密钥协商即被中止，推理请求也不会真正下发。

**透明审计报告**

每次推理调用成功后，SDK 会自动在本地持久化一份透明审计记录。每份报告（文件名形如 `report_YYYYMMDD_HHMMSS.000.json`）包含：

- 本次请求的 prompt
- TEE 远程证明证据，以及解析后的关键字段（MRTD、RTMR、TD attributes 等）
- 透明日志数据（release manifest 与 proof entries）
- 各阶段的验证时间戳

这些报告提供了一份持久化在本地、可离线审计与安全复核的可验证轨迹。
