updated docs

This commit is contained in:
Y. T. Chung
2017-02-18 01:48:27 +08:00
parent 50f37de0e6
commit 99daba0680
5 changed files with 49 additions and 9 deletions
+1 -8
View File
@@ -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 <del>bypass firewalls</del>.
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
+31
View File
@@ -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<AeadD
const SUBKEY_INFO: &'static [u8] = b"ss-subkey";
/// Make Session key
///
/// ## Session key (SIP007)
///
/// AEAD ciphers require a per-session subkey derived from the pre-shared master key using HKDF, and use the subkey
/// to encrypt/decrypt. Essentially it means we are moving from (M+N)-bit (PSK, nonce) pair to
/// (M+N)-bit (HKDF(PSK, salt), nonce) pair. Because HKDF is a PRF, the new construction significantly expands the
/// amount of randomness (from N to at least M where M is much greater than N), thus correcting the previously
/// mentioned design flaw.
///
/// Assuming we already have a user-supplied pre-shared master key PSK.
///
/// Function HKDF_SHA1 is a HKDF constructed using SHA1 hash. Its signature is
///
/// ```plain
/// HKDF_SHA1(secret_key, salt, info)
/// ```
///
/// The "info" string argument allows us to bind the derived subkey to a specific application context.
///
/// For AEAD ciphers, the encryption scheme is:
///
/// 1. Pick a random R-bit salt (R = max(128, len(SK)))
/// 2. Derive subkey SK = HKDF_SHA1(PSK, salt, "ss-subkey")
/// 3. Send salt
/// 4. For each chunk, encrypt and authenticate payload using SK with a counting nonce (starting from 0 and increment by 1 after each use)
/// 5. Send encrypted chunk
pub fn make_skey(t: CipherType, key: &[u8], salt: &[u8]) -> Vec<u8> {
assert!(t.category() == CipherCategory::Aead);
+3
View File
@@ -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,
}
+5
View File
@@ -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
+9 -1
View File
@@ -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<W>(self, w: W) -> Copy<Self, W>
@@ -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<usize>;
/// Flush the writer
fn flush(&mut self) -> io::Result<()>;