rc4 works now, fix #3
This commit is contained in:
Binary file not shown.
+34
-49
@@ -111,11 +111,11 @@ static void mergesort(uint8_t array[], int length)
|
||||
merge(left, llength, right, middle);
|
||||
}
|
||||
|
||||
void encrypt(char *buf, int len) {
|
||||
if (_method == RC4_ENC) {
|
||||
void encrypt(char *buf, int len, EVP_CIPHER_CTX *ctx) {
|
||||
if (ctx != NULL) {
|
||||
int outlen;
|
||||
unsigned char mybuf[BUF_SIZE];
|
||||
EVP_CipherUpdate(&ctx, mybuf, &outlen, (unsigned char*)buf, len);
|
||||
EVP_CipherUpdate(ctx, mybuf, &outlen, (unsigned char*)buf, len);
|
||||
memcpy(buf, mybuf, len);
|
||||
} else {
|
||||
char *end = buf + len;
|
||||
@@ -126,11 +126,11 @@ void encrypt(char *buf, int len) {
|
||||
}
|
||||
}
|
||||
|
||||
void decrypt(char *buf, int len) {
|
||||
if (_method == RC4_ENC) {
|
||||
void decrypt(char *buf, int len, EVP_CIPHER_CTX *ctx) {
|
||||
if (ctx != NULL) {
|
||||
int outlen;
|
||||
unsigned char mybuf[BUF_SIZE];
|
||||
EVP_CipherUpdate(&ctx, mybuf, &outlen, (unsigned char*) buf, len);
|
||||
EVP_CipherUpdate(ctx, mybuf, &outlen, (unsigned char*) buf, len);
|
||||
memcpy(buf, mybuf, len);
|
||||
} else {
|
||||
char *end = buf + len;
|
||||
@@ -141,51 +141,36 @@ void decrypt(char *buf, int len) {
|
||||
}
|
||||
}
|
||||
|
||||
int send_encrypt(int sock, char *buf, int len, int flags) {
|
||||
char mybuf[BUF_SIZE];
|
||||
memcpy(mybuf, buf, len);
|
||||
encrypt(mybuf, len);
|
||||
return send(sock, mybuf, len, flags);
|
||||
void enc_ctx_init(EVP_CIPHER_CTX *ctx, const char *pass, int enc) {
|
||||
unsigned char key[EVP_MAX_KEY_LENGTH];
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH];
|
||||
int key_len = EVP_BytesToKey(EVP_rc4(), EVP_md5(), NULL, (unsigned char*) pass,
|
||||
strlen(pass), 1, key, iv);
|
||||
EVP_CIPHER_CTX_init(ctx);
|
||||
EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, NULL, NULL, enc);
|
||||
if (!EVP_CIPHER_CTX_set_key_length(ctx, key_len)) {
|
||||
LOGE("Invalid key length: %d", key_len);
|
||||
EVP_CIPHER_CTX_cleanup(ctx);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc);
|
||||
}
|
||||
|
||||
int recv_decrypt(int sock, char *buf, int len, int flags) {
|
||||
char mybuf[BUF_SIZE];
|
||||
int result = recv(sock, mybuf, len, flags);
|
||||
memcpy(buf, mybuf, len);
|
||||
decrypt(buf, len);
|
||||
return result;
|
||||
}
|
||||
void get_table(const char *pass) {
|
||||
uint8_t *table = encrypt_table;
|
||||
uint8_t *tmp_hash = MD5((unsigned char *) pass, strlen(pass), NULL);
|
||||
_a = htole64(*(uint64_t *) tmp_hash);
|
||||
uint32_t i;
|
||||
|
||||
void get_table(const char* pass) {
|
||||
if (_method == RC4_ENC) {
|
||||
unsigned char key[EVP_MAX_KEY_LENGTH];
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH];
|
||||
int key_len = EVP_BytesToKey(EVP_rc4(), EVP_md5(), NULL, (unsigned char*) pass,
|
||||
strlen(pass), 1, key, iv);
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1);
|
||||
if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) {
|
||||
LOGE("Invalid key length: %d", key_len);
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, 1);
|
||||
} else {
|
||||
uint8_t *table = encrypt_table;
|
||||
uint8_t *tmp_hash = MD5((unsigned char *) pass, strlen(pass), NULL);
|
||||
_a = htole64(*(uint64_t *) tmp_hash);
|
||||
uint32_t i;
|
||||
|
||||
for(i = 0; i < 256; ++i) {
|
||||
table[i] = i;
|
||||
}
|
||||
for(i = 1; i < 1024; ++i) {
|
||||
_i = i;
|
||||
mergesort(table, 256);
|
||||
}
|
||||
for(i = 0; i < 256; ++i) {
|
||||
// gen decrypt table from encrypt table
|
||||
decrypt_table[encrypt_table[i]] = i;
|
||||
}
|
||||
for(i = 0; i < 256; ++i) {
|
||||
table[i] = i;
|
||||
}
|
||||
for(i = 1; i < 1024; ++i) {
|
||||
_i = i;
|
||||
mergesort(table, 256);
|
||||
}
|
||||
for(i = 0; i < 256; ++i) {
|
||||
// gen decrypt table from encrypt table
|
||||
decrypt_table[encrypt_table[i]] = i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,18 +10,16 @@
|
||||
|
||||
#define BUF_SIZE 4096
|
||||
|
||||
#define TABLE_ENC 0
|
||||
#define RC4_ENC 1
|
||||
#define TABLE 0
|
||||
#define RC4 1
|
||||
|
||||
unsigned char encrypt_table[256];
|
||||
unsigned char decrypt_table[256];
|
||||
EVP_CIPHER_CTX ctx;
|
||||
|
||||
void get_table(const char* key);
|
||||
void encrypt(char *buf, int len);
|
||||
void decrypt(char *buf, int len);
|
||||
int send_encrypt(int sock, char *buf, int len, int flags);
|
||||
int recv_decrypt(int sock, char *buf, int len, int flags);
|
||||
void encrypt(char *buf, int len, EVP_CIPHER_CTX *ctx);
|
||||
void decrypt(char *buf, int len, EVP_CIPHER_CTX *ctx);
|
||||
void enc_ctx_init(EVP_CIPHER_CTX *ctx, const char *pass, int enc);
|
||||
|
||||
unsigned int _i;
|
||||
unsigned long long _a;
|
||||
|
||||
+31
-13
@@ -28,6 +28,7 @@
|
||||
static char *_server;
|
||||
static char *_remote_port;
|
||||
static int _timeout;
|
||||
static char *_key;
|
||||
|
||||
int setnonblocking(int fd) {
|
||||
int flags;
|
||||
@@ -123,7 +124,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
|
||||
|
||||
// local socks5 server
|
||||
if (server->stage == 5) {
|
||||
encrypt(remote->buf, r);
|
||||
encrypt(remote->buf, r, server->e_ctx);
|
||||
int w = send(remote->fd, remote->buf, r, 0);
|
||||
if(w == -1) {
|
||||
if (errno == EAGAIN) {
|
||||
@@ -186,7 +187,6 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
|
||||
size_t in_addr_len = sizeof(struct in_addr);
|
||||
memcpy(addr_to_send + addr_len, server->buf + 4, in_addr_len + 2);
|
||||
addr_len += in_addr_len + 2;
|
||||
addr_to_send[addr_len] = 0;
|
||||
|
||||
} else if (request->atyp == 3) {
|
||||
// Domain name
|
||||
@@ -198,7 +198,6 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
|
||||
// get port
|
||||
addr_to_send[addr_len++] = *(unsigned char *)(server->buf + 4 + 1 + name_len);
|
||||
addr_to_send[addr_len++] = *(unsigned char *)(server->buf + 4 + 1 + name_len + 1);
|
||||
addr_to_send[addr_len] = 0;
|
||||
} else {
|
||||
LOGE("unsupported addrtype: %d\n", request->atyp);
|
||||
close_and_free_remote(EV_A_ remote);
|
||||
@@ -206,7 +205,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
|
||||
return;
|
||||
}
|
||||
|
||||
send_encrypt(remote->fd, addr_to_send, addr_len, 0);
|
||||
encrypt(addr_to_send, addr_len, server->e_ctx);
|
||||
send(remote->fd, addr_to_send, addr_len, 0);
|
||||
|
||||
// Fake reply
|
||||
struct socks5_response response;
|
||||
@@ -233,7 +233,6 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
|
||||
}
|
||||
|
||||
server->stage = 5;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -333,7 +332,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
decrypt(server->buf, r);
|
||||
decrypt(server->buf, r, server->d_ctx);
|
||||
int w = send(server->fd, server->buf, r, MSG_NOSIGNAL);
|
||||
if(w == -1) {
|
||||
if (errno == EAGAIN) {
|
||||
@@ -482,6 +481,15 @@ struct server* new_server(int fd) {
|
||||
server->send_ctx->server = server;
|
||||
server->send_ctx->connected = 0;
|
||||
server->stage = 0;
|
||||
if (_method == RC4) {
|
||||
server->e_ctx = malloc(sizeof(EVP_CIPHER_CTX));
|
||||
server->d_ctx = malloc(sizeof(EVP_CIPHER_CTX));
|
||||
enc_ctx_init(server->e_ctx, _key, 1);
|
||||
enc_ctx_init(server->d_ctx, _key, 0);
|
||||
} else {
|
||||
server->e_ctx = NULL;
|
||||
server->d_ctx = NULL;
|
||||
}
|
||||
return server;
|
||||
}
|
||||
void free_server(struct server *server) {
|
||||
@@ -489,6 +497,12 @@ void free_server(struct server *server) {
|
||||
if (server->remote != NULL) {
|
||||
server->remote->server = NULL;
|
||||
}
|
||||
if (_method == RC4) {
|
||||
EVP_CIPHER_CTX_cleanup(server->e_ctx);
|
||||
EVP_CIPHER_CTX_cleanup(server->d_ctx);
|
||||
free(server->e_ctx);
|
||||
free(server->d_ctx);
|
||||
}
|
||||
free(server->recv_ctx);
|
||||
free(server->send_ctx);
|
||||
free(server);
|
||||
@@ -603,12 +617,6 @@ int main (int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (method != NULL) {
|
||||
if (strcmp(method, "rc4") == 0) {
|
||||
_method = RC4_ENC;
|
||||
}
|
||||
}
|
||||
|
||||
if (f_flags) {
|
||||
|
||||
/* Our process ID and Session ID */
|
||||
@@ -658,12 +666,22 @@ int main (int argc, char **argv)
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
// init global variables
|
||||
_server = strdup(server);
|
||||
_remote_port = strdup(remote_port);
|
||||
_timeout = atoi(timeout);
|
||||
_key = key;
|
||||
_method = TABLE;
|
||||
if (method != NULL) {
|
||||
if (strcmp(method, "rc4") == 0) {
|
||||
_method = RC4;
|
||||
}
|
||||
}
|
||||
|
||||
LOGD("calculating ciphers %d", _method);
|
||||
get_table(key);
|
||||
if (_method != RC4) {
|
||||
get_table(key);
|
||||
}
|
||||
|
||||
int listenfd;
|
||||
listenfd = create_and_bind(port);
|
||||
|
||||
@@ -21,6 +21,8 @@ struct server {
|
||||
char buf[BUF_SIZE]; // server send from, remote recv into
|
||||
char stage;
|
||||
int buf_len;
|
||||
EVP_CIPHER_CTX *e_ctx;
|
||||
EVP_CIPHER_CTX *d_ctx;
|
||||
struct server_ctx *recv_ctx;
|
||||
struct server_ctx *send_ctx;
|
||||
struct remote *remote;
|
||||
|
||||
Binary file not shown.
@@ -405,31 +405,35 @@ public class Shadowsocks extends PreferenceActivity implements
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (key.equals("remotePort"))
|
||||
if (settings.getString("remotePort", "").equals(""))
|
||||
if (key.equals("remotePort")) {
|
||||
if (settings.getString("remotePort", "").equals("")) {
|
||||
remotePortText.setSummary(getString(R.string.remote_port_summary));
|
||||
else
|
||||
} else {
|
||||
remotePortText.setSummary(settings.getString("remotePort", ""));
|
||||
else if (key.equals("port"))
|
||||
if (settings.getString("port", "").equals(""))
|
||||
}
|
||||
} else if (key.equals("port")) {
|
||||
if (settings.getString("port", "").equals("")) {
|
||||
portText.setSummary(getString(R.string.port_summary));
|
||||
else
|
||||
} else {
|
||||
portText.setSummary(settings.getString("port", ""));
|
||||
else if (key.equals("sitekey"))
|
||||
if (settings.getString("sitekey", "").equals(""))
|
||||
}
|
||||
} else if (key.equals("sitekey")) {
|
||||
if (settings.getString("sitekey", "").equals("")) {
|
||||
sitekeyText.setSummary(getString(R.string.sitekey_summary));
|
||||
else
|
||||
} else {
|
||||
sitekeyText.setSummary(settings.getString("sitekey", ""));
|
||||
else if (key.equals("encMethod"))
|
||||
if (!settings.getString("encMethod", "").equals(""))
|
||||
}
|
||||
} else if (key.equals("encMethod")) {
|
||||
if (!settings.getString("encMethod", "").equals("")) {
|
||||
encMethodText.setSummary(settings.getString("encMethod", ""));
|
||||
else if (key.equals("proxy"))
|
||||
}
|
||||
} else if (key.equals("proxy")) {
|
||||
if (settings.getString("proxy", "").equals("")) {
|
||||
proxyText.setSummary(getString(R.string.proxy_summary));
|
||||
} else {
|
||||
proxyText.setSummary(settings.getString("proxy", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user