企微获取会话内容,RSA 解密函数
- 企微获取会话内容
- 下载SDK
- SDK配置
- 解密过程
- 解密代码参考
- SDK文件上传到服务器
- 最后
企微获取会话内容
官方文档:
https://developer.work.weixin.qq.com/document/path/91774
下载SDK
根据自己的环境下载对应的SDK。
SDK配置
1、sdk中的文件拷贝到项目中
我这里的linux的.so文件,原本是_Java.so那个,我复制了一份去掉了_Java后缀,内容一样的。
2、Finance文件
1)注意要放在 指定路径下
package com.tencent.wework;
2)修改Finance文件
将最后的static代码块改成以下代码
static {
if (isWindows()) {
String path = Finance.class.getClassLoader().getResource("").getPath() + "\\lib\\qywx\\win\\";
path = path.replaceAll("%20", " ").replaceFirst("/", "").replace("/", "\\\\");
//加载顺序不能变
System.load(path.concat("libcrypto-1_1-x64.dll"));
System.load(path.concat("libssl-1_1-x64.dll"));
System.load(path.concat("libcurl-x64.dll"));
System.load(path.concat("WeWorkFinanceSdk.dll"));
} else {
// linux 加载指定so文件在linux系统下的位置
System.load("/usr/lib/libWeWorkFinanceSdk.so");
System.loadLibrary("WeWorkFinanceSdk");
}
}
public static boolean isWindows() {
String osName = System.getProperties().getProperty("os.name");
return osName.toUpperCase().indexOf("WINDOWS") != -1;
}
解密过程
参考官方文档案例演示: https://developer.work.weixin.qq.com/document/path/91551
我这里只展示需要自己开发的RSA解密方法,官方文档是这样描述解密过程的:
encrypt_random_key内容解密说明:
encrypt_random_key是使用企业在管理端填写的公钥(使用模值为2048bit的秘钥),采用RSA加密算法进行加密处理后base64
encode的内容,加密内容为企业微信产生。RSA使用PKCS1。 企业通过GetChatData获取到会话数据后:
a) 需首先对每条消息的encrypt_random_key内容进行base64 decode,得到字符串str1.
b) 使用publickey_ver指定版本的私钥,使用RSA PKCS1算法对str1进行解密,得到解密内容str2.
c) 得到str2与对应消息的encrypt_chat_msg,调用下方描述的DecryptData接口,即可获得消息明文。
注:需要注意的是,如果你用的json处理库会把+号自动转换为空格,要手动转换回来,不然会出错。
String encryptRandomKey = jsonObject.getString("encrypt_random_key");
encryptRandomKey = encryptRandomKey.replace(" ", "+");
比如说com.alibaba.fastjson.JSONObject
解密代码参考
String data = this.decodeWeworkData(encryptRandomKey);//解密
long msg = Finance.NewSlice();
int decryptDataReturn = Finance.DecryptData(sdk, data, encryptChatMsg, msg);//调用企微sdk获取消息明文msg
String decryDataMsg = Finance.GetContentFromSlice(msg);//消息明文,json格式
Finance.FreeSlice(msg);//释放
注:最后decryDataMsg
就是解密后的消息明文。
下面是具体的解密方法:
public String decodeWeworkData(String chatData) {
//解密
String str = null;
try {
str = getPrivateKeyByPKCS1(chatData, priKey);
} catch (Exception e) {
System.out.println("解密错误");
e.printStackTrace();
}
return str;
}
public static String getPrivateKeyByPKCS1(String encrypt_random_key,String privKeyPEM) throws Exception {
String privKeyPEMnew = privKeyPEM.replaceAll("\\n", "").replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("-----END RSA PRIVATE KEY-----", "");
byte[] bytes = java.util.Base64.getDecoder().decode(privKeyPEMnew);
DerInputStream derReader = new DerInputStream(bytes);
DerValue[] seq = derReader.getSequence(0);
BigInteger modulus = seq[1].getBigInteger();
BigInteger publicExp = seq[2].getBigInteger();
BigInteger privateExp = seq[3].getBigInteger();
BigInteger prime1 = seq[4].getBigInteger();
BigInteger prime2 = seq[5].getBigInteger();
BigInteger exp1 = seq[6].getBigInteger();
BigInteger exp2 = seq[7].getBigInteger();
BigInteger crtCoef = seq[8].getBigInteger();
RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2, exp1, exp2, crtCoef);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
// 64位解码加密后的字符串
byte[] inputByte = Base64.decodeBase64(encrypt_random_key.getBytes("UTF-8"));
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
//RSA解密
String outStr = new String(cipher.doFinal(inputByte));
return outStr;
}
其中priKey
是私钥,我是直接写在了代码里了,参考案例演示:
注:RSA使用PKCS1,模值为2048bit
SDK文件上传到服务器
例如使用Docker部署,添加如下代码至Dockerfile,
COPY src/main/resources/lib/qywx/linux/libWeWorkFinanceSdk.so /usr/lib/libWeWorkFinanceSdk.so
最后
希望对你有所帮助,有疑问和错误欢迎讨论和指正。