diff --git a/server/feishu-sync/internal/config/config.go b/server/feishu-sync/internal/config/config.go index 2c9df9ad..1224b8b8 100644 --- a/server/feishu-sync/internal/config/config.go +++ b/server/feishu-sync/internal/config/config.go @@ -10,4 +10,9 @@ type Config struct { SourceMysql string Auth types.Auth SourceRabbitMq string + FeiShu struct { + ApiHost string + EncryptKey string + VerificationToken string + } } diff --git a/server/feishu-sync/internal/logic/webhooklogic.go b/server/feishu-sync/internal/logic/webhooklogic.go index fc30ea90..2a422d0f 100644 --- a/server/feishu-sync/internal/logic/webhooklogic.go +++ b/server/feishu-sync/internal/logic/webhooklogic.go @@ -2,19 +2,12 @@ package logic import ( "context" - "crypto/aes" - "crypto/cipher" - "crypto/sha256" - "encoding/base64" "encoding/json" - "errors" - "fmt" + "fusenapi/server/feishu-sync/internal/svc" + "fusenapi/utils/feishu" + "github.com/zeromicro/go-zero/core/logx" "io/ioutil" "net/http" - "strings" - - "fusenapi/server/feishu-sync/internal/svc" - "github.com/zeromicro/go-zero/core/logx" ) type WebhookLogic struct { @@ -61,9 +54,8 @@ func (l *WebhookLogic) Webhook(w http.ResponseWriter, r *http.Request) { //计算签名 timestamp := r.Header.Get("X-Lark-Request-Timestamp") nonce := r.Header.Get("X-Lark-Request-Nonce") - encryptKey := "DmiHQ2bHhKiR3KK4tIjLShbs13eErxKA" signature := r.Header.Get("X-Lark-Signature") - sign := l.CalculateFeiShuWebhookSignature(timestamp, nonce, encryptKey, bodyBytes) + sign := feishu.CalculateFeiShuWebhookSignature(timestamp, nonce, l.svcCtx.Config.FeiShu.EncryptKey, bodyBytes) if signature != sign { logx.Error("非法的消息,签名验证不通过", sign, "====", signature) return @@ -78,7 +70,7 @@ func (l *WebhookLogic) Webhook(w http.ResponseWriter, r *http.Request) { return } //解密 - realMsgBytes, err := l.DecryptFeiShuWebhookMsg(encryptMsg.Encrypt, encryptKey) + realMsgBytes, err := feishu.DecryptFeiShuWebhookMsg(encryptMsg.Encrypt, l.svcCtx.Config.FeiShu.EncryptKey) if err != nil { logx.Error(err) return @@ -127,51 +119,3 @@ func (l *WebhookLogic) Webhook(w http.ResponseWriter, r *http.Request) { } return } - -// 计算签名 -func (l *WebhookLogic) CalculateFeiShuWebhookSignature(timestamp, nonce, encryptKey string, body []byte) string { - var b strings.Builder - b.WriteString(timestamp) - b.WriteString(nonce) - b.WriteString(encryptKey) - b.Write(body) //bodystring 指整个请求体,不要在反序列化后再计算 - bs := []byte(b.String()) - h := sha256.New() - h.Write(bs) - bs = h.Sum(nil) - sig := fmt.Sprintf("%x", bs) - return sig -} - -// 解密事件消息 -func (l *WebhookLogic) DecryptFeiShuWebhookMsg(encrypt string, encryptKey string) ([]byte, error) { - buf, err := base64.StdEncoding.DecodeString(encrypt) - if err != nil { - return nil, fmt.Errorf("base64StdEncode Error[%v]", err) - } - if len(buf) < aes.BlockSize { - return nil, errors.New("cipher too short") - } - keyBs := sha256.Sum256([]byte(encryptKey)) - block, err := aes.NewCipher(keyBs[:sha256.Size]) - if err != nil { - return nil, fmt.Errorf("AESNewCipher Error[%v]", err) - } - iv := buf[:aes.BlockSize] - buf = buf[aes.BlockSize:] - // CBC mode always works in whole blocks. - if len(buf)%aes.BlockSize != 0 { - return nil, errors.New("ciphertext is not a multiple of the block size") - } - mode := cipher.NewCBCDecrypter(block, iv) - mode.CryptBlocks(buf, buf) - n := strings.Index(string(buf), "{") - if n == -1 { - n = 0 - } - m := strings.LastIndex(string(buf), "}") - if m == -1 { - m = len(buf) - 1 - } - return buf[n : m+1], nil -} diff --git a/utils/feishu/decrypt.go b/utils/feishu/decrypt.go new file mode 100644 index 00000000..8160fccc --- /dev/null +++ b/utils/feishu/decrypt.go @@ -0,0 +1,44 @@ +package feishu + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/sha256" + "encoding/base64" + "errors" + "fmt" + "strings" +) + +// 解密事件消息 +func DecryptFeiShuWebhookMsg(encryptData string, encryptKey string) ([]byte, error) { + buf, err := base64.StdEncoding.DecodeString(encryptData) + if err != nil { + return nil, fmt.Errorf("base64StdEncode Error[%v]", err) + } + if len(buf) < aes.BlockSize { + return nil, errors.New("cipher too short") + } + keyBs := sha256.Sum256([]byte(encryptKey)) + block, err := aes.NewCipher(keyBs[:sha256.Size]) + if err != nil { + return nil, fmt.Errorf("AESNewCipher Error[%v]", err) + } + iv := buf[:aes.BlockSize] + buf = buf[aes.BlockSize:] + // CBC mode always works in whole blocks. + if len(buf)%aes.BlockSize != 0 { + return nil, errors.New("ciphertext is not a multiple of the block size") + } + mode := cipher.NewCBCDecrypter(block, iv) + mode.CryptBlocks(buf, buf) + n := strings.Index(string(buf), "{") + if n == -1 { + n = 0 + } + m := strings.LastIndex(string(buf), "}") + if m == -1 { + m = len(buf) - 1 + } + return buf[n : m+1], nil +} diff --git a/utils/feishu/verify.go b/utils/feishu/verify.go new file mode 100644 index 00000000..23bd1fe9 --- /dev/null +++ b/utils/feishu/verify.go @@ -0,0 +1,22 @@ +package feishu + +import ( + "crypto/sha256" + "fmt" + "strings" +) + +// 计算签名 +func CalculateFeiShuWebhookSignature(timestamp, nonce, encryptKey string, body []byte) string { + var b strings.Builder + b.WriteString(timestamp) + b.WriteString(nonce) + b.WriteString(encryptKey) + b.Write(body) //bodystring 指整个请求体,不要在反序列化后再计算 + bs := []byte(b.String()) + h := sha256.New() + h.Write(bs) + bs = h.Sum(nil) + sig := fmt.Sprintf("%x", bs) + return sig +}