898 lines
28 KiB
Markdown
898 lines
28 KiB
Markdown
# 灵隙协议补充草案:去中心化身份与寻址
|
||
|
||
> 版本:0.1(草案)
|
||
> 状态:草案
|
||
> 层级:基础设施层
|
||
> 依赖:[灵隙原始协议](01_raw-protocol.md)
|
||
|
||
---
|
||
|
||
## 摘要
|
||
|
||
本草案定义了灵隙协议栈中去中心化场景下的 Agent 身份认证与发现机制,解决无中心化目录时的 AgentID 唯一性和可验证性问题。
|
||
|
||
---
|
||
|
||
## 1. 背景与目标
|
||
|
||
### 1.1 问题陈述
|
||
|
||
现有协议假设存在中心化的注册表(如灵脉 Meridian),但在以下场景中:
|
||
- 临时 P2P 网络
|
||
- 跨组织协作
|
||
- 离线/断网环境
|
||
- 边缘计算场景
|
||
|
||
中心化注册不可用,需要去中心化的身份认证与发现机制。
|
||
|
||
### 1.2 设计目标
|
||
|
||
| 目标 | 说明 |
|
||
|-----|------|
|
||
| 身份可验证 | AgentID 无法伪造或冒用 |
|
||
| 去中心化 | 无需中心化注册表 |
|
||
| 高可用 | 无单点故障 |
|
||
| 可扩展 | 支持大规模 Agent 网络 |
|
||
| 可读性 | 支持人类可读别名(可选) |
|
||
|
||
---
|
||
|
||
## 2. AgentID 生成规则
|
||
|
||
### 2.1 ID 结构
|
||
|
||
AgentID 由三部分组成:
|
||
|
||
```
|
||
AgentID = {namespace}:{key_hash}:{alias}
|
||
|
||
示例:
|
||
synapse:7hJ4x9K2mNpQ:llm-agent-01
|
||
synapse:3kM8nP5qRsTu:image-gen
|
||
did:synapse:abc123def456:chat-bot
|
||
```
|
||
|
||
| 部分 | 格式 | 说明 |
|
||
|------|------|------|
|
||
| namespace | string | 命名空间(如 `synapse`) |
|
||
| key_hash | base58 | 公钥哈希的前 16 字节 |
|
||
| alias | string(可选) | 人类可读别名 |
|
||
|
||
### 2.2 生成算法
|
||
|
||
```go
|
||
func GenerateAgentID(privateKey []byte, namespace string, alias string) string {
|
||
// 1. 从私钥派生公钥
|
||
publicKey := crypto.GeneratePublicKey(privateKey)
|
||
|
||
// 2. 计算公钥哈希
|
||
hash := sha3.Sum256(publicKey)
|
||
|
||
// 3. 取前 16 字节,Base58 编码
|
||
keyHash := base58.Encode(hash[:16])
|
||
|
||
// 4. 组装完整 ID
|
||
if alias != "" {
|
||
return fmt.Sprintf("%s:%s:%s", namespace, keyHash, alias)
|
||
}
|
||
return fmt.Sprintf("%s:%s", namespace, keyHash)
|
||
}
|
||
```
|
||
|
||
### 2.3 ID 特性
|
||
|
||
| 特性 | 说明 |
|
||
|------|------|
|
||
| 唯一性 | 相同公钥 → 相同 key_hash → 相同 AgentID |
|
||
| 不可伪造 | 无法在没有私钥的情况下生成有效 AgentID |
|
||
| 可验证 | 任何人都可以用公钥验证 AgentID 真实性 |
|
||
| 不可预测 | 私钥随机生成,key_hash 不可预测 |
|
||
|
||
---
|
||
|
||
## 3. 身份认证机制
|
||
|
||
### 3.1 自我认证原理
|
||
|
||
```
|
||
验证方程:
|
||
Verify(AgentID, PublicKey) = true/false
|
||
|
||
其中:
|
||
AgentID.key_hash = Base58(SHA256(PublicKey)[:16])
|
||
```
|
||
|
||
### 3.2 签名验证流程
|
||
|
||
```
|
||
发送方:
|
||
1. 用私钥对消息签名
|
||
2. 发送 (Message, Signature, PublicKey, AgentID)
|
||
|
||
接收方:
|
||
1. 用 PublicKey 重新计算 AgentID.key_hash
|
||
2. 与消息中的 AgentID.key_hash 比较
|
||
3. 如匹配,用公钥验证签名
|
||
4. 如签名有效,确认消息来源
|
||
```
|
||
|
||
### 3.3 消息签名格式
|
||
|
||
```go
|
||
type SignedMessage struct {
|
||
Message *UnifiedSynapseMessage // 原始消息
|
||
Signature []byte // 签名
|
||
PublicKey []byte // 公钥
|
||
AgentID string // Agent 标识
|
||
}
|
||
```
|
||
|
||
签名内容:
|
||
|
||
```
|
||
signature_content =
|
||
sender.agent_id |
|
||
sender.endpoint |
|
||
timestamp |
|
||
sha256(payload)
|
||
```
|
||
|
||
### 3.4 签名算法
|
||
|
||
| 算法 | 说明 |
|
||
|------|------|
|
||
| Ed25519 | 默认,高效且安全 |
|
||
| ECDSA-P256 | 兼容性选项 |
|
||
| RSA-2048 | 遗留系统兼容 |
|
||
|
||
---
|
||
|
||
## 4. 分布式发现协议
|
||
|
||
### 4.1 发现机制选择
|
||
|
||
| 场景 | 推荐机制 |
|
||
|------|---------|
|
||
| 小规模(<100 Agent) | 广播查询 |
|
||
| 中规模(100-10000) | 分层 DHT |
|
||
| 大规模(>10000) | 完整 Kademlia |
|
||
|
||
### 4.2 广播查询协议
|
||
|
||
适用于小型网络,无需复杂路由:
|
||
|
||
```
|
||
Agent A 想知道 Agent B 的 Endpoint:
|
||
|
||
1. A 广播查询请求:
|
||
{
|
||
type: "agent_lookup",
|
||
target_id: "B's AgentID",
|
||
requester_id: "A's AgentID"
|
||
}
|
||
|
||
2. 知道 B 的节点响应:
|
||
{
|
||
type: "agent_lookup_response",
|
||
target_id: "B's AgentID",
|
||
endpoint: "http://B:8080",
|
||
signature: "B's signature"
|
||
}
|
||
|
||
3. A 收到响应后,用 B 的公钥验证签名
|
||
```
|
||
|
||
### 4.3 分层 DHT 协议
|
||
|
||
适用于中等规模网络:
|
||
|
||
```
|
||
层级结构:
|
||
Level 0: 本地网络(局域网/子网)
|
||
Level 1: 组织内网络
|
||
Level 2: 跨组织网络
|
||
Level 3: 全局网络
|
||
|
||
查询流程:
|
||
1. 先在本地查询
|
||
2. 本地未找到,查询上一层
|
||
3. 直到找到或返回"未找到"
|
||
```
|
||
|
||
### 4.4 DHT 消息类型
|
||
|
||
| 消息类型 | 说明 |
|
||
|---------|------|
|
||
| `dht:ping` | 节点存活探测 |
|
||
| `dht:store` | 存储 Agent 记录 |
|
||
| `dht:find_node` | 查找附近节点 |
|
||
| `dht:find_value` | 查找 Agent 记录 |
|
||
| `dht:notify` | 通知记录更新 |
|
||
|
||
### 4.5 Agent 记录结构
|
||
|
||
```go
|
||
type AgentRecord struct {
|
||
AgentID string // Agent 唯一标识
|
||
Alias string // 人类可读别名(可选)
|
||
Endpoint string // 网络地址
|
||
PublicKey []byte // 公钥
|
||
TTL int64 // 记录有效期(秒)
|
||
Version uint64 // 版本号(递增)
|
||
Signature []byte // Agent 对以上字段的签名
|
||
Timestamp int64 // 发布时间戳
|
||
}
|
||
```
|
||
|
||
签名内容:
|
||
|
||
```
|
||
record_signature_content =
|
||
agent_id | alias | endpoint | public_key | ttl | version | timestamp
|
||
```
|
||
|
||
---
|
||
|
||
## 4.1 区块链发现方案
|
||
|
||
区块链提供了强信任的去中心化注册与发现机制,适合高价值、高安全要求的场景。
|
||
|
||
### 4.1.1 链上 Agent 注册表(智能合约)
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ Blockchain │
|
||
│ ┌─────────────────────────────────────────────────┐ │
|
||
│ │ AgentRegistry Contract │ │
|
||
│ │ ┌─────────────────────────────────────────┐ │ │
|
||
│ │ │ mapping(agentID => AgentRecord) │ │ │
|
||
│ │ │ - agentID: bytes32 │ │ │
|
||
│ │ │ - endpoint: string │ │ │
|
||
│ │ │ - publicKey: bytes │ │ │
|
||
│ │ │ - stake: uint256 │ │ │
|
||
│ │ │ - lastHeartbeat: uint256 │ │ │
|
||
│ │ │ - status: AgentStatus │ │ │
|
||
│ │ └─────────────────────────────────────────┘ │ │
|
||
│ └─────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────┘
|
||
▲ 注册 ▲ 查询
|
||
│ │
|
||
┌────┴────┐ ┌────┴────┐
|
||
│ Agent A │ │ Agent B │
|
||
└─────────┘ └─────────┘
|
||
```
|
||
|
||
**核心思想**:
|
||
- Agent 在区块链智能合约中注册身份
|
||
- 注册需要质押一定数量的代币作为保证金
|
||
- 心跳通过交易上链更新
|
||
- 查询通过调用合约 `lookup` 方法
|
||
- 所有注册信息不可篡改
|
||
|
||
### 4.1.2 智能合约实现
|
||
|
||
```solidity
|
||
// SPDX-License-Identifier: MIT
|
||
pragma solidity ^0.8.19;
|
||
|
||
contract AgentRegistry {
|
||
// Agent 状态
|
||
enum AgentStatus { None, Registered, Active, Suspended, Revoked }
|
||
|
||
// Agent 记录
|
||
struct AgentRecord {
|
||
bytes32 agentID; // Agent 标识(公钥哈希)
|
||
string endpoint; // 网络地址
|
||
bytes publicKey; // 公钥
|
||
uint256 stake; // 质押金额
|
||
uint256 lastHeartbeat; // 最后心跳时间
|
||
uint256 registerTime; // 注册时间
|
||
AgentStatus status; // 状态
|
||
bytes signature; // Agent 签名
|
||
}
|
||
|
||
// 配置
|
||
uint256 public registrationStake = 0.01 ether; // 注册押金
|
||
uint256 public heartbeatInterval = 1 hours; // 心跳间隔
|
||
uint256 public stakeAmount = 0.1 ether; // 质押要求
|
||
|
||
// 状态变量
|
||
mapping(bytes32 => AgentRecord) public agents;
|
||
mapping(address => bytes32) public addressToAgentID;
|
||
|
||
// 事件
|
||
event AgentRegistered(bytes32 indexed agentID, address indexed owner);
|
||
event AgentHeartbeat(bytes32 indexed agentID);
|
||
event AgentRevoked(bytes32 indexed agentID);
|
||
event AgentEndpointUpdated(bytes32 indexed agentID, string endpoint);
|
||
|
||
// 注册 Agent
|
||
function register(
|
||
bytes32 _agentID,
|
||
string memory _endpoint,
|
||
bytes memory _publicKey,
|
||
bytes memory _signature
|
||
) external payable {
|
||
require(msg.value >= registrationStake, "Insufficient stake");
|
||
require(agents[_agentID].status == AgentStatus.None, "Already registered");
|
||
|
||
// 验证签名:AgentID = keccak256(publicKey)
|
||
bytes32 derivedID = keccak256(_publicKey);
|
||
require(derivedID == _agentID, "AgentID does not match public key");
|
||
|
||
// 验证签名内容
|
||
bytes32 messageHash = keccak256(
|
||
abi.encodePacked(_agentID, _endpoint, msg.sender, block.timestamp)
|
||
);
|
||
require(
|
||
verifySignature(messageHash, _signature, _publicKey),
|
||
"Invalid signature"
|
||
);
|
||
|
||
agents[_agentID] = AgentRecord({
|
||
agentID: _agentID,
|
||
endpoint: _endpoint,
|
||
publicKey: _publicKey,
|
||
stake: msg.value,
|
||
lastHeartbeat: block.timestamp,
|
||
registerTime: block.timestamp,
|
||
status: AgentStatus.Registered,
|
||
signature: _signature
|
||
});
|
||
|
||
addressToAgentID[msg.sender] = _agentID;
|
||
emit AgentRegistered(_agentID, msg.sender);
|
||
}
|
||
|
||
// 心跳保活(可更新 Endpoint)
|
||
function heartbeat(
|
||
bytes32 _agentID,
|
||
string memory _newEndpoint,
|
||
bytes memory _signature
|
||
) external {
|
||
AgentRecord storage agent = agents[_agentID];
|
||
require(agent.status != AgentStatus.None, "Not registered");
|
||
|
||
// 验证签名
|
||
bytes32 messageHash = keccak256(
|
||
abi.encodePacked(_agentID, block.timestamp, _newEndpoint)
|
||
);
|
||
require(
|
||
verifySignature(messageHash, _signature, agent.publicKey),
|
||
"Invalid signature"
|
||
);
|
||
|
||
// 更新 Endpoint(如有变化)
|
||
if (bytes(_newEndpoint).length > 0 &&
|
||
keccak256(abi.encodePacked(_newEndpoint)) !=
|
||
keccak256(abi.encodePacked(agent.endpoint))) {
|
||
agent.endpoint = _newEndpoint;
|
||
emit AgentEndpointUpdated(_agentID, _newEndpoint);
|
||
}
|
||
|
||
agent.lastHeartbeat = block.timestamp;
|
||
emit AgentHeartbeat(_agentID);
|
||
}
|
||
|
||
// 查询 Agent 信息
|
||
function lookup(bytes32 _agentID) external view returns (AgentRecord memory) {
|
||
return agents[_agentID];
|
||
}
|
||
|
||
// 验证 Agent 是否活跃
|
||
function isActive(bytes32 _agentID) external view returns (bool) {
|
||
AgentRecord memory agent = agents[_agentID];
|
||
if (agent.status == AgentStatus.None || agent.status == AgentStatus.Revoked) {
|
||
return false;
|
||
}
|
||
// 检查心跳是否过期(3倍心跳间隔)
|
||
if (block.timestamp - agent.lastHeartbeat > heartbeatInterval * 3) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// 追加质押
|
||
function stakeMore(bytes32 _agentID) external payable {
|
||
AgentRecord storage agent = agents[_agentID];
|
||
require(agent.status != AgentStatus.None, "Not registered");
|
||
agent.stake += msg.value;
|
||
}
|
||
|
||
// 注销 Agent(可取回质押)
|
||
function revoke(bytes32 _agentID) external {
|
||
AgentRecord storage agent = agents[_agentID];
|
||
require(agent.status != AgentStatus.None, "Not registered");
|
||
require(agent.status != AgentStatus.Revoked, "Already revoked");
|
||
|
||
uint256 refund = agent.stake;
|
||
agent.stake = 0;
|
||
agent.status = AgentStatus.Revoked;
|
||
|
||
payable(msg.sender).transfer(refund);
|
||
emit AgentRevoked(_agentID);
|
||
}
|
||
|
||
// 验证签名(EIP-191)
|
||
function verifySignature(
|
||
bytes32 _message,
|
||
bytes memory _signature,
|
||
bytes memory _publicKey
|
||
) internal pure returns (bool) {
|
||
bytes32 ethSignedMessageHash = keccak256(
|
||
abi.encodePacked("\x19Ethereum Signed Message:\n32", _message)
|
||
);
|
||
|
||
address signer = recoverSigner(ethSignedMessageHash, _signature);
|
||
address expectedSigner = address(uint160(uint256(keccak256(_publicKey))));
|
||
|
||
return signer == expectedSigner;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.1.3 DID(Decentralized Identifiers)
|
||
|
||
本草案兼容 W3C DID 标准,支持标准的 DID 格式。
|
||
|
||
**DID 格式**:
|
||
|
||
```
|
||
did:synapse:{method-specific-id}
|
||
|
||
示例:
|
||
did:synapse:ethereum:0x1234abcd...5678
|
||
did:synapse:polygon:0xabcd...efgh
|
||
did:synapse:solana:7DeF...8901
|
||
did:synapse:key:z6MkpTHR...
|
||
```
|
||
|
||
**DID 方法**:
|
||
|
||
| 方法 | 说明 |
|
||
|------|------|
|
||
| `did:synapse:ethereum` | 基于以太坊链上注册表 |
|
||
| `did:synapse:polygon` | 基于 Polygon 链 |
|
||
| `did:synapse:solana` | 基于 Solana 链 |
|
||
| `did:synapse:key` | 基于公钥的离链 DID |
|
||
| `did:synapse:dht` | 基于 DHT 的离链 DID |
|
||
|
||
**DID Document 示例**:
|
||
|
||
```json
|
||
{
|
||
"@context": [
|
||
"https://www.w3.org/ns/did/v1",
|
||
"https://www.w3.org/ns/synapse/v1"
|
||
],
|
||
"id": "did:synapse:ethereum:0x1234abcd5678",
|
||
"verificationMethod": [{
|
||
"id": "did:synapse:ethereum:0x1234abcd5678#keys-1",
|
||
"type": "EcdsaSecp256k1VerificationKey2019",
|
||
"controller": "did:synapse:ethereum:0x1234abcd5678",
|
||
"publicKeyHex": "02b3..."
|
||
}],
|
||
"service": [{
|
||
"id": "did:synapse:ethereum:0x1234abcd5678#synapse-agent",
|
||
"type": "SynapseAgent",
|
||
"serviceEndpoint": "https://agent-01.example.com/api/synapse"
|
||
}],
|
||
"synapse:capabilities": ["text_generation", "image_generation"],
|
||
"synapse:agentName": "智能写作助手",
|
||
"synapse:version": "1.0.0"
|
||
}
|
||
```
|
||
|
||
### 4.1.4 区块链平台选择
|
||
|
||
| 平台 | 优点 | 缺点 | 适合场景 |
|
||
|------|------|------|---------|
|
||
| Ethereum | 生态最大、安全最高 | Gas 贵、延迟高 | 高价值交易、核心 Agent |
|
||
| Polygon | 低 Gas、快确认 | 中心化程度较高 | 中等价值、大量 Agent |
|
||
| Solana | 高吞吐、低延迟 | 稳定性偶有问题 | 高频心跳场景 |
|
||
| 联盟链 | 可控、隐私好 | 需要许可机制 | 企业内部、联盟合作 |
|
||
| L2 (Arbitrum) | 低 Gas、安全继承 | 复杂度较高 | 通用场景 |
|
||
| 本地私链 | 完全可控、零成本 | 信任范围有限 | 测试、内部系统 |
|
||
|
||
### 4.1.5 混合架构(推荐)
|
||
|
||
结合本地缓存、DHT 和区块链的三层架构,平衡性能和安全性:
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 查询路径(快→慢) │
|
||
│ │
|
||
│ Agent A │
|
||
│ │ │
|
||
│ │ 1. 本地缓存查询(内存,微秒级) │
|
||
│ │ ─────────────────────────── │
|
||
│ │ [cache hit] → 返回 │
|
||
│ │ [cache miss] │
|
||
│ │ │
|
||
│ │ 2. DHT 查询(网络,毫秒~秒级) │
|
||
│ │ ─────────────────────────── │
|
||
│ │ [dht hit] → 验证签名 → 更新缓存 → 返回 │
|
||
│ │ [dht miss] │
|
||
│ │ │
|
||
│ │ 3. 区块链查询(链上,秒~分钟级) │
|
||
│ │ ─────────────────────────── │
|
||
│ │ [chain hit] → 验证签名 → 广播DHT → 更新缓存 → 返回 │
|
||
│ │ [chain miss] → 未找到 │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**分层缓存实现**:
|
||
|
||
```go
|
||
type HybridLookup struct {
|
||
// L1: 本地缓存(内存,TTL 1分钟)
|
||
LocalCache map[string]*AgentRecord
|
||
|
||
// L2: DHT 网络(分钟级一致性)
|
||
DHT DHTClient
|
||
|
||
// L3: 区块链(最终一致性源)
|
||
Blockchain BlockchainClient
|
||
}
|
||
|
||
func (h *HybridLookup) Find(agentID string) (*AgentRecord, error) {
|
||
// 1. 查本地缓存
|
||
if record, ok := h.LocalCache.Get(agentID); ok {
|
||
if record.IsFresh() {
|
||
return record, nil
|
||
}
|
||
}
|
||
|
||
// 2. 查 DHT
|
||
if record, err := h.DHT.FindValue(agentID); err == nil {
|
||
// 验证签名
|
||
if record.VerifySignature() {
|
||
h.LocalCache.Set(agentID, record)
|
||
return record, nil
|
||
}
|
||
}
|
||
|
||
// 3. 查区块链(最终源)
|
||
if record, err := h.Blockchain.Lookup(agentID); err == nil {
|
||
// 验证链上签名(已由链上合约验证过)
|
||
h.LocalCache.Set(agentID, record)
|
||
// 广播到 DHT 加速后续查询
|
||
h.DHT.Store(agentID, record)
|
||
return record, nil
|
||
}
|
||
|
||
return nil, ErrAgentNotFound
|
||
}
|
||
```
|
||
|
||
### 4.1.6 链上治理与激励
|
||
|
||
区块链还可实现链上治理功能:
|
||
|
||
| 功能 | 说明 |
|
||
|------|------|
|
||
| 质押机制 | Agent 注册需质押代币,恶意行为被 slash |
|
||
| 信誉评分 | 链上可查的 Agent 信誉分 |
|
||
| 服务定价 | 智能合约自动结算任务费用 |
|
||
| 争议仲裁 | 链上投票仲裁 Agent 纠纷 |
|
||
| 协议升级 | 通过 DAO 投票决定协议升级 |
|
||
|
||
---
|
||
|
||
## 5. 身份冲突处理
|
||
|
||
### 5.1 冲突场景
|
||
|
||
| 场景 | 说明 |
|
||
|------|------|
|
||
| 同一公钥注册多个别名 | 允许(同一 Agent 的多个别名) |
|
||
| 不同公钥生成相同 AgentID | 不可能(公钥哈希唯一) |
|
||
| 伪造他人 AgentID | 不可能(无法伪造签名) |
|
||
| Endpoint 欺骗 | 需要额外验证 |
|
||
|
||
### 5.2 Endpoint 绑定验证
|
||
|
||
为防止 Endpoint 欺骗,引入双向认证:
|
||
|
||
```
|
||
1. Agent A 声称自己是 "synapse:abc123:agent-A"
|
||
并声称其 Endpoint 是 "http://A:8080"
|
||
|
||
2. Agent B 收到声明后:
|
||
a. 用 A 的公钥验证 AgentID 合法
|
||
b. 向 Endpoint 发送挑战
|
||
c. A 必须用私钥响应挑战
|
||
d. 响应通过,确认 Endpoint 有效
|
||
```
|
||
|
||
### 5.3 挑战-响应协议
|
||
|
||
```go
|
||
// 挑战消息
|
||
type Challenge struct {
|
||
ChallengeID string // 挑战 ID
|
||
Nonce []byte // 随机数
|
||
Timestamp int64 // 发送时间
|
||
}
|
||
|
||
// 响应消息
|
||
type ChallengeResponse struct {
|
||
ChallengeID string // 对应的挑战 ID
|
||
Nonce []byte // 原样返回的随机数
|
||
Signature []byte // 对 Nonce 的签名
|
||
}
|
||
|
||
// 验证流程
|
||
func VerifyEndpoint(endpoint string, publicKey []byte, challenge *Challenge) bool {
|
||
// 1. 发送挑战到 Endpoint
|
||
resp := SendChallenge(endpoint, challenge)
|
||
|
||
// 2. 验证响应
|
||
if resp.ChallengeID != challenge.ChallengeID {
|
||
return false // 挑战 ID 不匹配
|
||
}
|
||
if !bytes.Equal(resp.Nonce, challenge.Nonce) {
|
||
return false // Nonce 被篡改
|
||
}
|
||
|
||
// 3. 验证签名
|
||
return crypto.Verify(publicKey, challenge.Nonce, resp.Signature)
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6. 生命周期管理
|
||
|
||
### 6.1 状态流转
|
||
|
||
```
|
||
┌──────────────┐
|
||
│ offline │
|
||
└──────┬───────┘
|
||
│ 注册/上线
|
||
▼
|
||
┌──────────────┐
|
||
┌─────────│ online │─────────┐
|
||
│ └──────┬───────┘ │
|
||
│ │ 刷新 │ 心跳超时
|
||
│ ▼ │
|
||
│ ┌──────────────┐ │
|
||
│ │ active │ │
|
||
│ └──────┬───────┘ │
|
||
│ │ │
|
||
│ ┌─────────┴─────────┐ │
|
||
│ ▼ ▼ │
|
||
│ ┌──────────┐ ┌──────────┐ │
|
||
│ │ refreshing│ │ suspended │ │
|
||
│ └────┬─────┘ └────┬─────┘ │
|
||
│ │ │ │
|
||
└──────┴───────────────────┴───────┘
|
||
│
|
||
▼
|
||
┌──────────────┐
|
||
│ offline │
|
||
└──────────────┘
|
||
```
|
||
|
||
### 6.2 生命周期消息
|
||
|
||
| 状态 | 说明 | 触发条件 |
|
||
|------|------|---------|
|
||
| offline | 离线 | 初始状态或主动注销 |
|
||
| online | 上线中 | 注册完成,等待首次心跳 |
|
||
| active | 活跃 | 定期心跳维持 |
|
||
| refreshing | 刷新中 | 更新 Endpoint 或别名 |
|
||
| suspended | 挂起 | 心跳超时,未注销 |
|
||
| offline | 离线 | 注销或永久离线 |
|
||
|
||
### 6.3 消息类型
|
||
|
||
| 消息类型 | 方向 | 说明 |
|
||
|---------|------|------|
|
||
| `identity:register` | → 网络 | 注册 Agent 身份 |
|
||
| `identity:refresh` | → 网络 | 刷新注册信息 |
|
||
| `identity:challenge` | 双向 | Endpoint 验证挑战 |
|
||
| `identity:challenge_response` | 双向 | 挑战响应 |
|
||
| `identity:revoke` | → 网络 | 注销身份 |
|
||
| `identity:lookup` | → 网络 | 查询 Agent 信息 |
|
||
| `identity:lookup_response` | → 网络 | 查询响应 |
|
||
| `identity:announce` | → 网络 | 广播在线状态 |
|
||
| `identity:heartbeat` | → 网络 | 心跳保活 |
|
||
|
||
### 6.4 Register 载荷
|
||
|
||
```go
|
||
type IdentityRegisterPayload struct {
|
||
AgentID string // Agent 标识
|
||
Alias string // 人类可读别名
|
||
Endpoint string // 网络地址
|
||
PublicKey []byte // 公钥
|
||
TTL int64 // 注册有效期
|
||
Version uint64 // 版本号
|
||
Signature []byte // Agent 签名
|
||
}
|
||
```
|
||
|
||
### 6.5 Heartbeat 载荷
|
||
|
||
```go
|
||
type IdentityHeartbeatPayload struct {
|
||
AgentID string // Agent 标识
|
||
Endpoint string // 当前 Endpoint(可能变化)
|
||
TTL int64 // 续期时间
|
||
Signature []byte // Agent 签名
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 安全考虑
|
||
|
||
### 7.1 威胁模型
|
||
|
||
| 威胁 | 场景 | 防护措施 |
|
||
|------|------|---------|
|
||
| 身份伪造 | 攻击者声称自己是他人 | 公钥派生 ID + 签名验证 |
|
||
| Endpoint 欺骗 | 攻击者声称他人 Endpoint | 挑战-响应协议 |
|
||
| 重放攻击 | 攻击者重放旧消息 | 时间戳 + Nonce |
|
||
| 中间人攻击 | 拦截并修改消息 | TLS + 签名验证 |
|
||
| 女巫攻击 | 一个节点伪装多个身份 | 工作量证明或权益证明(可选) |
|
||
| 日食攻击 | 隔离目标节点 | 多路径查询 |
|
||
|
||
### 7.2 重放攻击防护
|
||
|
||
```go
|
||
type AntiReplay struct {
|
||
RecentNonces map[string]int64 // nonce -> timestamp
|
||
Window time.Duration // 时间窗口(5分钟)
|
||
}
|
||
|
||
func (a *AntiReplay) CheckAndAdd(nonce string, timestamp int64) bool {
|
||
// 1. 检查时间戳是否在窗口内
|
||
now := time.Now().Unix()
|
||
if now - timestamp > int64(a.Window.Seconds()) {
|
||
return false // 时间戳太旧
|
||
}
|
||
|
||
// 2. 检查 Nonce 是否已使用
|
||
if _, exists := a.RecentNonces[nonce]; exists {
|
||
return false // 重放
|
||
}
|
||
|
||
// 3. 记录
|
||
a.RecentNonces[nonce] = timestamp
|
||
return true
|
||
}
|
||
```
|
||
|
||
### 7.3 私钥保护
|
||
|
||
| 场景 | 建议 |
|
||
|------|------|
|
||
| 本地运行 | 使用密钥文件 + 操作系统密钥链 |
|
||
| 云端运行 | 使用 HSM/KMS |
|
||
| 嵌入式设备 | 使用 TPM |
|
||
| 多 Agent 共享 | 密钥分片(如 Shamir's Secret Sharing) |
|
||
|
||
---
|
||
|
||
## 8. 与现有协议的关系
|
||
|
||
### 8.1 与原始协议的整合
|
||
|
||
本草案扩展 [raw-protocol.md](01_raw-protocol.md) 中的 `AgentEndpoint`:
|
||
|
||
```go
|
||
type AgentEndpoint struct {
|
||
AgentID string // 扩展:基于公钥派生
|
||
AgentName string // 人类可读名称
|
||
SystemID string // 所属系统
|
||
Endpoint string // 回调端点
|
||
Version string // Agent 版本
|
||
|
||
// 新增字段
|
||
PublicKey []byte // 公钥(用于验证)
|
||
Namespace string // 命名空间
|
||
Alias string // 人类可读别名
|
||
}
|
||
```
|
||
|
||
### 8.2 与灵脉(Meridian)的整合
|
||
|
||
| 模式 | 行为 |
|
||
|------|------|
|
||
| 中心化可用 | 使用灵脉作为主注册表,本草案作为备份 |
|
||
| 去中心化 | 使用本草案的 DHT 机制,完全去中心化 |
|
||
| 混合模式 | 核心 Agent 使用中心化,边缘 Agent 使用去中心化 |
|
||
|
||
### 8.3 与灵玺(Sigil)的整合
|
||
|
||
| 组件 | 职责 |
|
||
|------|------|
|
||
| 灵玺(Sigil) | 密钥管理、签名验证 |
|
||
| 本草案 | ID 生成、发现协议、生命周期 |
|
||
|
||
---
|
||
|
||
## 9. 协议消息汇总
|
||
|
||
### 9.1 消息类型列表
|
||
|
||
| 类型 | 协议前缀 | 说明 |
|
||
|------|---------|------|
|
||
| `identity:register` | 前端 | 注册身份 |
|
||
| `identity:refresh` | 前端 | 刷新注册 |
|
||
| `identity:revoke` | 前端 | 注销身份 |
|
||
| `identity:challenge` | 前端 | 挑战请求 |
|
||
| `identity:challenge_response` | 前端 | 挑战响应 |
|
||
| `identity:lookup` | 前端 | 查询身份 |
|
||
| `identity:lookup_response` | 前端 | 查询响应 |
|
||
| `identity:announce` | 前端 | 广播在线 |
|
||
| `identity:heartbeat` | 前端 | 心跳保活 |
|
||
| `dht:ping` | DHT | 节点探测 |
|
||
| `dht:store` | DHT | 存储记录 |
|
||
| `dht:find_node` | DHT | 查找节点 |
|
||
| `dht:find_value` | DHT | 查找值 |
|
||
| `dht:notify` | DHT | 通知更新 |
|
||
|
||
---
|
||
|
||
## 10. 待解决问题(Open Issues)
|
||
|
||
| 问题 | 说明 | 优先级 |
|
||
|------|------|--------|
|
||
| 隐私保护 | 公钥哈希是否暴露身份? | 高 |
|
||
| 密钥轮换 | 私钥更换后如何保持 AgentID? | 高 |
|
||
| 名称冲突 | 人类可读别名可能重复 | 中 |
|
||
| 性能优化 | DHT 查找延迟 | 中 |
|
||
| 移动 Agent | Endpoint 频繁变化 | 低 |
|
||
| 链上 Gas 成本 | 区块链交易费用 | 中 |
|
||
| DID 方法注册 | W3C 标准 DID 方法注册流程 | 低 |
|
||
|
||
---
|
||
|
||
## 11. 实现建议
|
||
|
||
### 11.1 分阶段实现
|
||
|
||
**Phase 1(最小可行)**:
|
||
- 实现 AgentID 公钥派生
|
||
- 实现消息签名验证
|
||
- 使用广播进行发现
|
||
|
||
**Phase 2(基本功能)**:
|
||
- 实现分层 DHT
|
||
- 实现生命周期管理
|
||
- 实现挑战-响应协议
|
||
|
||
**Phase 3(完整功能)**:
|
||
- 实现完整 Kademlia
|
||
- 实现隐私保护
|
||
- 实现密钥轮换
|
||
|
||
### 11.2 推荐库
|
||
|
||
| 功能 | 推荐库 |
|
||
|------|--------|
|
||
| 加密签名 | golang.org/x/crypto/ed25519 |
|
||
| Base58 | github.com/mr-tron/base58 |
|
||
| DHT | github.com/anacrolix/go-libutp 或自实现 |
|
||
| 分布式存储 | etcd/consul(混合模式) |
|
||
|
||
---
|
||
|
||
## 12. 参考资料
|
||
|
||
- [Kademlia: A Peer-to-peer Information System Based on the XOR Metric](https://pdos.csail.mit.edu/~petar/papers/maymounkov-kademlia-lncs.pdf)
|
||
- [Self-Certifying File System (SFS)](https://pdos.csail.mit.edu/~petar/papers/sfs.pdf)
|
||
- [Decentralized Identifiers (DIDs) v1.0](https://www.w3.org/TR/did-core/)
|
||
- [WebID 2.0](https://www.w3.org/2005/Incubator/webid/spec/identity/)
|
||
- [EIP-191: Signed Data Standard](https://eips.ethereum.org/EIPS/eip-191)
|
||
- [EIP-712: Ethereum Typed Structured Data Signing](https://eips.ethereum.org/EIPS/eip-712)
|
||
- [DID Method Registry](https://www.w3.org/TR/did-spec-registries/)
|
||
|
||
---
|
||
|
||
**草案状态**:本文档为初始草案,欢迎反馈和讨论。 |