mirror of
https://github.com/shadowsocks/shadowsocks-rust.git
synced 2026-11-06 16:14:11 +00:00
updated docs
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
# shadowsocks-rust
|
||||
|
||||
[](https://travis-ci.org/zonyitoo/shadowsocks-rust)
|
||||
[](https://ci.appveyor.com/project/zonyitoo/shadowsocks-rust)
|
||||
[](https://github.com/zonyitoo/shadowsocks-rust)
|
||||
[](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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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<()>;
|
||||
|
||||
Reference in New Issue
Block a user