diff --git a/platformapi/enterprise_wechat/enterprise_callback.go b/platformapi/enterprise_wechat/enterprise_callback.go index 06fc79cd..b8d653bb 100644 --- a/platformapi/enterprise_wechat/enterprise_callback.go +++ b/platformapi/enterprise_wechat/enterprise_callback.go @@ -15,10 +15,6 @@ type SuiteTicketInfo struct { SuiteTicket string `xml:"SuiteTicket"` // Ticket内容,最长为512字节 } -type SuiteTicketXml struct { - Xml *SuiteTicketInfo `xml:"xml"` -} - func (a *API) GetEnterpriseMsg(request *http.Request) (*SuiteTicketInfo, error) { data, err := ioutil.ReadAll(request.Body) if err != nil { diff --git a/utils/weworkapi_golang-master/httpserver.go b/utils/weworkapi_golang-master/httpserver.go new file mode 100644 index 00000000..75d5efce --- /dev/null +++ b/utils/weworkapi_golang-master/httpserver.go @@ -0,0 +1,115 @@ +package weworkapi_golang + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + "net/url" + "strings" +) + +const token = "nn3P9sfkGK5UlHgtNoAqB" +const receiverId = "ww9a156bfa070e1857" +const encodingAeskey = "471RkJkfISWJQUC2f8DSdOgXH0reVCxWCpfaTawSIWA" + +func getString(str, endstr string, start int, msg *string) int { + end := strings.Index(str, endstr) + *msg = str[start:end] + return end + len(endstr) +} + +func VerifyURL(w http.ResponseWriter, r *http.Request) { + //httpstr := `&{GET /?msg_signature=825075c093249d5a60967fe4a613cae93146636b×tamp=1597998748&nonce=1597483820&echostr=neLB8CftccHiz19tluVb%2BUBnUVMT3xpUMZU8qvDdD17eH8XfEsbPYC%2FkJyPsZOOc6GdsCeu8jSIa2noSJ%2Fez2w%3D%3D HTTP/1.1 1 1 map[Cache-Control:[no-cache] Accept:[*/*] Pragma:[no-cache] User-Agent:[Mozilla/4.0]] 0x86c180 0 [] false 100.108.211.112:8893 map[] map[] map[] 100.108.79.233:59663 /?msg_signature=825075c093249d5a60967fe4a613cae93146636b×tamp=1597998748&nonce=1597483820&echostr=neLB8CftccHiz19tluVb%2BUBnUVMT3xpUMZU8qvDdD17eH8XfEsbPYC%2FkJyPsZOOc6GdsCeu8jSIa2noSJ%2Fez2w%3D%3D }` + fmt.Println(r, r.Body) + httpstr := r.URL.RawQuery + start := strings.Index(httpstr, "msg_signature=") + start += len("msg_signature=") + + var msg_signature string + next := getString(httpstr, "×tamp=", start, &msg_signature) + + var timestamp string + next = getString(httpstr, "&nonce=", next, ×tamp) + + var nonce string + next = getString(httpstr, "&echostr=", next, &nonce) + + echostr := httpstr[next:len(httpstr)] + + echostr, _ = url.QueryUnescape(echostr) + fmt.Println(msg_signature, timestamp, nonce, echostr, next) + + wxcpt := NewWXBizMsgCrypt(token, encodingAeskey, receiverId, JsonType) + echoStr, cryptErr := wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr) + if nil != cryptErr { + fmt.Println("verifyUrl fail", cryptErr) + } + fmt.Println("verifyUrl success echoStr", string(echoStr)) + fmt.Fprintf(w, string(echoStr)) + +} + +func MsgHandler(w http.ResponseWriter, r *http.Request) { + httpstr := r.URL.RawQuery + start := strings.Index(httpstr, "msg_signature=") + start += len("msg_signature=") + + var msg_signature string + next := getString(httpstr, "×tamp=", start, &msg_signature) + + var timestamp string + next = getString(httpstr, "&nonce=", next, ×tamp) + + nonce := httpstr[next:len(httpstr)] + fmt.Println(msg_signature, timestamp, nonce) + + body, err := ioutil.ReadAll(r.Body) + fmt.Println(string(body), err) + wxcpt := NewWXBizMsgCrypt(token, encodingAeskey, receiverId, JsonType) + + msg, err_ := wxcpt.DecryptMsg(msg_signature, timestamp, nonce, body) + fmt.Println(string(msg), err_) + var msgContent MsgContent + err = json.Unmarshal(msg, &msgContent) + if nil != err { + fmt.Println("Unmarshal fail", err) + } else { + fmt.Println("struct", msgContent) + } + + fmt.Println(msgContent, err) + ToUsername := msgContent.ToUsername + msgContent.ToUsername = msgContent.FromUsername + msgContent.FromUsername = ToUsername + fmt.Println("replaymsg", msgContent) + replayJson, err := json.Marshal(&msgContent) + + encryptMsg, cryptErr := wxcpt.EncryptMsg(string(replayJson), "1409659589", "1409659589") + if nil != cryptErr { + fmt.Println("DecryptMsg fail", cryptErr) + } + + sEncryptMsg := string(encryptMsg) + + fmt.Println("after encrypt sEncryptMsg: ", sEncryptMsg) + fmt.Fprintf(w, sEncryptMsg) +} + +func CallbackHandler(w http.ResponseWriter, r *http.Request) { + httpstr := r.URL.RawQuery + echo := strings.Index(httpstr, "echostr") + if echo != -1 { + VerifyURL(w, r) + } else { + MsgHandler(w, r) + } + + fmt.Println("finished CallbackHandler", httpstr) +} + +func main() { + http.HandleFunc("/", CallbackHandler) // 设置访问路由 + log.Fatal(http.ListenAndServe(":8893", nil)) +} diff --git a/utils/weworkapi_golang-master/sample.go b/utils/weworkapi_golang-master/sample.go new file mode 100644 index 00000000..501ea335 --- /dev/null +++ b/utils/weworkapi_golang-master/sample.go @@ -0,0 +1,139 @@ +package weworkapi_golang + +// +//import ( +// "encoding/json" +// "fmt" +//) +// +type MsgContent struct { + ToUsername string `json:"ToUserName"` + FromUsername string `json:"FromUserName"` + CreateTime uint32 `json:"CreateTime"` + MsgType string `json:"MsgType"` + Content string `json:"Content"` + Msgid uint64 `json:"MsgId"` + Agentid uint32 `json:"AgentId"` +} + +//func main() { +// token := "QDG6eK" +// receiverId := "wx5823bf96d3bd56c7" +// encodingAeskey := "jWmYm7qr5nMoAUwZRjGtBxmz3KA1tkAj3ykkR6q2B2C" +// wxcpt := NewWXBizMsgCrypt(token, encodingAeskey, receiverId, JsonType) +// /* +// ------------使用示例一:验证回调URL--------------- +// *企业开启回调模式时,企业微信会向验证url发送一个get请求 +// 假设点击验证时,企业收到类似请求: +// * GET /cgi-bin/wxpush?msg_signature=5c45ff5e21c57e6ad56bac8758b79b1d9ac89fd3×tamp=1409659589&nonce=263014780&echostr=P9nAzCzyDtyTWESHep1vC5X9xho%2FqYX3Zpb4yKa9SKld1DsH3Iyt3tP3zNdtp%2B4RPcs8TgAE7OaBO%2BFZXvnaqQ%3D%3D +// * HTTP/1.1 Host: qy.weixin.qq.com +// +// 接收到该请求时,企业应 +// 1.解析出Get请求的参数,包括消息体签名(msg_signature),时间戳(timestamp),随机数字串(nonce)以及企业微信推送过来的随机加密字符串(echostr), +// 这一步注意作URL解码。 +// 2.验证消息体签名的正确性 +// 3. 解密出echostr原文,将原文当作Get请求的response,返回给企业微信 +// 第2,3步可以用企业微信提供的库函数VerifyURL来实现。 +// +// */ +// // 解析出url上的参数值如下: +// // verifyMsgSign := HttpUtils.ParseUrl("msg_signature") +// verifyMsgSign := "5c45ff5e21c57e6ad56bac8758b79b1d9ac89fd3" +// // verifyTimestamp := HttpUtils.ParseUrl("timestamp") +// verifyTimestamp := "1409659589" +// // verifyNonce := HttpUtils.ParseUrl("nonce") +// verifyNonce := "263014780" +// // verifyEchoStr := HttpUtils.ParseUrl("echoStr") +// verifyEchoStr := "P9nAzCzyDtyTWESHep1vC5X9xho/qYX3Zpb4yKa9SKld1DsH3Iyt3tP3zNdtp+4RPcs8TgAE7OaBO+FZXvnaqQ==" +// echoStr, cryptErr := wxcpt.VerifyURL(verifyMsgSign, verifyTimestamp, verifyNonce, verifyEchoStr) +// if nil != cryptErr { +// fmt.Println("verifyUrl fail", cryptErr) +// } +// fmt.Println("verifyUrl success echoStr", string(echoStr)) +// // 验证URL成功,将sEchoStr返回 +// // HttpUtils.SetResponse(sEchoStr) +// +// /* +// ------------使用示例二:对用户回复的消息解密--------------- +// 用户回复消息或者点击事件响应时,企业会收到回调消息,此消息是经过企业微信加密之后的密文以post形式发送给企业,密文格式请参考官方文档 +// 假设企业收到企业微信的回调消息如下: +// POST /cgi-bin/wxpush? msg_signature=477715d11cdb4164915debcba66cb864d751f3e6×tamp=1409659813&nonce=1372623149 HTTP/1.1 +// Host: qy.weixin.qq.com +// Content-Length: 613 +// { +// "tousername":"wx5823bf96d3bd56c7", +// "encrypt":"CZWs4CWRpI4VolQlvn4dlPBlXke6+HgmuI7p0LueFp1fKH40TNL+YHWJZwqIiYV+3kTrhdNU7fZwc+PmtgBvxSczkFeRz+oaVSsomrrtP2Z91LE313djjbWujqInRT+7ChGbCeo7ZzszByf8xnDSunPBxRX1MfX3kAxpKq7dqduW1kpMAx8O8xUzZ9oC0TLuZchbpxaml4epzGfF21O+zyXDwTxbCEiO0E87mChtzuh/VPlznXYbfqVrnyLNZ5pr", +// "agentid":"218" +// } +// +// 企业收到post请求之后应该: +// 1.解析出url上的参数,包括消息体签名(msg_signature),时间戳(timestamp)以及随机数字串(nonce) +// 2.验证消息体签名的正确性。 +// 3.将post请求的数据进行json解析,并将"Encrypt"标签的内容进行解密,解密出来的明文即是用户回复消息的明文,明文格式请参考官方文档 +// 第2,3步可以用企业微信提供的库函数DecryptMsg来实现。 +// */ +// +// // reqMsgSign := HttpUtils.ParseUrl("msg_signature") +// reqMsgSign := "0623cbc5a8cbee5bcc137c70de99575366fc2af3" +// // reqTimestamp := HttpUtils.ParseUrl("timestamp") +// reqTimestamp := "1409659813" +// // reqNonce := HttpUtils.ParseUrl("nonce") +// reqNonce := "1372623149" +// // post请求的密文数据 +// // reqData = HttpUtils.PostData() +// +// reqData := []byte(`{"tousername":"wx5823bf96d3bd56c7","encrypt":"CZWs4CWRpI4VolQlvn4dlEC1alN2MUEY2VklGehgBVLBrlVF7SyT+SV+Toj43l4ayJ9UMGKphktKKmP7B2j/P1ey67XB8PBgS7Wr5/8+w/yWriZv3Vmoo/MH3/1HsIWZrPQ3N2mJrelStIfI2Y8kLKXA7EhfZgZX4o+ffdkZDM76SEl79Ib9mw7TGjZ9Aw/x/A2VjNbV1E8BtEbRxYYcQippYNw7hr8sFfa3nW1xLdxokt8QkRX83vK3DFP2F6TQFPL2Tu98UwhcUpPvdJBuu1/yiOQIScppV3eOuLWEsko=","agentid":"218"}`) +// +// msg, cryptErr := wxcpt.DecryptMsg(reqMsgSign, reqTimestamp, reqNonce, reqData) +// if nil != cryptErr { +// fmt.Println("DecryptMsg fail", cryptErr) +// } +// fmt.Println("after decrypt msg: ", string(msg)) +// // TODO: 解析出明文json标签的内容进行处理 +// // For example: +// +// var msgContent MsgContent +// err := json.Unmarshal(msg, &msgContent) +// if nil != err { +// fmt.Println("Unmarshal fail", err) +// } else { +// fmt.Println("struct", msgContent) +// } +// +// /* +// ------------使用示例三:企业回复用户消息的加密--------------- +// 企业被动回复用户的消息也需要进行加密,并且拼接成密文格式的json串。 +// 假设企业需要回复用户的明文如下: +// +// { +// "ToUserName": "mycreate", +// "FromUserName":"wx5823bf96d3bd56c7", +// "CreateTime": 1348831860, +// "MsgType": "text", +// "Content": "this is a test", +// "MsgId": 1234567890123456, +// "AgentID": 128 +// } +// +// 为了将此段明文回复给用户,企业应: +// 1.自己生成时间时间戳(timestamp),随机数字串(nonce)以便生成消息体签名,也可以直接用从企业微信的post url上解析出的对应值。 +// 2.将明文加密得到密文。 +// 3.用密文,步骤1生成的timestamp,nonce和企业在企业微信设定的token生成消息体签名。 +// 4.将密文,消息体签名,时间戳,随机数字串拼接成json格式的字符串,发送给企业。 +// 以上2,3,4步可以用企业微信提供的库函数EncryptMsg来实现。 +// */ +// respData := "{\"ToUserName\":\"wx5823bf96d3bd56c7\",\"FromUserName\":\"mycreate\",\"CreateTime\": 1409659813,\"MsgType\":\"text\",\"Content\":\"hello\",\"MsgId\":4561255354251345929,\"AgentID\": 218}" +// //respData := `{"ToUserName":"wx5823bf96d3bd56c7","FromUserName":"mycreate","CreateTime": 1409659813,"MsgType":"text","Content":"hello","MsgId":4561255354251345929,"AgentID": 218}` +// //respData := `{"FromUserName":"mycreate","CreateTime": 1409659813,"MsgType":"text","Content":"hello","MsgId":4561255354251345929,"AgentID": 218}` +// encryptMsg, cryptErr := wxcpt.EncryptMsg(respData, reqTimestamp, reqNonce) +// if nil != cryptErr { +// fmt.Println("DecryptMsg fail", cryptErr) +// } +// +// sEncryptMsg := string(encryptMsg) +// +// fmt.Println("after encrypt sEncryptMsg: ", sEncryptMsg) +// // 加密成功 +// // TODO: +// // HttpUtils.SetResponse(sEncryptMsg) +//} diff --git a/utils/weworkapi_golang-master/wxbizjsonmsgcrypt.go b/utils/weworkapi_golang-master/wxbizjsonmsgcrypt.go new file mode 100644 index 00000000..6e729228 --- /dev/null +++ b/utils/weworkapi_golang-master/wxbizjsonmsgcrypt.go @@ -0,0 +1,310 @@ +package weworkapi_golang + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/sha1" + "encoding/base64" + "encoding/binary" + "encoding/json" + "fmt" + "math/rand" + "sort" + "strings" +) + +const letterBytes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + +const ( + ValidateSignatureError int = -40001 + ParseJsonError int = -40002 + ComputeSignatureError int = -40003 + IllegalAesKey int = -40004 + ValidateCorpidError int = -40005 + EncryptAESError int = -40006 + DecryptAESError int = -40007 + IllegalBuffer int = -40008 + EncodeBase64Error int = -40009 + DecodeBase64Error int = -40010 + GenJsonError int = -40011 + IllegalProtocolType int = -40012 +) + +type ProtocolType int + +const ( + JsonType ProtocolType = 1 +) + +type CryptError struct { + ErrCode int + ErrMsg string +} + +func NewCryptError(err_code int, err_msg string) *CryptError { + return &CryptError{ErrCode: err_code, ErrMsg: err_msg} +} + +type WXBizJsonMsg4Recv struct { + Tousername string `json:"tousername"` + Encrypt string `json:"encrypt"` + Agentid string `json:"agentid"` +} + +type WXBizJsonMsg4Send struct { + Encrypt string `json:"encrypt"` + Signature string `json:"msgsignature"` + Timestamp string `json:"timestamp"` + Nonce string `json:"nonce"` +} + +func NewWXBizJsonMsg4Send(encrypt, signature, timestamp, nonce string) *WXBizJsonMsg4Send { + return &WXBizJsonMsg4Send{Encrypt: encrypt, Signature: signature, Timestamp: timestamp, Nonce: nonce} +} + +type ProtocolProcessor interface { + parse(src_data []byte) (*WXBizJsonMsg4Recv, *CryptError) + serialize(msg_send *WXBizJsonMsg4Send) ([]byte, *CryptError) +} + +type WXBizMsgCrypt struct { + token string + encoding_aeskey string + receiver_id string + protocol_processor ProtocolProcessor +} + +type JsonProcessor struct { +} + +func (self *JsonProcessor) parse(src_data []byte) (*WXBizJsonMsg4Recv, *CryptError) { + var msg4_recv WXBizJsonMsg4Recv + err := json.Unmarshal(src_data, &msg4_recv) + if nil != err { + fmt.Println("Unmarshal fail", err) + return nil, NewCryptError(ParseJsonError, "json to msg fail") + } + return &msg4_recv, nil +} + +func (self *JsonProcessor) serialize(msg4_send *WXBizJsonMsg4Send) ([]byte, *CryptError) { + json_msg, err := json.Marshal(msg4_send) + if nil != err { + return nil, NewCryptError(GenJsonError, err.Error()) + } + + return json_msg, nil +} + +func NewWXBizMsgCrypt(token, encoding_aeskey, receiver_id string, protocol_type ProtocolType) *WXBizMsgCrypt { + var protocol_processor ProtocolProcessor + if protocol_type != JsonType { + panic("unsupport protocal") + } else { + protocol_processor = new(JsonProcessor) + } + + return &WXBizMsgCrypt{token: token, encoding_aeskey: (encoding_aeskey + "="), receiver_id: receiver_id, protocol_processor: protocol_processor} +} + +func (self *WXBizMsgCrypt) randString(n int) string { + b := make([]byte, n) + for i := range b { + b[i] = letterBytes[rand.Int63()%int64(len(letterBytes))] + } + return string(b) +} + +func (self *WXBizMsgCrypt) pKCS7Padding(plaintext string, block_size int) []byte { + padding := block_size - (len(plaintext) % block_size) + padtext := bytes.Repeat([]byte{byte(padding)}, padding) + var buffer bytes.Buffer + buffer.WriteString(plaintext) + buffer.Write(padtext) + return buffer.Bytes() +} + +func (self *WXBizMsgCrypt) pKCS7Unpadding(plaintext []byte, block_size int) ([]byte, *CryptError) { + plaintext_len := len(plaintext) + if nil == plaintext || plaintext_len == 0 { + return nil, NewCryptError(DecryptAESError, "pKCS7Unpadding error nil or zero") + } + if plaintext_len%block_size != 0 { + return nil, NewCryptError(DecryptAESError, "pKCS7Unpadding text not a multiple of the block size") + } + padding_len := int(plaintext[plaintext_len-1]) + return plaintext[:plaintext_len-padding_len], nil +} + +func (self *WXBizMsgCrypt) cbcEncrypter(plaintext string) ([]byte, *CryptError) { + aeskey, err := base64.StdEncoding.DecodeString(self.encoding_aeskey) + if nil != err { + return nil, NewCryptError(DecodeBase64Error, err.Error()) + } + const block_size = 32 + pad_msg := self.pKCS7Padding(plaintext, block_size) + + block, err := aes.NewCipher(aeskey) + if err != nil { + return nil, NewCryptError(EncryptAESError, err.Error()) + } + + ciphertext := make([]byte, len(pad_msg)) + iv := aeskey[:aes.BlockSize] + + mode := cipher.NewCBCEncrypter(block, iv) + + mode.CryptBlocks(ciphertext, pad_msg) + base64_msg := make([]byte, base64.StdEncoding.EncodedLen(len(ciphertext))) + base64.StdEncoding.Encode(base64_msg, ciphertext) + + return base64_msg, nil +} + +func (self *WXBizMsgCrypt) cbcDecrypter(base64_encrypt_msg string) ([]byte, *CryptError) { + aeskey, err := base64.StdEncoding.DecodeString(self.encoding_aeskey) + if nil != err { + return nil, NewCryptError(DecodeBase64Error, err.Error()) + } + + encrypt_msg, err := base64.StdEncoding.DecodeString(base64_encrypt_msg) + if nil != err { + return nil, NewCryptError(DecodeBase64Error, err.Error()) + } + + block, err := aes.NewCipher(aeskey) + if err != nil { + return nil, NewCryptError(DecryptAESError, err.Error()) + } + + if len(encrypt_msg) < aes.BlockSize { + return nil, NewCryptError(DecryptAESError, "encrypt_msg size is not valid") + } + + iv := aeskey[:aes.BlockSize] + + if len(encrypt_msg)%aes.BlockSize != 0 { + return nil, NewCryptError(DecryptAESError, "encrypt_msg not a multiple of the block size") + } + + mode := cipher.NewCBCDecrypter(block, iv) + + mode.CryptBlocks(encrypt_msg, encrypt_msg) + + return encrypt_msg, nil +} + +func (self *WXBizMsgCrypt) calSignature(timestamp, nonce, data string) string { + sort_arr := []string{self.token, timestamp, nonce, data} + sort.Strings(sort_arr) + var buffer bytes.Buffer + for _, value := range sort_arr { + buffer.WriteString(value) + } + + sha := sha1.New() + sha.Write(buffer.Bytes()) + signature := fmt.Sprintf("%x", sha.Sum(nil)) + return string(signature) +} + +func (self *WXBizMsgCrypt) ParsePlainText(plaintext []byte) ([]byte, uint32, []byte, []byte, *CryptError) { + const block_size = 32 + plaintext, err := self.pKCS7Unpadding(plaintext, block_size) + if nil != err { + return nil, 0, nil, nil, err + } + + text_len := uint32(len(plaintext)) + if text_len < 20 { + return nil, 0, nil, nil, NewCryptError(IllegalBuffer, "plain is to small 1") + } + random := plaintext[:16] + msg_len := binary.BigEndian.Uint32(plaintext[16:20]) + if text_len < (20 + msg_len) { + return nil, 0, nil, nil, NewCryptError(IllegalBuffer, "plain is to small 2") + } + + msg := plaintext[20 : 20+msg_len] + receiver_id := plaintext[20+msg_len:] + + return random, msg_len, msg, receiver_id, nil +} + +func (self *WXBizMsgCrypt) VerifyURL(msg_signature, timestamp, nonce, echostr string) ([]byte, *CryptError) { + signature := self.calSignature(timestamp, nonce, echostr) + + if strings.Compare(signature, msg_signature) != 0 { + return nil, NewCryptError(ValidateSignatureError, "signature not equal") + } + + plaintext, err := self.cbcDecrypter(echostr) + if nil != err { + return nil, err + } + + _, _, msg, receiver_id, err := self.ParsePlainText(plaintext) + if nil != err { + return nil, err + } + + if len(self.receiver_id) > 0 && strings.Compare(string(receiver_id), self.receiver_id) != 0 { + fmt.Println(string(receiver_id), self.receiver_id, len(receiver_id), len(self.receiver_id)) + return nil, NewCryptError(ValidateCorpidError, "receiver_id is not equil") + } + + return msg, nil +} + +func (self *WXBizMsgCrypt) EncryptMsg(reply_msg, timestamp, nonce string) ([]byte, *CryptError) { + rand_str := self.randString(16) + var buffer bytes.Buffer + buffer.WriteString(rand_str) + + msg_len_buf := make([]byte, 4) + binary.BigEndian.PutUint32(msg_len_buf, uint32(len(reply_msg))) + buffer.Write(msg_len_buf) + buffer.WriteString(reply_msg) + buffer.WriteString(self.receiver_id) + + tmp_ciphertext, err := self.cbcEncrypter(buffer.String()) + if nil != err { + return nil, err + } + ciphertext := string(tmp_ciphertext) + + signature := self.calSignature(timestamp, nonce, ciphertext) + + msg4_send := NewWXBizJsonMsg4Send(ciphertext, signature, timestamp, nonce) + return self.protocol_processor.serialize(msg4_send) +} + +func (self *WXBizMsgCrypt) DecryptMsg(msg_signature, timestamp, nonce string, post_data []byte) ([]byte, *CryptError) { + msg4_recv, crypt_err := self.protocol_processor.parse(post_data) + if nil != crypt_err { + return nil, crypt_err + } + + signature := self.calSignature(timestamp, nonce, msg4_recv.Encrypt) + + if strings.Compare(signature, msg_signature) != 0 { + return nil, NewCryptError(ValidateSignatureError, "signature not equal") + } + + plaintext, crypt_err := self.cbcDecrypter(msg4_recv.Encrypt) + if nil != crypt_err { + return nil, crypt_err + } + + _, _, msg, receiver_id, crypt_err := self.ParsePlainText(plaintext) + if nil != crypt_err { + return nil, crypt_err + } + + if len(self.receiver_id) > 0 && strings.Compare(string(receiver_id), self.receiver_id) != 0 { + return nil, NewCryptError(ValidateCorpidError, "receiver_id is not equil") + } + + return msg, nil +}