微信公众号消息加解密

公众,消息,加解密 · 浏览次数 : 176

小编点评

**Go语言的解密实现** ```go import ( "encoding/hex" "crypto/aes" "crypto/tls" "crypto/xml" ) // handlerEncrypt handles WeChat encrypt requests. func handlerEncrypt(body []byte, timestamp, nonce, msg_sig string) (string, []byte, error) { // Parse request body. request := &xml.Unmarshal(body)[0] // Verify msg signature. if calcSignature(token, timestamp, nonce, request.Encrypt) != msg_sig { return "", nil, fmt.Errorf("encrypt msg got from wechat verify signature failed") } // Decode cipher text. cipherText, err := base64.StdEncoding.DecodeString(request.Encrypt) if err != nil { return "", nil, fmt.Errorf("decode wechat encrypt request error: %w", err) } // Decrypt cipher text. key := []byte("your_aes_key_here") // Replace with your actual key. plaintext, err := aesDecrypt(cipherText, key) if err != nil { return "", nil, fmt.Errorf("decrypt wechat encrypt request error: %w", err) } // Get raw XML message length. rawXMLMsgLen := int(ntohl(plaintext[16:20])) // Verify appid. if len(plaintext) < appIDOffset || appID != string(plaintext[appIDOffset:]) { return "", nil, fmt.Errorf("Received an attack disguised as a WeChat server.") } // Return decrypted plaintext. return plaintext, nil } ``` **使用说明:** 1. 将您的密钥(`your_aes_key_here`)替换为您的 AES 密钥。 2. 将 `appIDOffset` 设置为您的公众号的 ID 的长度。 3. 将 `timestamp`、`nonce` 和 `msg_sig` 从您公众号中获取。 4. 将 `body` 传入 `handlerEncrypt` 函数中。 5. 运行程序。 **注意:** * 此代码需要安装 `crypto/aes`、`crypto/tls` 和 `crypto/xml` 库。 * 请确保您使用正确的密钥。 * 请确保您遵守微信的安全协议。

正文

在微信公众号的使用过程中,为了提高信息传输的安全性,可以在服务器配置中将消息加解密模式指定为安全模式

启用安全模式后,公众号主动调用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: 恋水无意


与微信公众号消息加解密相似的内容:

微信公众号消息加解密

在微信公众号的使用过程中,为了提高信息传输的安全性,可以在服务器配置中将消息加解密模式指定为安全模式。 启用安全模式后,公众号主动调用API的情况并不会受影响,只有被动回复用户的消息时才需要对消息进行加解密。 官方提供了5种开发语言的示例代码,参照官方给的C++示例代码,本文给出go语言的解密实现:

2023-04-26-微信安全模式下消息解析

在微信公众号的使用过程中,为了提高信息传输的安全性,可以在服务器配置中将消息加解密模式指定为安全模式。 启用安全模式后,公众号主动调用API的情况并不会受影响,只有被动回复用户的消息时才需要对消息进行加解密。 官方提供了5种开发语言的示例代码,参照官方给的C++示例代码,本文给出go语言的解密实现:

java实现 微信公众号推送消息 ,cv 就可运行!!!

一,注册公众号 1,官网地址:申请测试公众号 地址: 微信公众平台 (qq.com) 文档地址:微信开放文档 (qq.com) 2,注册后可以查看自己的appId 和 appsecret 3,创建模板 请注意: 1、测试模板的模板ID仅用于测试,不能用来给正式帐号发送模板消息 2、为方便测试,测试模

处理来自微信的文本消息

官方文档在这里。 我们的公众号服务器可以接收来自微信服务器的普通消息,包括: 文本消息 图片消息 语音消息 小视频消息 地理位置消息 链接消息 这里以文本消息为例,介绍如何处理微信服务器转发给我们的用户消息。 当普通微信用户向公众账号发消息时,微信服务器将向我们填写写的URL上发送一条包含XML数据

验证来自微信服务器的消息

内容来自微信官方文档。 接入微信公众平台开发,开发者需要按照如下步骤完成: 填写服务器配置 验证服务器地址的有效性 依据接口文档实现业务逻辑 微信官方的文档已经写得很详细,官方给出的例子是基于php的,这里给出go实现的消息验证,http框架使用的是gin。 type WeChatVerify st

文章《Semantic Kernel -- LangChain 的替代品?》的错误和疑问 探讨

微信公众号文章 Semantic Kernel —— LangChain 的替代品?[1] ,它使用的示例代码是Python ,他却发了这么一个疑问:支持的语言对比(因为 Semantic Kernel 是用 C#开发的,所以它对 C#比较支持)如上所示。不清楚 Semantic Kernel 为什

微信小程序生态13-微信公众号自定义菜单配置

序 微信公众号分为订阅号和服务号两种,虽然二者很大的不同,但是这两种公众号的底部却是差不多的:都有菜单栏,而且这些底部菜单也都是自定义配置的。 如CSDN的官方公众号的底部就有精彩栏目、新程序员、CSDN等菜单可供使用: 那这些菜单是如何生成的呢?微信以配置方式的不同把它分为了两类:自定义菜单、个性

Oracle修改字段长度及属性

首发微信公众号:SQL数据库运维 原文链接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247486117&idx=1&sn=02e2cd05e5db7eaa5758c70e81cf3972&chksm=ea375ed5dd40d7c

[转帖]Redis6通信协议升级至RESP3,一口气看完13种新数据类型

原创:微信公众号 码农参上,欢迎分享,转载请保留出处。 在前面的文章 Redis:我是如何与客户端进行通信的 中,我们介绍过RESP V2版本协议的规范,RESP的全程是Redis Serialization Protocol,基于这个实现简单且解析性能优秀的通信协议,Redis的服务端与客户端可以

[转帖]编译实战 | 手摸手教你在Windows环境下运行Redis6.x

原创:微信公众号 码农参上,欢迎分享,转载请保留出处。 哈喽大家好啊,我是没事就愿意瞎捣鼓的Hydra。 不知道有没有小伙伴像我一样,平常开发中用的是windows操作系统,有时候想装点什么软件,一看只支持linux系统,无奈要么启动虚拟机、要么装在云服务器上。 这不前几天又是这样,刚想用一下Red