VPN握手调试:可以正常接收返回的数据包,但解析尚存问题

This commit is contained in:
free will
2021-07-21 14:45:13 +08:00
parent 009d6448b8
commit 9b7c2a071e
5 changed files with 371 additions and 11 deletions
Binary file not shown.
@@ -44,8 +44,8 @@ public enum MINVpnSettingAPI {
private final String SP_PROXY_MODE = "SP_PROXY_MODE";
// 用户名 & 密码 & 客户端服务前缀
private String username="";
private String password="";
private String username="wefree";
private String password="123";
private String localPrefix="/vpn/client";
// MIR/VPN-Server的IP地址及服务前缀
private String mirIpAddress="1.1.1.1";
@@ -138,8 +138,10 @@ public enum MINVpnSettingAPI {
// ----------VPN Service--------------
public String getLocalPrefix(){
// return EncryptedSharedPreferenceUtil.get(context,
// SP_LOCAL_LOCAL_PREFIX,"/vpn/client");
return EncryptedSharedPreferenceUtil.get(context,
SP_LOCAL_LOCAL_PREFIX,"/vpn/client");
SP_LOCAL_LOCAL_PREFIX,"/min/gdcni19"+"/"+this.username);
}
public void updateLocalPrefix(String localPrefix){
@@ -23,12 +23,14 @@ import com.pkusz.min_vpn_client.utils.IPPackageUtil;
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.SM2HelperForConnection;
import com.pkusz.min_vpn_client.utils.SafetyInfoUtil;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Objects;
import java.util.Set;
@@ -43,6 +45,7 @@ import packet.CPacket;
import packet.Data;
import packet.Interest;
import packet.PacketException;
import util.ByteHelper;
import static java.nio.charset.StandardCharsets.US_ASCII;
@@ -51,6 +54,7 @@ public class MINVpnConnection implements Runnable{
private String handshakeResponse = null; // 握手应答
private ParcelFileDescriptor mParcelFileDescriptor = null; // 读出写入流
private boolean stop = false; // 标记本次连接是否停止
String fuck; // src地址
// 最大包长度
private static final int MAX_PACKET_SIZE = Short.MAX_VALUE;
@@ -122,7 +126,8 @@ public class MINVpnConnection implements Runnable{
mServerPort=serverPort;
mSharedSecret=sharedSecret;
mSharedSecretString=new String(mSharedSecret);
mEncryptedAESSeed= RSACryptoForConnection.encrypt5(mSharedSecretString);
// mEncryptedAESSeed= RSACryptoForConnection.encrypt5(mSharedSecretString);
mEncryptedAESSeed= SM2HelperForConnection.encrypt(mSharedSecretString);
// 代理地址(?)
if(!TextUtils.isEmpty(proxyHostName)) {
@@ -292,7 +297,8 @@ public class MINVpnConnection implements Runnable{
// 构造本地标识:/{local_prefix}
Identifier clientIdentifier;
try {
clientIdentifier = new Identifier(MINVpnSettingAPI.INSTANCE.getLocalPrefix());
// clientIdentifier = new Identifier(MINVpnSettingAPI.INSTANCE.getLocalPrefix());
clientIdentifier = new Identifier(fuck);
} catch (ComponentException e) {
e.printStackTrace();
LoggerHelper.warning("sendInterestPkt error 1: clientIdentifier init error: "+e.getMessage());
@@ -344,7 +350,9 @@ public class MINVpnConnection implements Runnable{
// 1. 构造兴趣包
// 构造兴趣包负载字段:加密密钥 & 本地前缀
ByteBuffer requestBuf = ByteBuffer.allocate(1024);
requestBuf.put((byte) 1).put(mEncryptedAESSeed).put(this.localPrefix.getBytes()).flip();
byte len= ByteHelper.uint8ToByte(mEncryptedAESSeed.length);
requestBuf.put((byte) 1).put(len).put(mEncryptedAESSeed).put(fuck.getBytes()).flip();
// requestBuf.put((byte) 1).put(len).put(mEncryptedAESSeed).put(this.localPrefix.getBytes()).flip();
// 构造目的标识:/{service prefix}/{cPacket seq}/{defraudString}
Identifier serverIdentifier;
try {
@@ -359,7 +367,8 @@ public class MINVpnConnection implements Runnable{
// 构造本地标识:/{local_prefix}
Identifier clientIdentifier;
try {
clientIdentifier = new Identifier(MINVpnSettingAPI.INSTANCE.getLocalPrefix());
// clientIdentifier = new Identifier(MINVpnSettingAPI.INSTANCE.getLocalPrefix());
clientIdentifier = new Identifier(fuck);
} catch (ComponentException e) {
e.printStackTrace();
LoggerHelper.warning("handshake error 1: clientIdentifier init error: "+e.getMessage());
@@ -367,10 +376,33 @@ public class MINVpnConnection implements Runnable{
}
// 构造CPacket:名称 生存时间 是否要求最新 TTL 请求内容
CPacket cPacket = new CPacket();
System.out.println("src是什么:"+clientIdentifier.toString());
try {
System.out.println("src是什么:"+clientIdentifier.toUri());
} catch (ComponentException e) {
e.printStackTrace();
}
try {
System.out.println("src是什么:"+clientIdentifier.toUriTemp());
} catch (ComponentException e) {
e.printStackTrace();
}
System.out.println("dst是什么:"+serverIdentifier.toString());
try {
System.out.println("dst是什么:"+serverIdentifier.toUri());
} catch (ComponentException e) {
e.printStackTrace();
}
cPacket.setSrcIdentifier(clientIdentifier);
cPacket.setDstIdentifier(serverIdentifier);
cPacket.ttl.setTtl(64);
cPacket.payload.setValue(requestBuf.array());
// requestBuf.limit(1+1+mEncryptedAESSeed.length+fuck.length());
int writeLen=1+1+mEncryptedAESSeed.length+fuck.length();
byte[] writeString=new byte[writeLen];
System.arraycopy(requestBuf.array(),0,writeString,0,writeLen);
System.out.println("array: "+ Arrays.toString(requestBuf.array()));
System.out.println("write: "+ Arrays.toString(writeString));
cPacket.payload.setValue(writeString);
// 输出未签名兴趣包
try {
@@ -400,11 +432,12 @@ public class MINVpnConnection implements Runnable{
// 3. 发送兴趣包到服务器,接收服务器发回来的数据包
try {
face.sendCPacket(cPacket);
CPacket data=face.receiveCPacket(5000);
CPacket data=face.receiveCPacket(10000);
ByteBuffer respondBuf = ByteBuffer.allocate(1024);
respondBuf.put(data.payload.getValue());
System.out.println("handshake recv data , data content : " + new String(data.payload.getValue()));
this.handshakeResponse = new String(respondBuf.array(), 1, data.payload.getValue().length - 1, US_ASCII).trim();
// 应答信息:m,8000 a,10.254.0.2 d,114.114.114.114 r,172.16.0.0,12 r,10.0.0.0,16 r,192.168.0.0,16
this.handshakeResponse = new String(respondBuf.array(), 0, data.payload.getValue().length, US_ASCII).trim();
} catch (LogicFaceException e) {
e.printStackTrace();
LoggerHelper.warning("handshake error 3: send sign cPacket error: "+e.getMessage());
@@ -545,7 +578,10 @@ public class MINVpnConnection implements Runnable{
// 2. 注册标识
RegisterPrefixHelper helper=new RegisterPrefixHelper();
try {
face.registerIdentifier(new Identifier(this.localPrefix),5000,helper);
// String timestamp="/"+System.currentTimeMillis();
fuck="/min/gdcni19/wefree/"+System.currentTimeMillis();
System.out.println("注册前缀:"+fuck);
face.registerIdentifier(new Identifier(fuck),5000,helper);
} catch (LogicFaceException | ComponentException e) {
e.printStackTrace();
LoggerHelper.warning("tcp logic face register identifier error: "+e.getMessage());
@@ -0,0 +1,38 @@
package com.pkusz.min_vpn_client.utils;
/*
* @Author: Wang Feng
* @Description:
* @Version: 1.0.0
* @Date: 17:31 2021/7/20
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
*/
import org.bouncycastle.crypto.InvalidCipherTextException;
import java.nio.charset.StandardCharsets;
import VMSConnection.Security.BC_KeyManager;
public class SM2HelperForConnection {
private static String pubkey_ForNewVPN="04acb8153bfeb71074903e9c80b4390" +
"8585b025a723fc434ed2f5b434d6046aa0fbab67f1c5d207263d65a" +
"63161fe788297bea01ea5b7e1ad43490215788100326";
// public static byte[] encrypt(String data){
// byte[] enRes=gmUtil.sm2encrypte(pubkey_ForNewVPN.getBytes(StandardCharsets.UTF_8),
// data.getBytes(StandardCharsets.UTF_8));
// return enRes;
// }
public static byte[] encrypt(String data){
byte[] enRes;
try {
enRes = BC_KeyManager.sm2encrypt(pubkey_ForNewVPN.getBytes(StandardCharsets.UTF_8),
data.getBytes(StandardCharsets.UTF_8));
} catch (InvalidCipherTextException e) {
e.printStackTrace();
return null;
}
return enRes;
}
}
@@ -0,0 +1,284 @@
package com.pkusz.min_vpn_client.utils;
import android.util.Log;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.zz.gmhelper.BCECUtil;
import org.zz.gmhelper.SM2Util;
import org.zz.gmhelper.SM4Util;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import static org.zz.gmhelper.BCECUtil.convertPKCS8ToECPrivateKey;
import static org.zz.gmhelper.BCECUtil.convertX509ToECPublicKey;
import static org.zz.gmhelper.SM2Util.decrypt;
import static org.zz.gmhelper.SM2Util.encrypt;
public class gmUtil {
static {
/* //Security.removeProvider("BC");
Security.addProvider(new BouncyCastleProvider());
}*/
}
public static void init() {
Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null){
Log.i("sys","运行环境没有BouncyCastleProvider");
Security.addProvider(new BouncyCastleProvider());
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) != null) {
double version = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME).getVersion();
Log.i("sys", "原有version=" + version);
}
}
}
//solution from stack overflow
public static void init_so() {
final String SUN_PROVIDERS = "sun.security.jca.Providers";
// remove BC provider first
Security.removeProvider("BC");
// also remove not sufficient AndroidOpenSSL provider for X.509 - most likely only needed if BouncyCastleJsseProvider is used
Security.removeProvider("AndroidOpenSSL");
// touch the internal Providers class to trigger the static provider loading
// see http://androidxref.com/9.0.0_r3/xref/libcore/ojluni/src/main/java/sun/security/jca/Providers.java#SYSTEM_BOUNCY_CASTLE_PROVIDER
try {
Class.forName(SUN_PROVIDERS);
} catch (ClassNotFoundException e) {
throw new RuntimeException(String.format("%s to patch not found.", SUN_PROVIDERS), e);
}
// insert modern BC as first crypto provider
Security.insertProviderAt(new BouncyCastleProvider(), 0);
}
public static void test() {
try {
KeyPair keyPair = SM2Util.generateKeyPair();
//BCECUtil.convertECPublicKeyToX509(keyPair.getPublic())
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
}
public static byte[] sm2encrypte(byte[] publicKey, byte[] srcData) {
try {
BCECPublicKey bcecPublicKey = convertX509ToECPublicKey(publicKey);
return encrypt(SM2Engine.Mode.C1C2C3, bcecPublicKey, srcData);
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (InvalidCipherTextException e) {
e.printStackTrace();
}
return null;
}
public static byte[] sm2encrypte(String publicKey, byte[] srcData) {
try {
byte[] keyX509 = BCECUtil.convertECPublicKeyPEMToX509(publicKey);
return sm2encrypte(keyX509, srcData);
} catch (IOException e) {
e.printStackTrace();
}
return null;
//return sm2encrypte(publicKey.getBytes(), srcData);
}
public static byte[] sm2decrypte(byte[] privateKey, byte[] srcData) {
try {
BCECPrivateKey bcecPrivateKey = convertPKCS8ToECPrivateKey(privateKey);
return decrypt(SM2Engine.Mode.C1C2C3, bcecPrivateKey, srcData);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (InvalidCipherTextException e) {
e.printStackTrace();
}
return null;
}
public static byte[] sm2decrypte(String publicKey, byte[] srcData) {
try {
byte[] keyPKCS8 = BCECUtil.convertECPrivateKeyPEMToPKCS8(publicKey);
return sm2decrypte(keyPKCS8, srcData);
} catch (IOException e) {
e.printStackTrace();
}
return null;
//return sm2decrypte(publicKey.getBytes(), srcData);
}
public static byte[] sm4encrypte(byte[] key, byte[] srcData) {
try {
return SM4Util.encrypt_ECB_Padding(key, srcData);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
public static byte[] sm4decrypte(byte[] key, byte[] srcData) {
try {
return SM4Util.decrypt_ECB_Padding(key, srcData);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
return null;
}
public static void testEncryptAndDecrypt() {
try {
AsymmetricCipherKeyPair keyPair = SM2Util.generateKeyPairParameter();
ECPrivateKeyParameters priKey = (ECPrivateKeyParameters) keyPair.getPrivate();
ECPublicKeyParameters pubKey = (ECPublicKeyParameters) keyPair.getPublic();
System.out.println("Pri Hex:"
+ ByteUtils.toHexString(priKey.getD().toByteArray()).toUpperCase());
System.out.println("Pub X Hex:"
+ ByteUtils.toHexString(pubKey.getQ().getAffineXCoord().getEncoded()).toUpperCase());
System.out.println("Pub X Hex:"
+ ByteUtils.toHexString(pubKey.getQ().getAffineYCoord().getEncoded()).toUpperCase());
System.out.println("Pub Point Hex:"
+ ByteUtils.toHexString(pubKey.getQ().getEncoded(false)).toUpperCase());
byte[] encryptedData = SM2Util.encrypt(pubKey, "SRC_DATA_24B".getBytes());
System.out.println("SM2 encrypt result:\n" + ByteUtils.toHexString(encryptedData));
byte[] decryptedData = SM2Util.decrypt(priKey, encryptedData);
System.out.println("SM2 decrypt result:\n" + ByteUtils.toHexString(decryptedData));
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void testOpensslCompat() {
Security.removeProvider("BC");
Security.addProvider(new BouncyCastleProvider());
try {
// openssl
// String pri_pem = "-----BEGIN PRIVATE KEY-----\n" +
// "MIIBYQIBADCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/////v//////\n" +
// "//////////////8AAAAA//////////8wRAQg/////v////////////////////8A\n" +
// "AAAA//////////wEICjp+p6dn140TVqeS89lCafzl4n1FauPkt28vUFNlA6TBEEE\n" +
// "MsSuLB8ZgRlfmQRGajnJlI/jC7/yZgvhcVpFiTNMdMe8Nzai9PZ3nFm9zuNraSFT\n" +
// "0KmHfMYqR0AC3zLlITnwoAIhAP////7///////////////9yA99rIcYFK1O79Ak5\n" +
// "1UEjAgEBBG0wawIBAQQgosPOsBUeDbMTsLKTpbopBuIJdGwv3oF1i208lpqzJNyh\n" +
// "RANCAATJ6QXXPgsLewr1uHGQga5n0s3EDp5KO4sDy+KyQARHdZrxXQqfDZa/eBwu\n" +
// "O8DhQ6owIGgAkV4Ng7Ne8LGrpqmf\n" +
// "-----END PRIVATE KEY-----\n";
// String pub_pem = "-----BEGIN PUBLIC KEY-----\n" +
// "MIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/////v//////////\n" +
// "//////////8AAAAA//////////8wRAQg/////v////////////////////8AAAAA\n" +
// "//////////wEICjp+p6dn140TVqeS89lCafzl4n1FauPkt28vUFNlA6TBEEEMsSu\n" +
// "LB8ZgRlfmQRGajnJlI/jC7/yZgvhcVpFiTNMdMe8Nzai9PZ3nFm9zuNraSFT0KmH\n" +
// "fMYqR0AC3zLlITnwoAIhAP////7///////////////9yA99rIcYFK1O79Ak51UEj\n" +
// "AgEBA0IABMnpBdc+Cwt7CvW4cZCBrmfSzcQOnko7iwPL4rJABEd1mvFdCp8Nlr94\n" +
// "HC47wOFDqjAgaACRXg2Ds17wsaumqZ8=\n" +
// "-----END PUBLIC KEY-----\n";
String pri_pem = "-----BEGIN PRIVATE KEY-----\n" +
"MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgrx6HiMUfpBbWLb/T\n" +
"QQq6BBNbvfFtmp6yFGLQjMtcQ/mgCgYIKoEcz1UBgi2hRANCAATzvqit8PlDCJq1\n" +
"wVwZKnNi8K+JbQ14euO2rd3BltBudvlAoP+keKOrwqpARCUQIrILeN9UDz5FCxbV\n" +
"NHdcb9++\n" +
"-----END PRIVATE KEY-----";
String pub_pem = "-----BEGIN PUBLIC KEY-----\n" +
"MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE876orfD5QwiatcFcGSpzYvCviW0N\n" +
"eHrjtq3dwZbQbnb5QKD/pHijq8KqQEQlECKyC3jfVA8+RQsW1TR3XG/fvg==\n" +
"-----END PUBLIC KEY-----";
byte[] pri_pkcs8 = BCECUtil.convertECPrivateKeyPEMToPKCS8(pri_pem);
BCECPrivateKey bcecPrivateKey = BCECUtil.convertPKCS8ToECPrivateKey(pri_pkcs8);
byte[] pub_x509 = BCECUtil.convertECPublicKeyPEMToX509(pub_pem);
BCECPublicKey bcecPublicKey = BCECUtil.convertX509ToECPublicKey(pub_x509);
System.out.println("D: " + ByteUtils.toHexString(bcecPrivateKey.getD().toByteArray()));
System.out.println("Q: " + bcecPublicKey.getQ());
byte[] encryptedData = SM2Util.encrypt(bcecPublicKey, "123".getBytes());
System.out.println("SM2 encrypt result:\n" + ByteUtils.toHexString(encryptedData));
byte[] decryptedData = SM2Util.decrypt(bcecPrivateKey, encryptedData);
System.out.println("SM2 decrypt result:\n" + new String(decryptedData));
System.out.println("==========================================================");
// 鐢ㄧ殑杩欎釜
byte[] encryptedData2 = SM2Util.encrypt(SM2Engine.Mode.C1C2C3, bcecPublicKey, "123".getBytes());
System.out.println("SM2 encrypt result:\n" + ByteUtils.toHexString(encryptedData2));
byte[] decryptedData2 = SM2Util.decrypt(SM2Engine.Mode.C1C2C3, bcecPrivateKey, encryptedData2);
System.out.println("SM2 decrypt result:\n" + ByteUtils.toHexString(decryptedData2));
byte[] sign = SM2Util.sign(bcecPrivateKey, "SRC_DATA".getBytes());
boolean flag = SM2Util.verify(bcecPublicKey, "SRC_DATA".getBytes(), sign);
System.out.println("SM2 sign without withId result:\n" + ByteUtils.toHexString(sign));
System.out.println("flag = " + flag);
// byte[] encData = Base64.decode("MHYCIQDKHiLS8J0C2VE6b3+aPzSaxLH6ku86zyFCLil38L8BZgIgQJP9FJZ9JeXB\n" +
// "rZWQX/gubzW3jyFmhWIw0p/HyZWt91kEIA92HlKH1gcPOreeVSq5bewoS/rUDZlV\n" +
// "788vrGMK103aBA3r5laOAr1V0BpBVYhe");
//
// System.out.println(Arrays.toString(encData));
// byte[] decData = SM2Util.decrypt(Mode.C1C2C3, bcecPrivateKey, encData);
// System.out.println(Arrays.toString(decData));
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}