企业开发采坑——会话代理,会话内容解密
在聊企业会话内容解密之前,先说⼀说会话内容⽩名单遇到的问题,因为部署的服务器是不能连接外⽹的,所以需要通过服务器的另⼀台机器代理请求访问,先来看⼀下官
⽅⽂档给出的描述
proxy否使⽤代理的请求,需要传⼊代理的链接。如:socks5://10.0.0.1:8081 或者 10.0.0.1:8081.如不使⽤代理可以设置为空. ⽀持sock5跟http代理
paswd否代理账号密码,需要传⼊代理的账号密码。如 user_name:passwd_123
在这⾥proxy是指我可以访问公⽹并且添加了对应⽩名单的机器,paswd是指⽤户名和密码,中间⽤【:】分隔。
⾸先需要⼀台代理机器,开始我再代理机器A上部署了nginx,并且⽤curl也可以尝试请求到数据
curl --proxy
但是curl https的时候会返回400
curl --proxy
这⾥前⾯是对应A机器的内⽹地址,8001是转发服务的端⼝,nginx的配置也只是利⽤8001的端⼝进⾏监听,然后转发到qyapi.weixin.qq,后来在sdk包联调调⽤的时
候,想到转发的接⼝⽤到的应该是https请求,但是https在ng中需要升级对应的模块,⽽且ng上配置也⽐较多,不能随便乱改,后台直接在A机器上装了squid代理服务。解决
问题。
第二次人生的演员⾄于ng为什么转发https需要单独的模块,可以参考下⾯⼏篇⽂章
linux 搭建squid可以参考如下⽂章,⼀种是源码安装,⼀种是yum安装
blog.csdn/weixin_30363817/article/details/98212574
wwwblogs/suntray/p/14452861.html
最后在调⽤ curl --proxy
成功
------------------------------------------------------------------------------------------------------------------------------
下⾯继续聊⼀聊企业会话内容开发过程中的解密问题
⾸先还是看官⽅⽂档给出的内容讲解
ChatDatas详解:
1. {"errcode":0,"errmsg":"ok","chatdata":
[{"seq":196,"msgid":"CAQQ2fbb4QUY0On2rYSAgAMgip/yzgs=","publickey_ver":3,"encrypt_random_key":"ftJ+uz3n/z1DsxlkwxNgE+mL38H42/KCvN8T60gbbtPD+Rta1hKTuQPzUzO6Hzne97Mg 返回参数说明:
参数说明
errcode0表⽰成功,错误返回⾮0错误码,需要参看errmsg。Uint32类型
errmsg返回信息,如⾮空为错误原因。String类型
chatdata聊天记录数据内容。数组类型。包括seq、msgid等内容
seq消息的seq值,标识消息的序号。再次拉取需要带上上次回包中最⼤的seq。Uint64类型,范围0-pow(2,64)-1
msgid消息id,消息的唯⼀标识,企业可以使⽤此字段进⾏消息去重。String类型。msgid以_external结尾的消息,表明该消息是⼀条外部消息。
publickey_ver加密此条消息使⽤的公钥版本号。Uint32类型
encrypt_random_key 使⽤publickey_ver指定版本的公钥进⾏⾮对称加密后base64加密的内容,需要业务⽅先base64 decode处理后,再使⽤指定版本的私钥进⾏解密,得出内容。String类型
encrypt_chat_msg消息密⽂。需要业务⽅使⽤将encrypt_random_key解密得到的内容,与encrypt_chat_msg,传⼊sdk接⼝DecryptData,得到消息明⽂。String类型
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接⼝,即可获得消息明⽂。
这⾥先聊⼀聊后台怎么配置,在配置秘钥的时候,先要⽣成好公钥和私钥,如果想⽅便⼀些,可以到下⾯的⽹站直接⽣成
把上⾯的公钥内容设置到后台的公钥中,下⾯的私钥⾃⼰保存好,⽤于解密
然后解密的内容可以参考下⾯⼏篇⽂章李晨与范冰冰
这⾥主要说⼀下PKCS8的秘钥格式,由于我当时⽣成秘钥的时候没有选秘钥格式,默认的是PKCS8,后来在同事的帮助下最终还是解析出来了数据内容。
记得调试的时候把
-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
换⾏符/n都替换成""空字符串。
//encryptionDto是解析出来的密⽂对象
String encryptChatMsg = Encrypt_chat_msg();
String encryptRandomKey = Encrypt_random_key();
String encrypt_key = null;
try {
//PrivateKey()是⾃⼰保存的对应的私钥
encrypt_key = PrivateKey3(PrivateKey());
} catch (Exception e) {
<("解密数据会话数据失败 encryptionDto:"+JSONString(encryptionDto), e);
continue;
}
// 将获取到的数据进⾏解密操作
法国世界杯阵容2022//long msg = Finance.NewSlice();
log.info("=======msgs==msgs=======:"+slice);
int ret = Finance.DecryptData(sdk, encrypt_key, encryptChatMsg, slice);
log.info("=======ret==ret=======:"+ret);
String decrypt_msg = Finance.GetContentFromSlice(slice);// 解密后的消息
log.info("解密后的内容 {}", decrypt_msg);
import dec.binary.Base64;
pto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/
**
* RSA加密和解密⼯具
* RSA加密和解密⼯具
*
*/
public class RSAUtil {
/**
* 数字签名,密钥算法
*/
private static final String RSA_KEY_ALGORITHM = "RSA";
/**
* 数字签名签名/验证算法
*/
private static final String SIGNATURE_ALGORITHM = "MD5withRSA";
/**
* RSA密钥长度,RSA算法的默认密钥长度是1024密钥长度必须是64的倍数,在512到65536位之间 */
private static final int KEY_SIZE = 1024;
/**
* ⽣成密钥对
*/
private static Map<String, String> initKey() throws Exception {
KeyPairGenerator keygen = Instance(RSA_KEY_ALGORITHM);
SecureRandom secrand = new SecureRandom();
/**
* 初始化随机产⽣器
*/
secrand.setSeed("initSeed".getBytes());
/**
* 初始化密钥⽣成器
*/
keygen.initialize(KEY_SIZE, secrand);
KeyPair keys = KeyPair();
byte[] pub_key = Public().getEncoded();
String publicKeyString = deBase64String(pub_key);
byte[] pri_key = Private().getEncoded();
String privateKeyString = deBase64String(pri_key);
Map<String, String> keyPairMap = new HashMap<String, String>();
keyPairMap.put("publicKeyString", publicKeyString);
keyPairMap.put("privateKeyString", privateKeyString);
return keyPairMap;
}
/**
* 密钥转成字符串
*
* @param key
* @return
*/
public static String encodeBase64String(byte[] key) {
deBase64String(key);
}
/**
* 密钥转成byte[]
*
* @param key
* @return
*/
public static byte[] decodeBase64(String key) {
return Base64.decodeBase64(key);
}
/**
* 公钥加密
*
* @param data 加密前的字符串
* @param publicKey 公钥
* @return 加密后的字符串
* @throws Exception
*/
public static String encryptByPubKey(String data, String publicKey) throws Exception {
byte[] pubKey = RSAUtil.decodeBase64(publicKey);
byte[] enSign = Bytes(), pubKey);
deBase64String(enSign);
}
/**
* 公钥加密
*
* @param data 待加密数据
* @param pubKey 公钥
* @return
* @throws Exception
*/
public static byte[] encryptByPubKey(byte[] data, byte[] pubKey) throws Exception {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
杨慧微博KeyFactory keyFactory = Instance(RSA_KEY_ALGORITHM);
PublicKey publicKey = atePublic(x509KeySpec);
Cipher cipher = Algorithm());
Cipher cipher = Algorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 私钥加密
*
* @param data 加密前的字符串
* @param privateKey 私钥
* @return 加密后的字符串
* @throws Exception
*/
public static String encryptByPriKey(String data, String privateKey) throws Exception {
byte[] priKey = RSAUtil.decodeBase64(privateKey);
byte[] enSign = Bytes(), priKey);
deBase64String(enSign);
}
/**
* 私钥加密
*
* @param data 待加密的数据
* @param priKey 私钥
* @return 加密后的数据
* @throws Exception
*/
public static byte[] encryptByPriKey(byte[] data, byte[] priKey) throws Exception {
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
KeyFactory keyFactory = Instance(RSA_KEY_ALGORITHM);
PrivateKey privateKey = atePrivate(pkcs8KeySpec);
Cipher cipher = Algorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 公钥解密
*
* @param data 待解密的数据
* @param pubKey 公钥
* @return 解密后的数据
* @throws Exception
*/
public static byte[] decryptByPubKey(byte[] data, byte[] pubKey) throws Exception {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
KeyFactory keyFactory = Instance(RSA_KEY_ALGORITHM);
PublicKey publicKey = atePublic(x509KeySpec);
Cipher cipher = Algorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 公钥解密
*
* @param data 解密前的字符串
* @param publicKey 公钥
* @return 解密后的字符串
* @throws Exception
*/
public static String decryptByPubKey(String data, String publicKey) throws Exception {
byte[] pubKey = RSAUtil.decodeBase64(publicKey);
byte[] design = decryptByPubKey(Base64.decodeBase64(data), pubKey);
return new String(design);
}
/*private static PrivateKey getPrivateKey (String privateKey) throws Exception {
十月十Reader privateKeyReader = new StringReader(privateKey);
PEMParser privatePemParser = new PEMParser(privateKeyReader);
Object privateObject = adObject();
if (privateObject instanceof PEMKeyPair) {
PEMKeyPair pemKeyPair = (PEMKeyPair) privateObject;
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
PrivateKey privKey = PrivateKeyInfo());
return privKey;
}
return null;
}*/
// //读取pkcs1格式的private key
// public static PrivateKey getPrivateKey2(String privKeyPEM) throws Exception{
//
// String privKeyPEMnew = placeAll("\\n", "").replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("-----END RSA PRIVATE KEY-----", ""); // byte[] bytes = RSAUtil.decodeBase64(privKeyPEMnew);
//
// DerInputStream derReader = new DerInputStream(bytes);
// DerValue[] seq = Sequence(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();
// BigInteger crtCoef = seq[8].getBigInteger();
/
/
// RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2, exp1, exp2, crtCoef); // KeyFactory keyFactory = Instance("RSA");
// PrivateKey privateKey = atePrivate(keySpec);
// return privateKey;
// }
/*public static RSAPrivateKey loadPrivateKeyByStr(String privateKeyStr)
throws Exception {
try {
byte[] buffer = Base64.decodeBase64(privateKeyStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = Instance("RSA");
return (RSAPrivateKey) atePrivate(keySpec);
} catch (NoSuchAlgorithmException e) {
throw new Exception("⽆此算法");
} catch (InvalidKeySpecException e) {
throw new Exception("私钥⾮法");
} catch (NullPointerException e) {
throw new Exception("私钥数据为空");
}
}*/
/**
* 私钥解密
锦鲤鱼怎么养*
* @param data 待解密的数据
* @param priKey 私钥
* @return
* @throws Exception
*/
/*public static byte[] decryptByPriKey(byte[] data, byte[] priKey) throws Exception {
// PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
// KeyFactory keyFactory = Instance(RSA_KEY_ALGORITHM);
// PrivateKey privateKey = atePrivate(pkcs8KeySpec);
RSAPrivateKeyStructure asn1PrivKey = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(priKey));
RSAPrivateKeySpec rsaPrivKeySpec = new Modulus(), PrivateExponent()); KeyFactory keyFactory= Instance("RSA");
PrivateKey privateKey= atePrivate(rsaPrivKeySpec);
Cipher cipher = Algorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}*/
/**
* 私钥解密
*
* @param data 解密前的字符串
* @param privateKey 私钥
* @return 解密后的字符串
* @throws Exception
*/
/*public static String decryptByPriKey(String data, String privateKey) throws Exception {
Security.addProvider(new BouncyCastleProvider());
Cipher rsa = Instance("RSA/ECB/PKCS1Padding", "BC");
rsa.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey));
byte[] utf8 = rsa.doFinal(Base64.decodeBase64(data));
String result = new String(utf8,"UTF-8");
return result;
}*/
/
**
* RSA签名
*
* @param data 待签名数据
* @param priKey 私钥
* @return 签名
* @throws Exception
*/
public static String sign(byte[] data, byte[] priKey) throws Exception {
// 取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
KeyFactory keyFactory = Instance(RSA_KEY_ALGORITHM);
// ⽣成私钥
PrivateKey privateKey = atePrivate(pkcs8KeySpec);
// 实例化Signature
Signature signature = Instance(SIGNATURE_ALGORITHM);
// 初始化Signature
signature.initSign(privateKey);
// 更新
signature.update(data);
deBase64String(signature.sign());
}
/
**
* RSA校验数字签名
*
* @param data 待校验数据
* @param sign 数字签名
* @param pubKey 公钥
* @return boolean 校验成功返回true,失败返回false
*/
public boolean verify(byte[] data, byte[] sign, byte[] pubKey) throws Exception {
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论