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异常")
+ }
+}