diff --git a/README.md b/README.md index 63d8fac7..432e45d1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # shadowsocks-rust [![Build Status](https://img.shields.io/travis/zonyitoo/shadowsocks-rust.svg)](https://travis-ci.org/zonyitoo/shadowsocks-rust) +[![Build status](https://ci.appveyor.com/api/projects/status/l703ewkke5tkqctl?svg=true)](https://ci.appveyor.com/project/zonyitoo/shadowsocks-rust) [![License](https://img.shields.io/github/license/zonyitoo/shadowsocks-rust.svg)](https://github.com/zonyitoo/shadowsocks-rust) [![crates.io](https://img.shields.io/crates/v/shadowsocks-rust.svg)](https://crates.io/crates/shadowsocks-rust) @@ -8,8 +9,6 @@ This is a port of [shadowsocks](https://github.com/shadowsocks/shadowsocks). shadowsocks is a fast tunnel proxy that helps you bypass firewalls. -It is **unstable**! If you encounter any problems, please open an issue. - ## Dependencies * libcrypto (OpenSSL) @@ -34,12 +33,6 @@ cargo build Then `sslocal` and `ssserver` will appear in `./target`, it works similarly as the two binaries in the official ShadowSocks' implementation. -Enable more crypto algorithms by passing the name `cipher-[name]` via command line argument `--features` - -```bash -cargo build --features "cipher-aes-ctr" -``` - Read `Cargo.toml` for more details. ## Getting Started diff --git a/src/crypto/aead.rs b/src/crypto/aead.rs index 675783c0..af0a09ba 100644 --- a/src/crypto/aead.rs +++ b/src/crypto/aead.rs @@ -29,11 +29,15 @@ use rust_crypto::hkdf::{hkdf_expand, hkdf_extract}; use rust_crypto::sha1::Sha1; use rust_crypto::digest::Digest; +/// Encryptor API for AEAD ciphers pub trait AeadEncryptor { + /// Encrypt `input` to `output` with `tag`. `output.len()` should equals to `input.len()`. fn encrypt(&mut self, input: &[u8], output: &mut [u8], tag: &mut [u8]); } +/// Decryptor API for AEAD ciphers pub trait AeadDecryptor { + /// Decrypt `input` to `output` with `tag`. `output.len()` should equals to `input.len()`. fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> CipherResult<()>; } @@ -65,6 +69,33 @@ pub fn new_aead_decryptor(t: CipherType, key: &[u8], nounce: &[u8]) -> Box Vec { assert!(t.category() == CipherCategory::Aead); diff --git a/src/crypto/cipher.rs b/src/crypto/cipher.rs index 94301ebc..55d27151 100644 --- a/src/crypto/cipher.rs +++ b/src/crypto/cipher.rs @@ -135,9 +135,12 @@ pub enum CipherType { Aes256Gcm, } +/// Category of ciphers #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum CipherCategory { + /// Stream ciphers is used for OLD ShadowSocks protocol, which uses stream ciphers to encrypt data payloads Stream, + /// AEAD ciphers is used in modern ShadowSocks protocol, which sends data in separate packets Aead, } diff --git a/src/crypto/crypto.rs b/src/crypto/crypto.rs index bc341d2e..6d4e9711 100644 --- a/src/crypto/crypto.rs +++ b/src/crypto/crypto.rs @@ -73,10 +73,14 @@ impl StreamCipher for CryptoCipher { } } +/// AEAD ciphers provided by Rust-Crypto pub enum CryptoAeadCryptoVariant { AesGcm(AesGcm<'static>), } +/// AEAD Cipher context +/// +/// According to SIP004, the `nounce` has to incr 1 after each encrypt/decrypt. pub struct CryptoAeadCrypto { cipher: CryptoAeadCryptoVariant, cipher_type: CipherType, @@ -85,6 +89,7 @@ pub struct CryptoAeadCrypto { } impl CryptoAeadCrypto { + /// Initialize context pub fn new(t: CipherType, key: &[u8], salt: &[u8]) -> CryptoAeadCrypto { // TODO: Check if salt is duplicated diff --git a/src/relay/tcprelay/crypto_io.rs b/src/relay/tcprelay/crypto_io.rs index 4001bdb5..b717aaa6 100644 --- a/src/relay/tcprelay/crypto_io.rs +++ b/src/relay/tcprelay/crypto_io.rs @@ -12,6 +12,10 @@ use tokio_core::io::{copy, Copy}; use super::BUFFER_SIZE; use super::utils::{copy_timeout, copy_timeout_opt, CopyTimeout, CopyTimeoutOpt}; +/// Reader to read data from ShadowSocks protocol +/// +/// This trait requires `BufRead`, because obviously this reader has to contain a buffer inside, +/// which stores the decrypted data. pub trait DecryptedRead: BufRead { /// Copies all data to `w` fn copy(self, w: W) -> Copy @@ -38,8 +42,12 @@ pub trait DecryptedRead: BufRead { } } +/// Writer that encrypt data and write it as ShadowSocks protocol +/// +/// The writer cannot implement `io::Write`, because you cannot ensure that you can write all the data in a batch +/// in non-blocking I/O environment. pub trait EncryptedWrite { - /// Writes raw bytes directly to the writer directly + /// Writes raw bytes directly to the writer fn write_raw(&mut self, data: &[u8]) -> io::Result; /// Flush the writer fn flush(&mut self) -> io::Result<()>;