Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Importance of Shadowsocks-ChromeApp #1

Closed
patwwh opened this issue May 29, 2014 · 22 comments
Closed

Importance of Shadowsocks-ChromeApp #1

patwwh opened this issue May 29, 2014 · 22 comments

Comments

@patwwh
Copy link

patwwh commented May 29, 2014

Hi All Developers,
I notice that this Shadowsocks Client (as Chrome Extension) has been stopped developed for over 1 year. Sincerely encourage you to take a look on it again and see if it can be re-developed now or not. Being able to deploy Shadowsocks is a big convenience for users. It also fully utilize the advantage of Shadowsocks, which is the rare one fully support Javascript client (needed for Chrome extension).
Pat

@clowwindy
Copy link
Contributor

No, it hasn't been stopped. Everything that can be done has be done.

At the moment, I'm still waiting for Chrome to implement the Web Cryptography API.

@patwwh
Copy link
Author

patwwh commented May 29, 2014

Thanks. Look forward to seeing its birth :)

@kzahel
Copy link

kzahel commented Sep 15, 2014

Hi. web crypto API is shipped in current stable versions in chrome. Any chance you'll continue development?

@clowwindy
Copy link
Contributor

Wonderful work, I'll check if we share any same cipher.

@clowwindy
Copy link
Contributor

Yes we can use AES-CFB8. But it's 16x slower than AES-CFB128. Why did they choose this algorithm?

@zhuzhuor
Copy link

@clowwindy Highly recommend you to use AES-GCM if possible.
It is an authenticated encryption scheme. It's also included in TLS 1.2

@clowwindy
Copy link
Contributor

Using GCM requires us to encapsulate each packet. This is suitable for each end of the communication. For a middle proxy, doing this will split each packet of a full MTU 1500 into two packets: a packet of length 1500, and a packet of a small length, resulting in low throughput and being vulnerable to detect.

ref:
https://tools.ietf.org/html/rfc5116#ref-GCM
https://tools.ietf.org/html/rfc4303

@clowwindy
Copy link
Contributor

Actually WebCrypto API requires us to encrypt the whole data at one time. Thus those ciphers are not stream ciphers.

@kzahel
Copy link

kzahel commented Sep 16, 2014

Oh right I remember that. I was also disappointed when I found out there was no .update() and .digest() methods for even a SHA1 digest. web crypto API seems pretty weak

Is it really too slow to use crypto-js for the ciphers? I imagine it would be too much work to try to use some c library which supports streaming mode with pnacl.

@clowwindy
Copy link
Contributor

I wonder is there actually one JavaScript crypto library that has implemented stream cipher and CFB mode correctly. I looked at some of them a year ago, like crypto-js, forge, but none of them meet the requirement for Shadowsocks.

If you know any library that will allow us to encrypt and decrypt AES-256-CFB or RC4 progressively, please let me know.

@kzahel
Copy link

kzahel commented Sep 16, 2014

I haven't used crypto-js stream ciphers, but according to the documents, it supports RC4 at least
https://code.google.com/p/crypto-js/#RC4,_RC4Drop

@zhuzhuor
Copy link

You can use AES-CTR as a stream cipher. It is extremely easy to implement if you have code for AES.

PS. RC4 is (almost) broken, so please use other cipher suites if you can. See https://www.schneier.com/blog/archives/2013/03/new_rc4_attack.html

@clowwindy
Copy link
Contributor

Shadowsocks is not for serious encryption since it's not even CCA secure.
For the firewall we are facing, recording 2^24 first packets from each TCP connection between each two endpoints is not practical at the moment.
We RC4 is considered dead, switching protocol just takes minutes.

@zhuzhuor
Copy link

For AES-CTR, I may write a small js lib based on webcrypto api to make it output progressively, later today when I have time.
It should also be faster and more parallelizable than CFB and RC4.

@clowwindy
Copy link
Contributor

Added AES-CTR mode from OpenSSL EVP interface in server:
shadowsocks/shadowsocks@0e64945

@clowwindy
Copy link
Contributor

@kzahel Tested crypto-js with RC4. Still broken. The implementation does not behave like a real stream cipher.

Test code:

