From d6d45e60194757f4e70042bdc923f371d44ca40c Mon Sep 17 00:00:00 2001 From: CharLemAznable <545541819@qq.com> Date: Fri, 16 Nov 2018 11:27:34 +0800 Subject: [PATCH] Add SHA1, CryptMsg methods. --- README.md | 2 ++ crypt.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ crypt_test.go | 32 ++++++++++++++++++++++++++------ sign.go | 21 +++++++++++++++++++++ sign_test.go | 14 ++++++++++++++ 5 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 sign.go create mode 100644 sign_test.go diff --git a/README.md b/README.md index 17f7766..cc2eeeb 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ # Wechat AES 提供接收和推送给微信公众平台消息的加解密接口 + + 参见微信开放平台->第三方平台->[消息加解密接入指引](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419318479&token=&lang=zh_CN) diff --git a/crypt.go b/crypt.go index 1bf9db9..1ecf2a1 100644 --- a/crypt.go +++ b/crypt.go @@ -4,6 +4,8 @@ import ( "crypto/aes" "crypto/cipher" "encoding/base64" + "encoding/xml" + "fmt" mathRand "math/rand" "time" ) @@ -40,6 +42,51 @@ func WechatCryptorRandomStr() string { return string(result) } +const WechatCryptorEncryptMsgFormat = ` + + + +%s + + +` + +func (cryptor *WechatCryptor) EncryptMsg(msg, timeStamp, nonce string) (string, error) { + encrypt, err := cryptor.Encrypt(WechatCryptorRandomStr(), msg) + if nil != err { + return "", err + } + + if 0 == len(timeStamp) { + timeStamp = string(time.Now().Unix()) + } + + sign := SHA1(cryptor.token, timeStamp, nonce, encrypt) + return fmt.Sprintf(WechatCryptorEncryptMsgFormat, encrypt, sign, timeStamp, nonce), nil +} + +type WechatCryptorPostBody struct { + XMLName xml.Name `xml:"xml"` + ToUserName string `xml:"ToUserName"` + AppId string `xml:"AppId"` + Encrypt string `xml:"Encrypt"` +} + +func (cryptor *WechatCryptor) DecryptMsg(msgSign, timeStamp, nonce, postData string) (string, error) { + postBody := WechatCryptorPostBody{} + err := xml.Unmarshal([]byte(postData), &postBody) + if nil != err || 0 == len(postBody.Encrypt) { + return "", &WechatCryptorError{Code: ParseXmlError} + } + + sign := SHA1(cryptor.token, timeStamp, nonce, postBody.Encrypt) + if msgSign != sign { + return "", &WechatCryptorError{Code: ValidateSignatureError} + } + + return cryptor.Decrypt(postBody.Encrypt) +} + // 对明文进行加密 func (cryptor *WechatCryptor) Encrypt(randomStr, text string) (string, error) { randomBytes := []byte(randomStr) diff --git a/crypt_test.go b/crypt_test.go index 42f54a8..efe769b 100644 --- a/crypt_test.go +++ b/crypt_test.go @@ -1,6 +1,7 @@ package wechataes import ( + "encoding/xml" "fmt" "testing" ) @@ -11,30 +12,49 @@ var encodingAesKey = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG" var randomStr = "aaaabbbbccccdddd" var replyMsg = "我是中文abcd123" var afterAesEncrypt = "jn1L23DB+6ELqJ+6bruv21Y6MD7KeIfP82D6gU39rmkgczbWwt5+3bnyg5K55bgVtVzd832WzZGMhkP72vVOfg==" -var replyMsg2 = "1407743423"; +var replyMsg2 = "1407743423" var afterAesEncrypt2 = "jn1L23DB+6ELqJ+6bruv23M2GmYfkv0xBh2h+XTBOKVKcgDFHle6gqcZ1cZrk3e1qjPQ1F4RsLWzQRG9udbKWesxlkupqcEcW7ZQweImX9+wLMa0GaUzpkycA8+IamDBxn5loLgZpnS7fVAbExOkK5DYHBmv5tptA9tklE/fTIILHR8HLXa5nQvFb3tYPKAlHF3rtTeayNf0QuM+UW/wM9enGIDIJHF7CLHiDNAYxr+r+OrJCmPQyTy8cVWlu9iSvOHPT/77bZqJucQHQ04sq7KZI27OcqpQNSto2OdHCoTccjggX5Z9Mma0nMJBU+jLKJ38YB1fBIz+vBzsYjrTmFQ44YfeEuZ+xRTQwr92vhA9OxchWVINGC50qE/6lmkwWTwGX9wtQpsJKhP+oS7rvTY8+VdzETdfakjkwQ5/Xka042OlUb1/slTwo4RscuQ+RdxSGvDahxAJ6+EAjLt9d8igHngxIbf6YyqqROxuxqIeIch3CssH/LqRs+iAcILvApYZckqmA7FNERspKA5f8GoJ9sv8xmGvZ9Yrf57cExWtnX8aCMMaBropU/1k+hKP5LVdzbWCG0hGwx/dQudYR/eXp3P0XxjlFiy+9DMlaFExWUZQDajPkdPrEeOwofJb" +var timestamp = "1409304348" +var nonce = "xxxxxx" -func TestNewWechatCryptor(t *testing.T) { +func TestWechatCrypt(t *testing.T) { cryptor, _ := NewWechatCryptor(appId, token, encodingAesKey) encrypt, _ := cryptor.Encrypt(randomStr, replyMsg) - fmt.Println(encrypt) if afterAesEncrypt != encrypt { t.Error("no异常") } decrypt, _ := cryptor.Decrypt(afterAesEncrypt) - fmt.Println(decrypt) if replyMsg != decrypt { t.Error("no异常") } encrypt2, _ := cryptor.Encrypt(randomStr, replyMsg2) - fmt.Println(encrypt2) if afterAesEncrypt2 != encrypt2 { t.Error("no异常") } decrypt2, _ := cryptor.Decrypt(afterAesEncrypt2) - fmt.Println(decrypt2) if replyMsg2 != decrypt2 { t.Error("no异常") } } + +type TestEncryptMsg struct { + XMLName xml.Name `xml:"xml"` + Encrypt string `xml:"Encrypt"` + MsgSignature string `xml:"MsgSignature"` +} + +func TestWechatCryptMsg(t *testing.T) { + cryptor, _ := NewWechatCryptor(appId, token, encodingAesKey) + afterEncrpt, _ := cryptor.EncryptMsg(replyMsg, timestamp, nonce) + + encryptMsg := TestEncryptMsg{} + xml.Unmarshal([]byte(afterEncrpt), &encryptMsg) + format := "" + fromXML := fmt.Sprintf(format, encryptMsg.Encrypt) + + afterDecrpt, _ := cryptor.DecryptMsg(encryptMsg.MsgSignature, timestamp, nonce, fromXML) + if replyMsg != afterDecrpt { + t.Error("no异常") + } +} diff --git a/sign.go b/sign.go new file mode 100644 index 0000000..944ba4b --- /dev/null +++ b/sign.go @@ -0,0 +1,21 @@ +package wechataes + +import ( + "crypto/sha1" + "encoding/hex" + "sort" + "strings" +) + +func SHA1(token, timestamp, nonce, encrypt string) string { + array := []string{token, timestamp, nonce, encrypt} + sort.Strings(array) + str := strings.Join(array, "") + + hash := sha1.New() + hash.Write([]byte(str)) + sum := hash.Sum(nil) + sumHex := make([]byte, hex.EncodedLen(len(sum))) + hex.Encode(sumHex, sum) + return string(sumHex) +} diff --git a/sign_test.go b/sign_test.go new file mode 100644 index 0000000..3a1abad --- /dev/null +++ b/sign_test.go @@ -0,0 +1,14 @@ +package wechataes + +import ( + "testing" +) + +var expectSHA1 = "82c962d39941aa48552f90ef55aa323dc620cc10" + +func TestSHA1(t *testing.T) { + sha1 := SHA1(token, timestamp, nonce, afterAesEncrypt) + if expectSHA1 != sha1 { + t.Error("no异常") + } +}