企业微信会话存档开发爬坑记(golang+linux)

背景:

      群友有问会话存档的解密问题,本来想着就是一个RSA的加解密应该也不难啊,想着就调试一把。结果就爬出来下面的坑。。。.

1)开发环境问题

2)IP加白

3)  解密密钥(最容易搞混的地方)

4)密钥版本(最容易出错的地方)

5)代理服务器(暂时没碰到,看别人有写)

1、开发环境问题

      会话存档的api只支持windows和linux,而我只有windows和mac。本着不折腾的原则,先配置了下windows。

      结果这才是折腾的开始,因为没有gcc就 尝试安装了 mingw64和cygwin;可能真是对这个windows的配置不熟悉,最终没有配置成功,放弃了。

      最后思路:在mac上跑了docker,利用linux的容器来编译代码!完整dockerfile如下。

FROM golang:1.18.3WORKDIR /appADD . .ENV GOPROXY="https://goproxy.cn"ENV CGO_ENBLED 1ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:/app/libRUN go build  -ldflags="-s -w" -installsuffix cgo -o msg-auditCMD ["msg-audit"]

开发时只要启动golang:1.18.3到容器里手动运行即可。(当然GoLand还可以配置 容器环境,不想折腾了)

2、IP加白

     这个没啥可说的,去归档应用上添加上IP就行了。毕竟现在连自建应用都要加IP白名单了。

    不添加IP会 报错40001

企业微信会话存档开发爬坑记(golang+linux)

 可疑的是还报过一个41001的错误提示access_token错误

企业微信会话存档开发爬坑记(golang+linux)

(上图是从网上截取的,开始没有截图)结果也是IP加白后就好了!

3、解密密钥

    这是最容易搞混的地方,按示例拿到的消息内容如下:

{"errcode":0,"errmsg":"ok",  "chatdata":[       {"seq":196,       "msgid":"CAQQ2fbb4QUY0On2rYSAgAMgip/yzgs=",       "publickey_ver":3,       "encrypt_random_key":"ftJ+uz3n/z1DsxlkwxNgE+mL38H42/KCvN8T60gbbtPD+Rta1hKTuQPzUzO6Hzne97MgKs7FfdDxDck/v8cDT6gUVjA2tZ/M7euSD0L66opJ/IUeBtpAtvgVSD5qhlaQjvfKJc/zPMGNK2xCLFYqwmQBZXbNT7uA69Fflm512nZKW/piK2RKdYJhRyvQnA1ISxK097sp9WlEgDg250fM5tgwMjujdzr7ehK6gtVBUFldNSJS7ndtIf6aSBfaLktZgwHZ57ONewWq8GJe7WwQf1hwcDbCh7YMG8nsweEwhDfUz+u8rz9an+0lgrYMZFRHnmzjgmLwrR7B/32Qxqd79A==",       "encrypt_chat_msg":"898WSfGMnIeytTsea7Rc0WsOocs0bIAerF6de0v2cFwqo9uOxrW9wYe5rCjCHHH5bDrNvLxBE/xOoFfcwOTYX0HQxTJaH0ES9OHDZ61p8gcbfGdJKnq2UU4tAEgGb8H+Q9n8syRXIjaI3KuVCqGIi4QGHFmxWenPFfjF/vRuPd0EpzUNwmqfUxLBWLpGhv+dLnqiEOBW41Zdc0OO0St6E+JeIeHlRZAR+E13Isv9eS09xNbF0qQXWIyNUi+ucLr5VuZnPGXBrSfvwX8f0QebTwpy1tT2zvQiMM2MBugKH6NuMzzuvEsXeD+6+3VRqL"       }   ]}

按文档说明:

    encrypt_random_key是使用企业在管理端填写的公钥(使用模值为2048bit的秘钥),采用RSA加密算法进行加密处理后base64 encode的内容,加密内容为企业微信产生。RSA使用PKCS1。

    就是这个encrypt_random_key要使用配置的对应私钥先进行解密,解密出来后的字符串才是用来解密聊天内容DecryptData函数的encrypt_key参数

所以通过GetChatData获取到会话数据后流程解密流程是:

a) 需首先对每条消息的encrypt_random_key内容进行base64 decode,得到字符串str1.
b) 使用publickey_ver指定版本的私钥,使用RSA PKCS1算法对str1进行解密,得到解密内容str2.
c) 得到str2与对应消息的encrypt_chat_msg,调用下方描述的DecryptData接口,即可获得消息明文。

以上步骤来源于官方文档,请大家还是多留意文档!!!

int DecryptData(const char* encrypt_key, const char* encrypt_msg, Slice_t* msg);

一定要注意使用的RSA是2048位PKCS1格式! RSA是2048位PKCS1格式!! RSA是2048位PKCS1格式!!!

可以在linux上使用如下命令生成

openssl genrsa -out private_key.pem 2048openssl rsa -in private_key.pem -pubout -out public_key.pem

4、密钥版本

在一再确认群友使用的私钥是正确的以后,发现解密 encrypt_random_key 还是会出现 crypto/rsa:decryption error,

最后留意到这个版本号上,因为开始拉取的聊天记录只有10条,也没注意这个版本号,就加大了条数看了下果然有新设置的版本号下的记录。

找到最新的版本号密钥进行解密正常!企业微信会话存档开发爬坑记(golang+linux)

文本消息解密后结果如下:

{%20%20"msgid":"5899772985335728163_1656292663584_external",%20%20"action":"send",%20%20"from":"xxxxxxxxxxxxx",%20%20"tolist":["xxxxxxxxxx"],%20%20"roomid":"",%20%20"msgtime":1656292663307,%20%20"msgtype":"text",%20%20"text":{"content":"我看下能不能读到吧"}}

 %20  在企业后台每设置一次公钥这个版本号就会增加,而在企业微信服务端是分时间段进行加密的,比如:

 %20 %201月1日开始设置了加密对,版本号为1

 %20 %202月1日又设置了新的加密对,版本号为2

 在1月1日到2月1日期间是使用版本号1的公钥对encrypt_random_key 进行的加密,在2月1日后是使用的新的公钥(版本号为2)对encrypt_random_key%20进行加密。

 %20 %20 所以要保存好每一个版本的加密对,不然历史数据将无法解密!!!

5、代理服务器

 %20 %20 如果读取存档的服务器不能直接连接外网,需要配置代理服务器的,这个需要设置。

 %20 %20 但直接连接服务器时要注意proxy和passwd不能传null,只能是空的字符串

int%20GetChatData(WeWorkFinanceSdk_t*%20sdk,%20unsigned%20long%20long%20seq,%20unsigned%20int%20limit,%20const%20char%20*proxy,const%20char*%20passwd,int%20timeout,Slice_t*%20chatDatas);

整体流程如官方文档里的图:

在开发中还有遇到哪些问题?可以留言反馈!!!

另:虽然开源的会话存档应用也有不少,还是打算再造个轮子!

打算包含如下功能:

  • 1、文件存储支持上传到又拍云、七牛云、腾讯云、阿里云等

  • 2、聊天记录内容支持写入数据库(gorm支持的库都可以)

  • 3、支持将已解密的消息写入队列(redis或者rabbitmq)满足数据结构不一致要自己处理存储的问题

  • 4、产生会话回调事件回调后再同步消息避免一直轮循

  • 5、docker部署,不再关心是windows还是linux也或者是mac

感谢大家的持续关注!!!