276 lines
7.0 KiB
Markdown
276 lines
7.0 KiB
Markdown
以下是为提供的 Python 代码编写的 **Markdown 格式技术文档**,涵盖了类的功能、依赖、中间件逻辑以及各方法的说明。
|
||
|
||
---
|
||
|
||
# `P2pLayer` 技术文档
|
||
|
||
## 概述
|
||
|
||
`P2pLayer` 是一个基于 `aiohttp` 的中间件组件,用于在 Web 请求处理流程中集成点对点(P2P)加密通信功能。该模块通过条件启用 P2P 加密层,并在请求/响应过程中实现握手、解码和编码操作,以保障通信安全。
|
||
|
||
此模块依赖于 `p2psc` 库中的 `PubkeyHandler` 和 `P2psc` 类,实现公钥管理和端到端加密逻辑。
|
||
|
||
---
|
||
|
||
## 依赖项
|
||
|
||
- [`aiohttp`](https://docs.aiohttp.org/):异步 HTTP 客户端/服务器框架。
|
||
- `p2psc.pubkey_handler.PubkeyHandler`:负责管理本地公钥与远程节点身份认证。
|
||
- `p2psc.p2psc.P2psc`:核心 P2P 安全通信类,支持加密握手与数据加解密。
|
||
- `getConfig()`:全局配置获取函数(外部定义,需确保可用)。
|
||
|
||
> ⚠️ 注意:`getConfig()` 函数未在此文件中定义,应由项目其他部分提供,返回包含配置树的对象。
|
||
|
||
---
|
||
|
||
## 类定义
|
||
|
||
```python
|
||
class P2pLayer
|
||
```
|
||
|
||
### 功能
|
||
|
||
`P2pLayer` 封装了 P2P 加密通信的初始化与中间件逻辑。根据配置决定是否启用加密传输,并在启用时拦截请求/响应流进行加解密处理。
|
||
|
||
---
|
||
|
||
## 初始化 (`__init__`)
|
||
|
||
```python
|
||
def __init__(self)
|
||
```
|
||
|
||
### 描述
|
||
|
||
初始化 `P2pLayer` 实例并根据配置决定是否启用 P2P 加密功能。
|
||
|
||
### 流程
|
||
|
||
1. 初始化 `self.p2pcrypt = False`。
|
||
2. 调用 `getConfig()` 获取系统配置。
|
||
3. 检查配置项 `config.website.p2pcrypt`:
|
||
- 若为 `True`,则启用 P2P 加密(设置 `self.p2pcrypt = True`),并初始化相关组件;
|
||
- 否则跳过初始化,后续中间件将直接透传请求。
|
||
4. 如果启用了加密:
|
||
- 创建 `PubkeyHandler` 实例用于密钥管理;
|
||
- 使用 handler 及其自身 ID 初始化 `P2psc` 实例。
|
||
|
||
### 属性
|
||
|
||
| 属性 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `p2pcrypt` | `bool` | 是否启用 P2P 加密模式 |
|
||
| `handler` | `PubkeyHandler` | 公钥处理器,管理本地/远程身份 |
|
||
| `p2p` | `P2psc` | P2P 安全通信核心实例 |
|
||
|
||
> ✅ 提示:仅当 `p2pcrypt` 为 `True` 时,`handler` 和 `p2p` 才会被创建。
|
||
|
||
---
|
||
|
||
## 中间件:`p2p_middle`
|
||
|
||
```python
|
||
@web.middleware
|
||
async def p2p_middle(self, request, handler)
|
||
```
|
||
|
||
### 描述
|
||
|
||
Aiohttp 异步中间件,用于拦截进入的 HTTP 请求并执行 P2P 加密相关处理。
|
||
|
||
### 执行逻辑
|
||
|
||
| 条件 | 行为 |
|
||
|------|------|
|
||
| `not self.p2pcrypt` | 直接调用原始 handler,不进行任何加密处理 |
|
||
| 请求头含 `P2pHandShake` | 调用 `self.p2p_handshake(request)` 进行密钥交换 |
|
||
| 请求头含 `P2pdata` | 解密请求 → 处理 → 加密响应 |
|
||
| 其他情况 | 直接调用 handler(明文通行) |
|
||
|
||
### 详细流程
|
||
|
||
```text
|
||
开始
|
||
│
|
||
├─ 是否禁用 p2pcrypt?
|
||
│ └─ 是 → 直接返回 handler(request)
|
||
│
|
||
├─ 是否存在 "P2pHandShake" 头?
|
||
│ └─ 是 → 返回 await p2p_handshake(request)
|
||
│
|
||
├─ 是否存在 "P2pdata" 头?
|
||
│ ├─ 是 →
|
||
│ │ 1. await p2p_decode_request(request)
|
||
│ │ 2. resp = await handler(decoded_request)
|
||
│ │ 3. return await p2p_encode_response(resp)
|
||
│
|
||
└─ 默认 → 返回 await handler(request)
|
||
```
|
||
|
||
### 注意事项
|
||
|
||
- 当前代码存在拼写错误:
|
||
- `if not p2pscrypr:` ❌ → 应为 `if not self.p2pcrypt:`
|
||
- `resturen` ❌ → 应为 `return`
|
||
- `request.header.get` ❌ → 应为 `request.headers.get`
|
||
- 正确代码应如下:
|
||
|
||
```python
|
||
@web.middleware
|
||
async def p2p_middle(self, request, handler):
|
||
if not self.p2pcrypt:
|
||
return await handler(request)
|
||
|
||
if request.headers.get('P2pHandShake', None):
|
||
return await self.p2p_handshake(request)
|
||
|
||
if request.headers.get('P2pdata', None):
|
||
request = await self.p2p_decode_request(request)
|
||
resp = await handler(request)
|
||
return await self.p2p_encode_response(resp)
|
||
|
||
return await handler(request)
|
||
```
|
||
|
||
---
|
||
|
||
## 方法说明
|
||
|
||
### `p2p_handshake(request)`
|
||
|
||
```python
|
||
async def p2p_handshake(self, request)
|
||
```
|
||
|
||
#### 描述
|
||
|
||
处理客户端发起的 P2P 安全握手请求(如密钥交换)。当前为空实现(`pass`),需子类或后续扩展完成具体协议逻辑。
|
||
|
||
#### 参数
|
||
|
||
- `request` (`aiohttp.web.Request`):HTTP 请求对象
|
||
|
||
#### 返回值
|
||
|
||
- 通常应返回 `aiohttp.web.Response` 对象,携带握手响应数据(如公钥、会话密钥等)
|
||
|
||
#### 示例场景
|
||
|
||
- TLS-like 密钥协商
|
||
- Diffie-Hellman 或 Noise 协议集成
|
||
|
||
---
|
||
|
||
### `p2p_decode_request(request)`
|
||
|
||
```python
|
||
async def p2p_decode_request(self, request)
|
||
```
|
||
|
||
#### 描述
|
||
|
||
对接收到的加密请求体进行解密和解析,还原为标准 `request` 对象。
|
||
|
||
#### 参数
|
||
|
||
- `request`:携带加密数据的原始请求
|
||
|
||
#### 返回值
|
||
|
||
- 解密后的 `request` 对象(可能包装新 body 或附加上下文字段)
|
||
|
||
#### 待实现内容
|
||
|
||
- 读取请求体
|
||
- 使用 `self.p2p.decrypt()` 解密
|
||
- 重构 JSON/body 数据
|
||
- 替换 `request._payload` 或使用自定义 Request 子类
|
||
|
||
---
|
||
|
||
### `p2p_encode_response(response)`
|
||
|
||
```python
|
||
async def p2p_encode_response(self, response)
|
||
```
|
||
|
||
#### 描述
|
||
|
||
将正常的 HTTP 响应内容加密后封装,返回给客户端。
|
||
|
||
#### 参数
|
||
|
||
- `response` (`aiohttp.web.Response`):原始响应对象
|
||
|
||
#### 返回值
|
||
|
||
- 加密后的响应对象(通常修改 body 并添加头部如 `Content-Encoding: p2p`)
|
||
|
||
#### 当前实现
|
||
|
||
```python
|
||
return response
|
||
```
|
||
|
||
> 🔴 当前为占位实现,未实际加密。需要补充:
|
||
>
|
||
> - 序列化响应内容
|
||
> - 使用 `self.p2p.encrypt()` 加密
|
||
> - 设置 `Content-Type` 或自定义头标识加密类型
|
||
> - 构造新的 `StreamResponse` 或 `Response` 返回
|
||
|
||
---
|
||
|
||
## 配置要求
|
||
|
||
确保配置结构中包含以下字段:
|
||
|
||
```python
|
||
config = {
|
||
"website": {
|
||
"p2pcrypt": True # 或 False,控制是否启用 P2P 加密
|
||
}
|
||
}
|
||
```
|
||
|
||
可通过环境变量、YAML 文件或其他方式加载。
|
||
|
||
---
|
||
|
||
## 使用示例(伪代码)
|
||
|
||
```python
|
||
app = web.Application(middlewares=[p2player.p2p_middle])
|
||
p2player = P2pLayer()
|
||
web.run_app(app)
|
||
```
|
||
|
||
---
|
||
|
||
## 已知问题 / 待修复 Bug
|
||
|
||
| 问题 | 位置 | 说明 |
|
||
|------|------|------|
|
||
| 拼写错误 `p2pscrypr` | 第10行 | 应为 `self.p2pcrypt` |
|
||
| `resturen` 错误 | 第12行 | 应为 `return` |
|
||
| `request.header` → `.headers` | 第15行 | 属性名错误 |
|
||
| `p2p_handshake` 无实现 | 第20行 | 需补充握手逻辑 |
|
||
| 加解密方法为空 | 第24–29行 | 仅为骨架,需具体实现 |
|
||
|
||
---
|
||
|
||
## 总结
|
||
|
||
`P2pLayer` 提供了一个可插拔的 P2P 加密通信中间件框架,适用于需要端到端安全传输的去中心化 Web 服务。虽然目前大部分功能尚未实现,但其设计清晰,具备良好的扩展性。
|
||
|
||
建议下一步:
|
||
- 修复语法错误
|
||
- 实现握手与加解密逻辑
|
||
- 添加单元测试与集成测试
|
||
- 支持超时、重试、会话缓存等机制
|
||
|
||
---
|
||
|
||
📌 **版本信息**:v0.1(草案)
|
||
📅 **最后更新**:2025-04-05 |