Skip to content

Commit 1c98a8d

Browse files
committed
feat: 补充说明签名算法
1 parent 43d91ca commit 1c98a8d

File tree

3 files changed

+64
-11
lines changed

3 files changed

+64
-11
lines changed

docs/develop/api-v2/dev-prepare/interface-framework/event-emit.md

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@ QQ机器人开放平台支持通过使用HTTP接口接收事件。开发者可
3636
| **CODE** | **名称** | **客户端行为** | **描述** |
3737
| --- | --- | --- | --- |
3838
| 0 | Dispatch | Receive | 服务端进行消息推送 |
39-
| 12 | HTTP Callback ACK | Reply | 仅用于 http 回调模式的回包,代表机器人收到了平台推送的数据 |
4039
| 13 | 回调地址验证 | Receive | 开放平台对机器人服务端进行验证 |
41-
| 14 | 回调地址验证 ACK | Reply | 机器人服务端响应开放平台的验证请求 |
42-
4340

4441
### 签名校验
4542
机器人服务端需要对回调请求进行签名验证以保证数据没有被篡改过。
@@ -50,8 +47,8 @@ QQ机器人开放平台支持通过使用HTTP接口接收事件。开发者可
5047
开发者需要提供一个HTTPS回调地址。并选定监听的事件类型。开放平台会将事件通过回调的方式推送给机器人。
5148
<img :src="$withBotBase('/images/api-231017/event_subscription.png')" alt="event_subscription">
5249

53-
开发者配置回调地址时,开放平台会对回调地址进行验证。机器人服务端需要按格式返回签名信息。签名算法同上。 机器人服务端需要在 3 秒内响应200或204,表示接受到事件。
54-
* 请求结构
50+
配置回调地址后,开放平台会对回调地址进行验证
51+
* 请求结构(Payload.d)
5552

5653
| **字段** | **描述** |
5754
| --- |------|
@@ -65,6 +62,58 @@ QQ机器人开放平台支持通过使用HTTP接口接收事件。开发者可
6562
| plain_token | 要计算hash的字符串 |
6663
| signature | 签名 |
6764

65+
计算过程如下(golang):
66+
```go
67+
func handleValidation(rw http.ResponseWriter, r *http.Request, botSecret string) {
68+
httpBody, err := io.ReadAll(r.Body)
69+
if err != nil {
70+
log.Println("read http body err", err)
71+
return
72+
}
73+
payload := &Payload{}
74+
if err = json.Unmarshal(httpBody, payload); err != nil {
75+
log.Println("parse http payload err", err)
76+
return
77+
}
78+
validationPayload := &ValidationRequest{}
79+
if err = json.Unmarshal(payload.Data, validationPayload);err != nil {
80+
log.Println("parse http payload failed:", err)
81+
return
82+
}
83+
seed := botSecret
84+
for len(seed) < ed25519.SeedSize {
85+
seed = strings.Repeat(seed, 2)
86+
}
87+
seed = seed[:ed25519.SeedSize]
88+
reader := strings.NewReader(seed)
89+
// GenerateKey 方法会返回公钥、私钥,这里只需要私钥进行签名生成不需要返回公钥
90+
_, privateKey, err := ed25519.GenerateKey(reader)
91+
if err != nil {
92+
log.Println("ed25519 generate key failed:", err)
93+
return
94+
}
95+
var msg bytes.Buffer
96+
msg.WriteString(validationPayload.EventTs)
97+
msg.WriteString(validationPayload.PlainToken)
98+
signature := hex.EncodeToString(ed25519.Sign(privateKey, msg.Bytes()))
99+
if err != nil {
100+
log.Println("generate signature failed:", err)
101+
return
102+
}
103+
rspBytes, err := json.Marshal(
104+
&ValidationResponse{
105+
PlainToken: validationPayload.PlainToken,
106+
Signature: signature,
107+
})
108+
if err != nil {
109+
log.Println("handle validation failed:", err)
110+
return
111+
}
112+
rw.Write(rspBytes)
113+
}
114+
115+
```
116+
68117
例如机器人账号
69118
```
70119
appid: 11111111

docs/develop/api-v2/dev-prepare/interface-framework/opcode.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
| 9 | Invalid Session | Receive | 当identify或resume的时候,如果参数有错,服务端会返回该消息 |
1313
| 10 | Hello | Receive | 当客户端与网关建立ws连接之后,网关下发的第一条消息 |
1414
| 11 | Heartbeat ACK | Receive/Reply | 当发送心跳成功之后,就会收到该消息 |
15-
| 12 | HTTP Callback ACK | Reply | 仅用于 http 回调模式的回包,代表机器人收到了平台推送的数据 |
15+
| 12 | HTTP Callback ACK | Reply | 仅用于 http 回调模式的回包,代表机器人收到了平台推送的数据() |
16+
| 13 | 回调地址验证 | Receive | 开放平台对机器人服务端进行验证 |
17+
1618

1719
客户端操作含义如下:
1820

docs/develop/api-v2/dev-prepare/interface-framework/sign.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,14 @@ privateKey: [110 97 79 67 48 111 99 81 69 51 115 104 87 76 65 102 102 102 86 76
6767
if timestamp == "" {
6868
return false
6969
}
70-
// 按照timstamp+Body顺序组成签名体
70+
httpBody, err := io.ReadAll(req.Body)
71+
if err != nil {
72+
return false
73+
}
74+
// 按照timestamp+Body顺序组成签名体
7175
var msg bytes.Buffer
7276
msg.WriteString(timestamp)
73-
var body bytes.Buffer
74-
// copy body into buffers
75-
_, err = io.Copy(&msg, io.TeeReader(r.Body, &body))
77+
msg.Write(httpBody)
7678
if err != nil {
7779
return false
7880
}
@@ -81,7 +83,7 @@ privateKey: [110 97 79 67 48 111 99 81 69 51 115 104 87 76 65 102 102 102 86 76
8183
- 根据公钥、Signature、签名体调用 Ed25519 算法进行验证
8284

8385
```go
84-
ed25519.Verify(publicKey, msg.Bytes(), sig)
86+
ed25519.Verify(publicKey, msg.Bytes(), sig)
8587
```
8688

8789
DEMO

0 commit comments

Comments
 (0)