Skip to content

Commit

Permalink
Merge pull request #43 from dawei101/dawei/rc4md5_n_chacha20
Browse files Browse the repository at this point in the history
Dawei/rc4md5 n chacha20
  • Loading branch information
dawei101 authored Sep 16, 2017
2 parents ed7d2da + 4b375a7 commit 6ef3193
Show file tree
Hide file tree
Showing 12 changed files with 219 additions and 37 deletions.
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ Last release: [Download](https://github.com/dawei101/shadowsocks-android-java/re

本版本为shadowsocks android版的纯java版本

因为实现原理的缘故,会牺牲掉很多功能(比如dns解析),虽然省电,但在速度有明显不足。建议作为玩具使用。

This version of shadowsocks for android is pure java version,take it as a toy please.
因为实现原理的缘故,会牺牲掉很多功能(比如dns解析).
This version of shadowsocks for android is pure java version.


代码多整理自 [smartproxy](https://github.com/hedaode/SmartProxy)[shadowsocks-java](https://github.com/blakey22/shadowsocks-java)
Expand All @@ -33,11 +32,11 @@ ss://base64encode(method:password@host:port)

And also it inherited the support of http(s) proxy from Smartproxy , Set the url as stardand http(s) proxy format when use it.

http(s)代理格式
http代理格式

http(s)proxy foramt:
http proxy foramt:
```
http(s)://(username:passsword)@host:port
http://(username:passsword)@host:port
```

支持的加密类型:
Expand All @@ -56,6 +55,9 @@ aes-256-ofb
camellia-128-cfb
camellia-192-cfb
camellia-256-cfb
chacha20
chacha20-ietf
rc4-md5
```

### 兄弟版本 Brother version
Expand Down
21 changes: 10 additions & 11 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
classpath 'com.android.tools.build:gradle:2.3.3'
}
}

android {
compileSdkVersion 25
buildToolsVersion "23.0.1"
compileSdkVersion 26
buildToolsVersion '26.0.1'
useLibrary 'org.apache.http.legacy'

defaultConfig {
applicationId "com.vm.shadowsocks"
minSdkVersion 15
targetSdkVersion 25
targetSdkVersion 26
versionCode 1
versionName "1.1"
versionName "1.2"
}
buildTypes {
release {
Expand All @@ -39,16 +39,15 @@ repositories {
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile fileTree(include: ['*.jar'], dir: 'libs')

testCompile 'junit:junit:4.12'

compile 'com.embarkmobile:zxing-android-minimal:2.0.0@aar'
compile 'com.embarkmobile:zxing-android-integration:2.0.0@aar'
compile 'com.google.zxing:core:3.0.1'
compile 'org.bouncycastle:bcprov-jdk15on:1.52'

compile 'org.bouncycastle:bcprov-jdk15on:1.57'
compile 'com.futuremind.recyclerfastscroll:fastscroll:0.2.5'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile('com.googlecode.json-simple:json-simple:1.1.1') {
exclude group: 'junit', module: 'junit'
exclude group: 'org.hamcrest', module: 'hamcrest-core'
}
}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />

<application
android:allowBackup="true"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ private void runVPN() throws Exception {
}
onIPPacketReceived(m_IPHeader, size);
}
Thread.sleep(100);
Thread.sleep(20);
}
in.close();
disconnectVPN();
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/vm/shadowsocks/core/ProxyConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@

public class ProxyConfig {
public static final ProxyConfig Instance = new ProxyConfig();
public final static boolean IS_DEBUG = true;
public final static boolean IS_DEBUG = false;
public static String AppInstallID;
public static String AppVersion;
public final static int FAKE_NETWORK_MASK = CommonMethods.ipStringToInt("255.255.0.0");
public final static int FAKE_NETWORK_IP = CommonMethods.ipStringToInt("10.231.0.0");
public final static int FAKE_NETWORK_IP = CommonMethods.ipStringToInt("172.25.0.0");

ArrayList<IPAddress> m_IpList;
ArrayList<IPAddress> m_DnsList;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.vm.shadowsocks.tunnel.shadowsocks;

import org.bouncycastle.crypto.StreamCipher;
import org.bouncycastle.crypto.engines.ChaChaEngine;
import org.bouncycastle.crypto.engines.ChaCha7539Engine;

import java.io.ByteArrayOutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class Chacha20Crypt extends CryptBase {
public final static String CIPHER_CHACHA20 = "chacha20";
public final static String CIPHER_CHACHA20_IETF = "chacha20-ietf";

public static Map<String, String> getCiphers() {
Map<String, String> ciphers = new HashMap<>();
ciphers.put(CIPHER_CHACHA20, Chacha20Crypt.class.getName());
ciphers.put(CIPHER_CHACHA20_IETF, Chacha20Crypt.class.getName());
return ciphers;
}

public Chacha20Crypt(String name, String password) {
super(name, password);
}

@Override
protected StreamCipher getCipher(boolean isEncrypted) throws InvalidAlgorithmParameterException {
if (_name.equals(CIPHER_CHACHA20)) {
return new ChaChaEngine();
}
else if (_name.equals(CIPHER_CHACHA20_IETF)) {
return new ChaCha7539Engine();
}
return null;
}

@Override
protected SecretKey getKey() {
return new SecretKeySpec(_ssKey.getEncoded(), "AES");

}

@Override
protected void _encrypt(byte[] data, ByteArrayOutputStream stream) {
int noBytesProcessed;
byte[] buffer = new byte[data.length];

noBytesProcessed = encCipher.processBytes(data, 0, data.length, buffer, 0);
stream.write(buffer, 0, noBytesProcessed);
}

@Override
protected void _decrypt(byte[] data, ByteArrayOutputStream stream) {
int BytesProcessedNum;
byte[] buffer = new byte[data.length];
BytesProcessedNum = decCipher.processBytes(data, 0, data.length, buffer, 0);
stream.write(buffer, 0, BytesProcessedNum);

}

@Override
public int getKeyLength() {
if (_name.equals(CIPHER_CHACHA20) || _name.equals(CIPHER_CHACHA20_IETF)) {
return 32;
}
return 0;
}

@Override
public int getIVLength() {
if (_name.equals(CIPHER_CHACHA20)) {
return 8;
}
else if (_name.equals(CIPHER_CHACHA20_IETF)) {
return 12;
}
return 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@

package com.vm.shadowsocks.tunnel.shadowsocks;

import org.bouncycastle.crypto.StreamBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.StreamCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
Expand All @@ -50,14 +52,20 @@
*/
public abstract class CryptBase implements ICrypt {

protected abstract StreamBlockCipher getCipher(boolean isEncrypted) throws InvalidAlgorithmParameterException;
protected abstract StreamCipher getCipher(boolean isEncrypted) throws InvalidAlgorithmParameterException;

protected abstract SecretKey getKey();

protected abstract void _encrypt(byte[] data, ByteArrayOutputStream stream);

protected abstract void _decrypt(byte[] data, ByteArrayOutputStream stream);

protected CipherParameters getCipherParameters(byte[] iv){
_decryptIV = new byte[_ivLength];
System.arraycopy(iv, 0, _decryptIV, 0, _ivLength);
return new ParametersWithIV(new KeyParameter(_key.getEncoded()), _decryptIV);
}

protected final String _name;
protected final SecretKey _key;
protected final ShadowSocksKey _ssKey;
Expand All @@ -69,8 +77,8 @@ public abstract class CryptBase implements ICrypt {
protected byte[] _decryptIV;
protected final Lock encLock = new ReentrantLock();
protected final Lock decLock = new ReentrantLock();
protected StreamBlockCipher encCipher;
protected StreamBlockCipher decCipher;
protected StreamCipher encCipher;
protected StreamCipher decCipher;
private Logger logger = Logger.getLogger(CryptBase.class.getName());

public CryptBase(String name, String password) {
Expand All @@ -86,26 +94,26 @@ protected void setIV(byte[] iv, boolean isEncrypt) {
return;
}

CipherParameters cipherParameters = null;

if (isEncrypt) {
_encryptIV = new byte[_ivLength];
System.arraycopy(iv, 0, _encryptIV, 0, _ivLength);
cipherParameters = getCipherParameters(iv);
try {
encCipher = getCipher(isEncrypt);
ParametersWithIV parameterIV = new ParametersWithIV(new KeyParameter(_key.getEncoded()), _encryptIV);
encCipher.init(isEncrypt, parameterIV);
} catch (InvalidAlgorithmParameterException e) {
logger.info(e.toString());
}
encCipher.init(isEncrypt, cipherParameters);
} else {
_decryptIV = new byte[_ivLength];
System.arraycopy(iv, 0, _decryptIV, 0, _ivLength);
cipherParameters = getCipherParameters(iv);
try {
decCipher = getCipher(isEncrypt);
ParametersWithIV parameterIV = new ParametersWithIV(new KeyParameter(_key.getEncoded()), _decryptIV);
decCipher.init(isEncrypt, parameterIV);
} catch (InvalidAlgorithmParameterException e) {
logger.info(e.toString());
}
decCipher.init(isEncrypt, cipherParameters);
}
}

Expand Down Expand Up @@ -174,4 +182,14 @@ public void decrypt(byte[] data, int length, ByteArrayOutputStream stream) {
System.arraycopy(data, 0, d, 0, length);
decrypt(d, stream);
}


public static byte[] md5Digest(byte[] input) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
return md5.digest(input);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public class CryptFactory {
putAll(CamelliaCrypt.getCiphers());
putAll(BlowFishCrypt.getCiphers());
putAll(SeedCrypt.getCiphers());
putAll(Chacha20Crypt.getCiphers());
putAll(Rc4Md5Crypt.getCiphers());
// TODO: other crypts
}};
private static Logger logger = Logger.getLogger(CryptFactory.class.getName());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.vm.shadowsocks.tunnel.shadowsocks;

import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.StreamCipher;
import org.bouncycastle.crypto.engines.RC4Engine;
import org.bouncycastle.crypto.params.KeyParameter;

import java.io.ByteArrayOutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;


public class Rc4Md5Crypt extends CryptBase {
public static String CIPHER_RC4_MD5 = "rc4-md5";

public static Map<String, String> getCiphers() {
Map<String, String> ciphers = new HashMap<String, String>();
ciphers.put(CIPHER_RC4_MD5, Rc4Md5Crypt.class.getName());
return ciphers;
}

public Rc4Md5Crypt(String name, String password) {
super(name, password);
}

@Override
protected StreamCipher getCipher(boolean isEncrypted) throws InvalidAlgorithmParameterException {
return new RC4Engine();
}

@Override
protected SecretKey getKey() {
return new SecretKeySpec(_ssKey.getEncoded(), "AES");
}

@Override
protected void _encrypt(byte[] data, ByteArrayOutputStream stream) {
int noBytesProcessed;
byte[] buffer = new byte[data.length];

noBytesProcessed = encCipher.processBytes(data, 0, data.length, buffer, 0);
stream.write(buffer, 0, noBytesProcessed);
}

@Override
protected void _decrypt(byte[] data, ByteArrayOutputStream stream) {
int noBytesProcessed;
byte[] buffer = new byte[data.length];

noBytesProcessed = decCipher.processBytes(data, 0, data.length, buffer, 0);
stream.write(buffer, 0, noBytesProcessed);
}

@Override
public int getIVLength() {
return 16;
}

@Override
public int getKeyLength() {
return 16;
}

@Override
protected CipherParameters getCipherParameters(byte[] iv) {
byte[] bts = new byte[_keyLength + _ivLength];
System.arraycopy(_key.getEncoded(), 0, bts, 0, _keyLength);
System.arraycopy(iv, 0, bts, _keyLength, _ivLength);
return new KeyParameter(md5Digest(bts));
}
}
10 changes: 6 additions & 4 deletions app/src/main/res/raw/config

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
classpath 'com.android.tools.build:gradle:2.3.3'

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
Expand Down
Loading

0 comments on commit 6ef3193

Please sign in to comment.