-
Notifications
You must be signed in to change notification settings - Fork 48
/
Copy pathevent.go
99 lines (81 loc) · 2.48 KB
/
event.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package wechat
import (
"crypto/aes"
"crypto/sha1"
"encoding/base64"
"encoding/hex"
"fmt"
"sort"
"strconv"
"time"
"github.com/shenghui0779/sdk-go/lib"
"github.com/shenghui0779/sdk-go/lib/value"
"github.com/shenghui0779/sdk-go/lib/xcrypto"
)
// SignWithSHA1 事件消息sha1签名
func SignWithSHA1(token string, items ...string) string {
items = append(items, token)
sort.Strings(items)
h := sha1.New()
for _, v := range items {
h.Write([]byte(v))
}
return hex.EncodeToString(h.Sum(nil))
}
// EventEncrypt 时间消息加密
// [参考](https://developer.work.weixin.qq.com/document/path/90968)
func EventEncrypt(receiveID, encodingAESKey, nonce string, plainText []byte) (*xcrypto.CipherText, error) {
key, err := base64.StdEncoding.DecodeString(encodingAESKey + "=")
if err != nil {
return nil, err
}
contentLen := len(plainText)
appidOffset := 20 + contentLen
encryptData := make([]byte, appidOffset+len(receiveID))
copy(encryptData[:16], nonce)
copy(encryptData[16:20], EncodeUint32ToBytes(uint32(contentLen)))
copy(encryptData[20:], plainText)
copy(encryptData[appidOffset:], receiveID)
return xcrypto.AESEncryptCBC(key, key[:aes.BlockSize], encryptData)
}
// EventDecrypt 事件消息解密
// [参考](https://developer.work.weixin.qq.com/document/path/90968)
func EventDecrypt(receiveID, encodingAESKey, cipherText string) ([]byte, error) {
key, err := base64.StdEncoding.DecodeString(encodingAESKey + "=")
if err != nil {
return nil, err
}
decryptData, err := base64.StdEncoding.DecodeString(cipherText)
if err != nil {
return nil, err
}
plainText, err := xcrypto.AESDecryptCBC(key, key[:aes.BlockSize], decryptData)
if err != nil {
return nil, err
}
// 校验 receiveid
appidOffset := len(plainText) - len([]byte(receiveID))
if v := string(plainText[appidOffset:]); v != receiveID {
return nil, fmt.Errorf("receive_id mismatch, want: %s, got: %s", receiveID, v)
}
return plainText[20:appidOffset], nil
}
func EventReply(receiveID, token, encodingAESKey string, msg value.V) (value.V, error) {
str, err := ValueToXML(msg)
if err != nil {
return nil, err
}
nonce := lib.Nonce(16)
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
ct, err := EventEncrypt(receiveID, encodingAESKey, nonce, []byte(str))
if err != nil {
return nil, err
}
encryptMsg := ct.String()
return value.V{
"Encrypt": encryptMsg,
"MsgSignature": SignWithSHA1(token, timestamp, nonce, encryptMsg),
"TimeStamp": timestamp,
"Nonce": nonce,
}, nil
}