<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/rc4.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script>
    var key = CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f');                           

    var aesEncryptor = CryptoJS.algo.RC4.createEncryptor(key);

    var ciphertextPart1 = aesEncryptor.process("Message Part 1");
    var ciphertextPart2 = aesEncryptor.process("Message Part 2");
    var ciphertextPart3 = aesEncryptor.process("Message Part 3");
    var ciphertextPart4 = aesEncryptor.finalize();

    var aesDecryptor = CryptoJS.algo.RC4.createDecryptor(key);

    var plaintextPart1 = aesDecryptor.process(ciphertextPart1);
    var plaintextPart2 = aesDecryptor.process(ciphertextPart2);
    var plaintextPart3 = aesDecryptor.process(ciphertextPart3);
    var plaintextPart4 = aesDecryptor.process(ciphertextPart4);
    var plaintextPart5 = aesDecryptor.finalize();

    console.log('1:' + plaintextPart1.toString(CryptoJS.enc.Utf8));
    console.log('2:' + plaintextPart2.toString(CryptoJS.enc.Utf8));
    console.log('3:' + plaintextPart3.toString(CryptoJS.enc.Utf8));
    console.log('4:' + plaintextPart4.toString(CryptoJS.enc.Utf8));
    console.log('5:' + plaintextPart5.toString(CryptoJS.enc.Utf8));
</script>

Expected:

1:Message Part 1
2:Message Part 2
3:Message Part 3
4:
5:

Actual:

1:Message Part
2: 1Message Part 2
3:Message Part
4:
5: 3

@clowwindy
Copy link
Contributor

Will use an RC4 library written by myself just now.

https://github.com/clowwindy/jsrc4/blob/master/jsrc4.js

On Chrome 37: 185.98884066955983MB/s

@kzahel
Copy link

kzahel commented Sep 17, 2014

Wow, @clowwindy that is really, really great. I am eagerly following your progress. I very much would like to have a lightweight RC4 for bittorrent protocol encryption.

@clowwindy
Copy link
Contributor

@kzahel
Do you have any experience with chrome.sockets.tcp API? I found its performance really poor.

I created a TCP server that does nothing but piping data from one socket to another. It takes 150% CPU with 2.5MB/s throughput. One Google Chrome Helper takes 100% and one Google Chrome takes about 50%. At the same time, curl process that is dumping that data into /dev/null takes 3% CPU.

RC4 encryption is quite fast compared to that.

The code I use can be simplified as:

  readHandler = function(data, error) {
    if (error) {
      // close sockets
      // ...
      return;
    }
    tcp.send(anotherSocketId, data, function(sendInfo) {
      if (sendInfo.resultCode < 0) {
        // close sockets
        // ...
        return;
      }
    });
  };

@zhuzhuor
Copy link

@clowwindy It seems Chrome hasn't fully implemented APIs for AES-CTR yet, although it's in the w3 specification. I tried to build my own (progressive) AES-CTR by using AES-CBC as an underlying block. It is working but very slow.
I guess we may have to wait for some time if we want to use built-in AES-CTR in Chrome as a stream cipher.

@clowwindy
Copy link
Contributor

@zhuzhuor I implemented RC4 in JavaScript and it's around 180MB/s on Chrome. But after I then found that the new socket API provided by Chrome is terrible. It's not only slow, but requires us to keep creating new ArrayBuffers for each send() and recv() operation, rather than reusing them.

@kzahel
Copy link

kzahel commented Sep 19, 2014

@clowwindy you're using "chrome.sockets", not "chrome.socket" API, right? I found that the newer one performs better. You don't call .recv() anymore, you set pause/unpaused and have an event listener for when there is data to be read from the socket. I found it increased the throughput.

I do notice my app which uses chrome.sockets heavily is a very CPU bound app. But I haven't done any good benchmarking to see exactly where it's CPU bound. I am very interested in seeing example code gist of your sockets piping example that uses a lot of CPU. Maybe making a "crbug" would bring it to google's attention and somebody would work on it

I didn't ever try simply reading from one socket and writing the same arraybuffer to another socket, it's strange that that would give an error (it throws some kind of exception, or what?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants