尝试了各种方法,没有解决安卓与jre的javax.encrypto冲突的问题,下周准备返璞归真,不使用sm4而重新使用aes进行对称加密通信

This commit is contained in:
free will
2021-07-23 15:08:50 +08:00
parent 1e522e16f8
commit 4c21165f8d
8 changed files with 245 additions and 16 deletions
+12 -3
View File
@@ -34,7 +34,7 @@ android {
} }
compileSdkVersion 30 compileSdkVersion 30
buildToolsVersion "30.0.3" buildToolsVersion '30.0.3'
sourceSets.main.jniLibs.srcDirs = ['libs'] sourceSets.main.jniLibs.srcDirs = ['libs']
@@ -75,8 +75,17 @@ android {
} }
dependencies { dependencies {
implementation files('libs\\gmhelper.jar') implementation files('libs/gmhelper.jar')
implementation files('libs\\BaiduLBS_Android.jar') implementation files('libs/BaiduLBS_Android.jar')
implementation files('libs/vpnjce-1.0.jar')
// 在依赖中添加对jre的依赖,以尝试解决android.jar中原生javax与java中的javax的冲突问题
//noinspection GradlePath
// implementation files('C:/MyEnv/Java/jdk1.8.0_301/jre/lib/rt.jar')
// compileOnly files('C:/MyEnv/Java/jdk1.8.0_301/jre/lib/rt.jar')
// implementation files('C:/MyEnv/Java/jdk1.8.0_301/jre/lib/jce.jar')
// compileOnly files('C:/MyEnv/Java/jdk1.8.0_301/jre/lib/jce.jar')
// implementation files('libs\\jce.jar')
// testImplementation 'junit:junit:4.+' // testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.ext:junit:1.1.2'
Binary file not shown.
@@ -18,14 +18,12 @@ import android.text.TextUtils;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import com.pkusz.min_vpn_client.model.MINVpnSettingAPI; import com.pkusz.min_vpn_client.model.MINVpnSettingAPI;
import com.pkusz.min_vpn_client.utils.AESHelperForConnection;
import com.pkusz.min_vpn_client.utils.IPPackageUtil; import com.pkusz.min_vpn_client.utils.IPPackageUtil;
import com.pkusz.min_vpn_client.utils.KeyManager; import com.pkusz.min_vpn_client.utils.KeyManager;
import com.pkusz.min_vpn_client.utils.RSACryptoForConnection;
import com.pkusz.min_vpn_client.utils.RuleUtil; import com.pkusz.min_vpn_client.utils.RuleUtil;
import com.pkusz.min_vpn_client.utils.SM2HelperForConnection; import com.pkusz.min_vpn_client.utils.SM2HelperForConnection;
import com.pkusz.min_vpn_client.utils.SM3HelperForConnection;
import com.pkusz.min_vpn_client.utils.SM4HelperForConnection; import com.pkusz.min_vpn_client.utils.SM4HelperForConnection;
import com.pkusz.min_vpn_client.utils.SafetyInfoUtil;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@@ -43,8 +41,6 @@ import logicface.LogicFace;
import logicface.LogicFaceException; import logicface.LogicFaceException;
import mgmt.RegisterPrefixHelper; import mgmt.RegisterPrefixHelper;
import packet.CPacket; import packet.CPacket;
import packet.Data;
import packet.Interest;
import packet.PacketException; import packet.PacketException;
import util.ByteHelper; import util.ByteHelper;
@@ -71,6 +67,8 @@ public class MINVpnConnection implements Runnable{
private final byte[] mSharedSecret; private final byte[] mSharedSecret;
private final String mSharedSecretString; private final String mSharedSecretString;
private byte[] mEncryptedAESSeed; private byte[] mEncryptedAESSeed;
// 实际使用的密钥是:随机产生的密钥经过sm3哈希,取前16字节
private byte[] realSecret;
// 代理地址 todo:?? // 代理地址 todo:??
private String mProxyHostName; private String mProxyHostName;
@@ -80,7 +78,7 @@ public class MINVpnConnection implements Runnable{
private final boolean mAllow; private final boolean mAllow;
private final Set<String> mPackages; private final Set<String> mPackages;
// todo: ?? // 服务器给客户端的tun网卡分配的IP地址
private String allocatedAddress; private String allocatedAddress;
// 待决Intent、回调函数(建立连接成功;建立连接失败;长时间不操作的超时回调) // 待决Intent、回调函数(建立连接成功;建立连接失败;长时间不操作的超时回调)
@@ -127,8 +125,11 @@ public class MINVpnConnection implements Runnable{
mServerPort=serverPort; mServerPort=serverPort;
mSharedSecret=sharedSecret; mSharedSecret=sharedSecret;
mSharedSecretString=new String(mSharedSecret); mSharedSecretString=new String(mSharedSecret);
// mEncryptedAESSeed= RSACryptoForConnection.encrypt5(mSharedSecretString); mEncryptedAESSeed= SM2HelperForConnection.encryptWithSM2(mSharedSecretString);
mEncryptedAESSeed= SM2HelperForConnection.encrypt(mSharedSecretString); realSecret= SM3HelperForConnection.getSM3Hash16(mSharedSecret);
// 测试sm4
SM4HelperForConnection.encryptWithSM4(realSecret, "sss".getBytes());
// 代理地址(?) // 代理地址(?)
if(!TextUtils.isEmpty(proxyHostName)) { if(!TextUtils.isEmpty(proxyHostName)) {
@@ -218,7 +219,12 @@ public class MINVpnConnection implements Runnable{
byte[] ipPackageData = new byte[readLen]; byte[] ipPackageData = new byte[readLen];
System.arraycopy(buff1.array(), 0, ipPackageData, 0, readLen); System.arraycopy(buff1.array(), 0, ipPackageData, 0, readLen);
System.out.println("mSharedSecretString length: "+mSharedSecretString.length()); System.out.println("mSharedSecretString length: "+mSharedSecretString.length());
byte[] encrytedIPPackage = SM4HelperForConnection.encryptWithSM4(mSharedSecretString, ipPackageData); System.out.println("realSecret length: "+realSecret.length);
byte[] encrytedIPPackage = SM4HelperForConnection.encryptWithSM4(realSecret, ipPackageData);
if(encrytedIPPackage==null){
System.out.println("sm4加密错误!!!");
return;
}
System.out.println("encryptedIPPackage len: " + encrytedIPPackage.length); System.out.println("encryptedIPPackage len: " + encrytedIPPackage.length);
System.out.println("buff2 position: " + buff2.position()); System.out.println("buff2 position: " + buff2.position());
buff2.put(encrytedIPPackage); buff2.put(encrytedIPPackage);
@@ -243,7 +249,12 @@ public class MINVpnConnection implements Runnable{
// face.registerIdentifier(new Identifier(this.localPrefix),5000,helper); // face.registerIdentifier(new Identifier(this.localPrefix),5000,helper);
// 2. 接收服务器返回的数据包,放入buf2 // 2. 接收服务器返回的数据包,放入buf2
CPacket interest = face.receiveCPacket(-1); CPacket interest;
try {
interest = face.receiveCPacket(0);
}catch (Exception e){
continue;
}
System.out.println("recv interest packet, name : " + interest.getSrcIdentifier().toString()); System.out.println("recv interest packet, name : " + interest.getSrcIdentifier().toString());
System.out.println("兴趣包中装的数据长度 : " + interest.payload.getValue().length); System.out.println("兴趣包中装的数据长度 : " + interest.payload.getValue().length);
int dataLen = interest.payload.getValue().length; int dataLen = interest.payload.getValue().length;
@@ -256,7 +267,7 @@ public class MINVpnConnection implements Runnable{
System.arraycopy(buf2.array(), 0, decrpytedIPPackage, 0, buf2.position()); System.arraycopy(buf2.array(), 0, decrpytedIPPackage, 0, buf2.position());
ByteBuffer buf3 = ByteBuffer.allocate(5000); ByteBuffer buf3 = ByteBuffer.allocate(5000);
// buf3.put(Objects.requireNonNull(AESHelperForConnection.decryptWithAES(mSharedSecretString, decrpytedIPPackage))); // buf3.put(Objects.requireNonNull(AESHelperForConnection.decryptWithAES(mSharedSecretString, decrpytedIPPackage)));
buf3.put(Objects.requireNonNull(SM4HelperForConnection.decryptWithSM4(mSharedSecretString, decrpytedIPPackage))); buf3.put(Objects.requireNonNull(SM4HelperForConnection.decryptWithSM4(realSecret, decrpytedIPPackage)));
int decryptedDataLen = buf3.position(); int decryptedDataLen = buf3.position();
byte firstByte = buf3.get(0); byte firstByte = buf3.get(0);
if (firstByte == 0) { if (firstByte == 0) {
@@ -270,7 +281,7 @@ public class MINVpnConnection implements Runnable{
System.out.println("transfer data error: outputStream.write error"); System.out.println("transfer data error: outputStream.write error");
} }
} }
} catch (SecurityException | LogicFaceException e) { } catch (SecurityException e) {
e.printStackTrace(); e.printStackTrace();
System.out.println("transfer data error: recvFromServerAndReadThread.start error"); System.out.println("transfer data error: recvFromServerAndReadThread.start error");
} }
@@ -22,4 +22,6 @@ public class IPPackageUtil {
return null; return null;
} }
} }
@@ -24,7 +24,7 @@ public class SM2HelperForConnection {
// return enRes; // return enRes;
// } // }
public static byte[] encrypt(String data){ public static byte[] encryptWithSM2(String data){
byte[] enRes; byte[] enRes;
try { try {
enRes = BC_KeyManager.sm2encrypt(pubkey_ForNewVPN.getBytes(StandardCharsets.UTF_8), enRes = BC_KeyManager.sm2encrypt(pubkey_ForNewVPN.getBytes(StandardCharsets.UTF_8),
@@ -0,0 +1,29 @@
package com.pkusz.min_vpn_client.utils;
/*
* @Author: Wang Feng
* @Description:
* @Version: 1.0.0
* @Date: 10:07 2021/7/22
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
*/
import org.zz.gmhelper.SM3Util;
import java.util.Arrays;
public class SM3HelperForConnection {
/**
* 将传入参数使用sm3做哈希,然后返回前16个字节
* @param randBytes
* @return
*/
public static byte[] getSM3Hash16(byte[] randBytes){
System.out.println("sm3哈希之前的密钥:"+new String(randBytes));
byte[] hashRes=SM3Util.hash(randBytes);
byte[] res=new byte[16];
System.arraycopy(hashRes,0,res,0,16);
System.out.println("sm3哈希得到的密钥:"+res.length+" , "+new String(res));
System.out.println("sm3哈希得到的密钥:"+Arrays.toString(res));
return res;
}
}
@@ -9,10 +9,15 @@ package com.pkusz.min_vpn_client.utils;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import com.pkusz.min_vpn_client.utils.gmutil.sm4.VPN_SM4;
import org.zz.gmhelper.SM4Util;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException; import java.security.NoSuchProviderException;
import java.util.Arrays;
import java.util.Random; import java.util.Random;
import javax.crypto.BadPaddingException; import javax.crypto.BadPaddingException;
@@ -20,6 +25,7 @@ import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException; import javax.crypto.NoSuchPaddingException;
import VMSConnection.Security.BC_KeyManager; import VMSConnection.Security.BC_KeyManager;
import VMSConnection.Security.SM4.BC_SM4;
public class SM4HelperForConnection { public class SM4HelperForConnection {
public static byte[] encryptWithSM4(String secret,byte[] rawText){ public static byte[] encryptWithSM4(String secret,byte[] rawText){
@@ -40,6 +46,38 @@ public class SM4HelperForConnection {
} }
} }
public static byte[] encryptWithSM4(byte[] secretkey, byte[] origData) {
// try {
// return VPN_SM4.encrypt_ECB_Padding(secretkey, origData);
// } catch (Exception e){
// e.printStackTrace();
// return null;
// }
try {
return SM4Util.encrypt_ECB_Padding(secretkey,origData);
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
return null;
}
}
public static byte[] decryptWithSM4(byte[] secretkey, byte[] crypted){
// System.out.println("sec: " + secretkey);
// System.out.println("cry: " + Arrays.toString(crypted));
// try {
// return VPN_SM4.decrypt_ECB_Padding(secretkey, crypted);
// } catch (Exception e){
// e.printStackTrace();
// return null;
// }
try {
return SM4Util.decrypt_ECB_Padding(secretkey,crypted);
} catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException | NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException e) {
e.printStackTrace();
return null;
}
}
/** /**
* 获取长度为16字节的随机种子/随机密钥 * 获取长度为16字节的随机种子/随机密钥
* @return * @return
@@ -0,0 +1,140 @@
package com.pkusz.min_vpn_client.utils.gmutil.sm4;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.vpncrypto.*;
import javax.vpncrypto.spec.IvParameterSpec;
import javax.vpncrypto.spec.SecretKeySpec;
import java.security.*;
/*
* @Author: hongyu guo
* @Description: sm4算法
* 解尝试解决报错:Provider BC does not provide SM4/ECB/PKCS5Padding
*
* @Version: 1.0.0
* @Date: 16:26 2021/03/04
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
*/
public class VPN_SM4 {
static {
Security.addProvider(new BouncyCastleProvider());
}
public static final String ALGORITHM_NAME = "SM4";
public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
public static final String ALGORITHM_NAME_ECB_NOPADDING = "SM4/ECB/NoPadding";
public static final String ALGORITHM_NAME_CBC_PADDING = "SM4/CBC/PKCS5Padding";
public static final String ALGORITHM_NAME_CBC_NOPADDING = "SM4/CBC/NoPadding";
/**
* SM4算法目前只支持128位(即密钥16字节)
*/
public static final int DEFAULT_KEY_SIZE = 128;
/**
* 生成16字节的sm4 key
* @param
* @return byte[]
* @throws NoSuchAlgorithmException
* @author hongyu guo
* @date 2021/3/15
**/
public static byte[] generateKey() throws NoSuchAlgorithmException, NoSuchProviderException {
return generateKey(DEFAULT_KEY_SIZE);
}
public static byte[] generateKey(int keySize) throws NoSuchAlgorithmException, NoSuchProviderException {
KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
kg.init(keySize, new SecureRandom());
return kg.generateKey().getEncoded();
}
public static byte[] encrypt_ECB_Padding(byte[] key, byte[] data)
throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,
NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(data);
}
public static byte[] decrypt_ECB_Padding(byte[] key, byte[] cipherText)
throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {
Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);
return cipher.doFinal(cipherText);
}
public static byte[] encrypt_ECB_NoPadding(byte[] key, byte[] data)
throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,
NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_NOPADDING, Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(data);
}
public static byte[] decrypt_ECB_NoPadding(byte[] key, byte[] cipherText)
throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {
Cipher cipher = generateECBCipher(ALGORITHM_NAME_ECB_NOPADDING, Cipher.DECRYPT_MODE, key);
return cipher.doFinal(cipherText);
}
public static byte[] encrypt_CBC_Padding(byte[] key, byte[] iv, byte[] data)
throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,
NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException,
InvalidAlgorithmParameterException {
Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.ENCRYPT_MODE, key, iv);
return cipher.doFinal(data);
}
public static byte[] decrypt_CBC_Padding(byte[] key, byte[] iv, byte[] cipherText)
throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
InvalidAlgorithmParameterException {
Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.DECRYPT_MODE, key, iv);
return cipher.doFinal(cipherText);
}
public static byte[] encrypt_CBC_NoPadding(byte[] key, byte[] iv, byte[] data)
throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,
NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException,
InvalidAlgorithmParameterException {
Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_NOPADDING, Cipher.ENCRYPT_MODE, key, iv);
return cipher.doFinal(data);
}
public static byte[] decrypt_CBC_NoPadding(byte[] key, byte[] iv, byte[] cipherText)
throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
InvalidAlgorithmParameterException {
Cipher cipher = generateCBCCipher(ALGORITHM_NAME_CBC_NOPADDING, Cipher.DECRYPT_MODE, key, iv);
return cipher.doFinal(cipherText);
}
private static Cipher generateECBCipher(String algorithmName, int mode, byte[] key)
throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
InvalidKeyException {
Cipher cipher = null;
try {
cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
} catch (Exception e) {
e.printStackTrace();
}
Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
cipher.init(mode, sm4Key);
return cipher;
}
private static Cipher generateCBCCipher(String algorithmName, int mode, byte[] key, byte[] iv)
throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException,
NoSuchProviderException, NoSuchPaddingException {
Cipher cipher = null;
try {
cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
} catch (Exception e) {
e.printStackTrace();
}
Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(mode, sm4Key, ivParameterSpec);
return cipher;
}
}