微信公众号消息加解密
在微信公众号的使用过程中,为了提高信息传输的安全性,可以在服务器配置中将消息加解密模式指定为安全模式。
启用安全模式后,公众号主动调用API的情况并不会受影响,只有被动回复用户的消息时才需要对消息进行加解密。
官方提供了5种开发语言的示例代码,参照官方给的C++示例代码,本文给出go语言的解密实现:
func handlerEncrypt(body []byte, timestamp, nonce, msg_sig string) (random, rawXMLMsg []byte, err error) { request := &WeChatEncryptRequest{} err = xml.Unmarshal(body, request) if err != nil { log.Errorf("unmarshal wechat encrypt request error: %s") errors.Wrap(err, "unmarshal wechat encrypt request error") return } // verify msg from wechat signature if calcSignature(token, timestamp, nonce, request.Encrypt) != msg_sig { log.Errorf("encrypt msg got from wechat verify signature failed") errors.New("encrypt msg got from wechat verify signature failed") return } // decode cipher text from base64 cipherText, err := base64.StdEncoding.DecodeString(request.Encrypt) if err != nil { log.Errorf("decode wechat encrypt request error: %s", err.Error()) errors.Wrap(err, "decode wechat encrypt request error") return } // aes decrypt plainText, err := aesDecrypt(cipherText, key) if err != nil { log.Errorf("decrypt wechat encrypt request error: %s", err.Error()) errors.Wrap(err, "decrypt wechat encrypt request error") return } // get raw wechat encrypt request length rawXMLMsgLen := int(ntohl(plainText[16:20])) if rawXMLMsgLen < 0 { log.Errorf("incorrect msg length: %d", rawXMLMsgLen) errors.Wrapf(err, "incorrect msg length: %d", rawXMLMsgLen) return } // verify appid appIDOffset := 20 + rawXMLMsgLen if len(plainText) <= appIDOffset { log.Errorf("msg length too large: %d", rawXMLMsgLen) errors.Wrapf(err, "msg length too large: %d", rawXMLMsgLen) return } // verify appid if appID != string(plainText[appIDOffset:]) { log.Errorf("Received an attack disguised as a WeChat server.") errors.New("Received an attack disguised as a WeChat server.") return } // get random which from wechat random = plainText[:16:20] // raw wechat msg rawXMLMsg = plainText[20:appIDOffset:appIDOffset] return } func calcSignature(args ...string) string { sort.Strings(args) h := sha1.New() for _, arg := range args { io.WriteString(h, arg) } return hex.EncodeToString(h.Sum(nil)) } func aesDecrypt(cipherText []byte, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } blockSize := block.BlockSize() blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) plainText := make([]byte, len(cipherText)) blockMode.CryptBlocks(plainText, cipherText) plainText = pkcs7UnPadding(plainText) return plainText, nil } func pkcs7UnPadding(data []byte) []byte { length := len(data) unpadding := int(data[length-1]) return data[:(length - unpadding)] } func ntohl(orderBytes []byte) (n uint32) { return uint32(orderBytes[0])<<24 | uint32(orderBytes[1])<<16 | uint32(orderBytes[2])<<8 | uint32(orderBytes[3]) }
完整的代码示例在这里。
声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2021-04-26 Fabric网络升级(四)
2021-04-26 Fabric网络升级(三)
2021-04-26 Fabric网络升级(二)
2021-04-26 Fabric网络升级(一)
2021-04-26 Fabric网络升级(总)