背景:
群友有问会话存档的解密问题,本来想着就是一个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.3
WORKDIR /app
ADD . .
ENV GOPROXY="https://goproxy.cn"
ENV CGO_ENBLED 1
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:/app/lib
RUN go build -ldflags="-s -w" -installsuffix cgo -o msg-audit
CMD ["msg-audit"]
开发时只要启动golang:1.18.3到容器里手动运行即可。(当然GoLand还可以配置 容器环境,不想折腾了)
2、IP加白
这个没啥可说的,去归档应用上添加上IP就行了。毕竟现在连自建应用都要加IP白名单了。
不添加IP会 报错40001
可疑的是还报过一个41001的错误提示access_token错误
(上图是从网上截取的,开始没有截图)结果也是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 2048
openssl rsa -in private_key.pem -pubout -out public_key.pem
4、密钥版本
在一再确认群友使用的私钥是正确的以后,发现解密 encrypt_random_key 还是会出现 crypto/rsa:decryption error,
最后留意到这个版本号上,因为开始拉取的聊天记录只有10条,也没注意这个版本号,就加大了条数看了下果然有新设置的版本号下的记录。
找到最新的版本号密钥进行解密正常!
文本消息解密后结果如下:
{
%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
感谢大家的持续关注!!!