# apiSign demo

本仓库提供一个 **Kong → Agent** 链路的“签名 + 加密”HTTP demo（Go）。

目标：

- 仅保护 **Kong → Agent** 这一段（上游 → Kong 不在需求范围）。
- Kong→Agent：HTTP body **全量加密**（raw body bytes），并对关键元数据 + body hash 做签名。
- Agent→Kong：响应 **必须签名 + 加密**；Kong 必须验签并解密。
- 密钥 **静态配置**（`keygen` 生成本地 json 配置）。
- 约束参数可配置；防重放可关闭。

## 环境要求

- Go 1.22+（`go version`）

## 目录结构

- `cmd/keygen`: 生成 demo 静态密钥与 json 配置
- `cmd/kong-sim`: 模拟 Kong（HTTP server）
- `cmd/db-agent`: 模拟 Agent（HTTP server）
- `internal/crypto`: Ed25519、X25519+HKDF+AES-GCM
- `internal/proto`: header/envelope/canonical/AAD
- `internal/replay`: 可选防重放（内存 TTL）

## Setup & Run

以下命令均在仓库根目录执行。

### 最短运行清单（建议直接复制执行）

1) 生成配置

```bash
go run ./cmd/keygen -out ./demo
```

2) 启动 agent（建议先用 verbose 看清楚全过程）

```bash
go run ./cmd/db-agent -config ./demo/agent.json -verbose
```

3) 启动 kong（建议开启 dump-http 输出完整 HTTP 请求包）

```bash
go run ./cmd/kong-sim -config ./demo/kong.json -dump-http
```

4) 发送测试请求（SQL 只是作为 raw body 示例）

```bash
curl -sS \
  -X POST http://127.0.0.1:8080/proxy \
  -H 'Content-Type: text/plain' \
  --data 'SELECT 1;'
```

你会在：

- kong 日志里看到“结构化输出”与“raw HTTP 请求包（加密 body）”
- agent 日志里看到“接收原始请求 → 验签 → 解密 → 明文预览 → 响应签名+加密”

1) 编译检查（可选）

```bash
go test ./...
```

2) 生成 demo 配置与密钥

```bash
go run ./cmd/keygen -out ./demo
```

生成：

- `demo/kong.json`
- `demo/agent.json`

可选参数：

```bash
# 关闭防重放
go run ./cmd/keygen -out ./demo -antireplay=false

# 调整默认 TTL / 允许时钟偏差 / 最大 body
go run ./cmd/keygen -out ./demo -ttl-ms 300000 -skew-ms 300000 -max-body 2097152
```

3) 启动 db-agent（默认 `:8081`）

```bash
go run ./cmd/db-agent -config ./demo/agent.json
```

如果你希望 agent 打印更详细信息（接收原始请求、加密 envelope、canonical string/AAD、解密后的明文预览等），加上 `-verbose`：

```bash
go run ./cmd/db-agent -config ./demo/agent.json -verbose
```

4) 启动 kong-sim（默认 `:8080`，转发到 agent 的 `/v1/execute`）

```bash
go run ./cmd/kong-sim -config ./demo/kong.json
```

默认会输出“结构化”的 Kong→Agent 请求信息（URL / headers / 加密 envelope JSON）。

如果你希望输出“BurpSuite 风格”的原始 HTTP 请求（包含加密后的 body），加上 `-dump-http`：

```bash
go run ./cmd/kong-sim -config ./demo/kong.json -dump-http
```

5) 调用 kong-sim

上游→Kong 不加密，仅用于触发 Kong→Agent 的加密转发：

```bash
curl -sS \
  -X POST http://127.0.0.1:8080/proxy \
  -H 'Content-Type: text/plain' \
  --data 'SELECT 1;'
```

你会看到 kong-sim 返回 agent mock 的 JSON 结果。

## 如何验证“body 确实被加密”

- 查看 `db-agent` 日志：会打印解密后的 payload（截断输出），能看到明文 SQL/原始 body。
- 抓包查看 kong-sim→agent 的请求 body：应是 envelope JSON（`v/epk/salt/iv/ct`），而不是明文。

## 配置与参数

### keygen 参数

- `-out`：输出目录（默认 `./demo`）
- `-agent-url`：写入 kong 配置的 agent URL（默认 `http://127.0.0.1:8081/v1/execute`）
- `-antireplay`：是否启用防重放（默认 true）
- `-max-body`：最大 envelope body bytes（默认 1MiB）
- `-skew-ms`：允许时钟偏差窗口（默认 300000）
- `-ttl-ms`：默认有效期（默认 60000）

### 配置文件字段（demo/*.json）

你可以直接编辑生成的 `demo/kong.json` / `demo/agent.json`：

- `listenAddr`: 监听地址
- `agentUrl`: kong-sim 转发目标（仅 kong 配置）
- `protoHeader`: 协议版本标识（默认 `kong-agent-secure/1`）
- `limits.antiReplayEnabled`: 是否启用防重放（决定是否携带/校验 nonce）
- `limits.maxBodyBytes`: 最大 body
- `limits.maxClockSkewMs`: 最大时钟偏差
- `limits.defaultTTLms`: 默认 TTL

## 常见问题 / 排错

- `signature verify failed`
  - 确认 `demo/kong.json` 与 `demo/agent.json` 来自同一次 `keygen` 输出。
  - 确认 agent 的 `kongSignPub` 与 kong 的 `signingKey.publicB64` 匹配。

- `decrypt failed`
  - 确认 agent 的 `decryptKey` 与 kong 的 `agentEncPub` 匹配（同一对 X25519）。

- `replay detected` / `missing nonce`
  - 防重放启用时需要 nonce；可用 `keygen -antireplay=false` 或改配置关闭。

- `timestamp skew too large` / `request expired`
  - 调大 `limits.maxClockSkewMs`、`limits.defaultTTLms`，或确保机器时间一致。

## 注意

- Demo 使用明文 HTTP 便于观察；生产建议仍使用 TLS/mTLS。
- Demo 的“mock 执行”仅做日志输出与 echo，不连接真实数据库。
