refactor(wecom): replace generateSignature with computeSignature and update related tests
This commit is contained in:
parent
81f6787dd5
commit
8f3d611a4c
3 changed files with 19 additions and 44 deletions
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha1"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
@ -14,7 +13,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -291,13 +289,14 @@ func (c *WeComAIBotChannel) handleWebhook(w http.ResponseWriter, r *http.Request
|
||||||
"query": r.URL.RawQuery,
|
"query": r.URL.RawQuery,
|
||||||
})
|
})
|
||||||
|
|
||||||
if r.Method == http.MethodGet {
|
switch r.Method {
|
||||||
|
case http.MethodGet:
|
||||||
// URL verification
|
// URL verification
|
||||||
c.handleVerification(ctx, w, r)
|
c.handleVerification(ctx, w, r)
|
||||||
} else if r.Method == http.MethodPost {
|
case http.MethodPost:
|
||||||
// Message callback
|
// Message callback
|
||||||
c.handleMessageCallback(ctx, w, r)
|
c.handleMessageCallback(ctx, w, r)
|
||||||
} else {
|
default:
|
||||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -909,7 +908,7 @@ func (c *WeComAIBotChannel) encryptResponse(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate signature
|
// Generate signature
|
||||||
signature := c.generateSignature(timestamp, nonce, encrypted)
|
signature := computeSignature(c.config.Token, timestamp, nonce, encrypted)
|
||||||
|
|
||||||
// Build encrypted response
|
// Build encrypted response
|
||||||
encryptedResp := WeComAIBotEncryptedResponse{
|
encryptedResp := WeComAIBotEncryptedResponse{
|
||||||
|
|
@ -1010,20 +1009,6 @@ func pkcs7Pad(data []byte, blockSize int) []byte {
|
||||||
return append(data, padText...)
|
return append(data, padText...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateSignature generates message signature using common function
|
|
||||||
func (c *WeComAIBotChannel) generateSignature(timestamp, nonce, encrypt string) string {
|
|
||||||
// Sort parameters
|
|
||||||
params := []string{c.config.Token, timestamp, nonce, encrypt}
|
|
||||||
sort.Strings(params)
|
|
||||||
|
|
||||||
// Concatenate
|
|
||||||
str := strings.Join(params, "")
|
|
||||||
|
|
||||||
// SHA1 hash
|
|
||||||
hash := sha1.Sum([]byte(str))
|
|
||||||
return fmt.Sprintf("%x", hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateStreamID generates a random stream ID
|
// generateStreamID generates a random stream ID
|
||||||
func (c *WeComAIBotChannel) generateStreamID() string {
|
func (c *WeComAIBotChannel) generateStreamID() string {
|
||||||
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
|
|
|
||||||
|
|
@ -192,27 +192,19 @@ func TestEncryptDecrypt(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateSignature(t *testing.T) {
|
func TestGenerateSignature(t *testing.T) {
|
||||||
cfg := config.WeComAIBotConfig{
|
token := "test_token"
|
||||||
Enabled: true,
|
|
||||||
Token: "test_token",
|
|
||||||
EncodingAESKey: "testkey1234567890123456789012345678901234567",
|
|
||||||
}
|
|
||||||
|
|
||||||
messageBus := bus.NewMessageBus()
|
|
||||||
ch, _ := NewWeComAIBotChannel(cfg, messageBus)
|
|
||||||
|
|
||||||
timestamp := "1234567890"
|
timestamp := "1234567890"
|
||||||
nonce := "test_nonce"
|
nonce := "test_nonce"
|
||||||
encrypt := "encrypted_msg"
|
encrypt := "encrypted_msg"
|
||||||
|
|
||||||
signature := ch.generateSignature(timestamp, nonce, encrypt)
|
signature := computeSignature(token, timestamp, nonce, encrypt)
|
||||||
|
|
||||||
if signature == "" {
|
if signature == "" {
|
||||||
t.Error("Generated signature is empty")
|
t.Error("Generated signature is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify signature using verifySignature function
|
// Verify signature using verifySignature function
|
||||||
if !verifySignature(cfg.Token, signature, timestamp, nonce, encrypt) {
|
if !verifySignature(token, signature, timestamp, nonce, encrypt) {
|
||||||
t.Error("Generated signature does not verify correctly")
|
t.Error("Generated signature does not verify correctly")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,25 +14,23 @@ import (
|
||||||
// blockSize is the PKCS7 block size used by WeCom (32)
|
// blockSize is the PKCS7 block size used by WeCom (32)
|
||||||
const blockSize = 32
|
const blockSize = 32
|
||||||
|
|
||||||
|
// computeSignature computes the WeCom message signature from the given parameters.
|
||||||
|
// It sorts [token, timestamp, nonce, encrypt], concatenates them and returns the SHA1 hex digest.
|
||||||
|
func computeSignature(token, timestamp, nonce, encrypt string) string {
|
||||||
|
params := []string{token, timestamp, nonce, encrypt}
|
||||||
|
sort.Strings(params)
|
||||||
|
str := strings.Join(params, "")
|
||||||
|
hash := sha1.Sum([]byte(str))
|
||||||
|
return fmt.Sprintf("%x", hash)
|
||||||
|
}
|
||||||
|
|
||||||
// verifySignature verifies the message signature for WeCom
|
// verifySignature verifies the message signature for WeCom
|
||||||
// This is a common function used by both WeCom Bot and WeCom App
|
// This is a common function used by both WeCom Bot and WeCom App
|
||||||
func verifySignature(token, msgSignature, timestamp, nonce, msgEncrypt string) bool {
|
func verifySignature(token, msgSignature, timestamp, nonce, msgEncrypt string) bool {
|
||||||
if token == "" {
|
if token == "" {
|
||||||
return true // Skip verification if token is not set
|
return true // Skip verification if token is not set
|
||||||
}
|
}
|
||||||
|
return computeSignature(token, timestamp, nonce, msgEncrypt) == msgSignature
|
||||||
// Sort parameters
|
|
||||||
params := []string{token, timestamp, nonce, msgEncrypt}
|
|
||||||
sort.Strings(params)
|
|
||||||
|
|
||||||
// Concatenate
|
|
||||||
str := strings.Join(params, "")
|
|
||||||
|
|
||||||
// SHA1 hash
|
|
||||||
hash := sha1.Sum([]byte(str))
|
|
||||||
expectedSignature := fmt.Sprintf("%x", hash)
|
|
||||||
|
|
||||||
return expectedSignature == msgSignature
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// decryptMessage decrypts the encrypted message using AES
|
// decryptMessage decrypts the encrypted message using AES
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue