Browse Source

Update specs

pull/1519/head
Max Lv 7 years ago
parent
commit
4b1550626f
2 changed files with 64 additions and 56 deletions
  1. 85
      src/aead.c
  2. 35
      src/stream.c

85
src/aead.c

@ -56,75 +56,48 @@
#define CHUNK_SIZE_MASK 0x3FFF #define CHUNK_SIZE_MASK 0x3FFF
/* /*
* This is SIP004 proposed by @Mygod, the design of TCP chunk is from @breakwa11 and
* @Noisyfox. This first version of this file is written by @wongsyrone.
* Spec: http://shadowsocks.org/en/spec/AEAD-Ciphers.html
* *
* The first nonce is either from client or server side, it is generated randomly, and
* the sequent nonces are increased by 1.
* The way Shadowsocks using AEAD ciphers is specified in SIP004 and amended in SIP007. SIP004 was proposed by @Mygod
* with design inspirations from @wongsyrone, @Noisyfox and @breakwa11. SIP007 was proposed by @riobard with input from
* @madeye, @Mygod, @wongsyrone, and many others.
* *
* Data.Len is used to separate general ciphertext and Auth tag. We can start decryption
* if and only if the verification is passed.
* Firstly, we do length check, then decrypt it, separate ciphertext and attached data tag
* based on the verified length, verify data tag and decrypt the corresponding data.
* Finally, do what you supposed to do, e.g. forward user data.
* Key Derivation
* *
* For UDP, nonces are generated randomly without the incrementation.
* HKDF_SHA1 is a function that takes a secret key, a non-secret salt, an info string, and produces a subkey that is
* cryptographically strong even if the input secret key is weak.
* *
* TCP request (before encryption)
* +------+---------------------+------------------+
* | ATYP | Destination Address | Destination Port |
* +------+---------------------+------------------+
* | 1 | Variable | 2 |
* +------+---------------------+------------------+
* HKDF_SHA1(key, salt, info) => subkey
* *
* TCP request (after encryption, *ciphertext*)
* +--------+--------------+------------------+--------------+---------------+
* | NONCE | *HeaderLen* | HeaderLen_TAG | *Header* | Header_TAG |
* +--------+--------------+------------------+--------------+---------------+
* | Fixed | 2 | Fixed | Variable | Fixed |
* +--------+--------------+------------------+--------------+---------------+
* The info string binds the generated subkey to a specific application context. In our case, it must be the string
* "ss-subkey" without quotes.
* *
* Header input: atyp + dst.addr + dst.port
* HeaderLen is length(atyp + dst.addr + dst.port)
* HeaderLen_TAG and Header_TAG are in plaintext
* We derive a per-session subkey from a pre-shared master key using HKDF_SHA1. Salt must be unique through the entire
* life of the pre-shared master key.
* *
* TCP Chunk (before encryption)
* +----------+
* | DATA |
* +----------+
* | Variable |
* +----------+
* TCP
* *
* Data.Len is a 16-bit big-endian integer indicating the length of DATA.
* An AEAD encrypted TCP stream starts with a randomly generated salt to derive the per-session subkey, followed by any
* number of encrypted chunks. Each chunk has the following structure:
* *
* TCP Chunk (after encryption, *ciphertext*)
* +--------------+---------------+--------------+------------+
* | *DataLen* | DataLen_TAG | *Data* | Data_TAG |
* +--------------+---------------+--------------+------------+
* | 2 | Fixed | Variable | Fixed |
* +--------------+---------------+--------------+------------+
* [encrypted payload length][length tag][encrypted payload][payload tag]
* *
* Len_TAG and DATA_TAG have the same length, they are in plaintext.
* After encryption, DATA -> DATA*
* Payload length is a 2-byte big-endian unsigned integer capped at 0x3FFF. The higher two bits are reserved and must be
* set to zero. Payload is therefore limited to 16*1024 - 1 bytes.
* *
* UDP (before encryption)
* +------+---------------------+------------------+----------+
* | ATYP | Destination Address | Destination Port | DATA |
* +------+---------------------+------------------+----------+
* | 1 | Variable | 2 | Variable |
* +------+---------------------+------------------+----------+
* The first AEAD encrypt/decrypt operation uses a counting nonce starting from 0. After each encrypt/decrypt operation,
* the nonce is incremented by one as if it were an unsigned little-endian integer. Note that each TCP chunk involves
* two AEAD encrypt/decrypt operation: one for the payload length, and one for the payload. Therefore each chunk
* increases the nonce twice.
* *
* UDP (after encryption, *ciphertext*)
* +--------+-----------+-----------+
* | NONCE | *Data* | Data_TAG |
* +--------+-----------+-----------+
* | Fixed | Variable | Fixed |
* +--------+-----------+-----------+
* UDP
* *
* *Data* is Encrypt(atyp + dst.addr + dst.port + payload)
* RSV and FRAG are dropped
* Since UDP packet is either received completely or missed,
* we don't have to keep a field to track its length.
* An AEAD encrypted UDP packet has the following structure:
*
* [salt][encrypted payload][tag]
*
* The salt is used to derive the per-session subkey and must be generated randomly to ensure uniqueness. Each UDP
* packet is encrypted/decrypted independently, using the derived subkey and a nonce with all zero bytes.
* *
*/ */

35
src/stream.c

@ -37,6 +37,41 @@
#define SODIUM_BLOCK_SIZE 64 #define SODIUM_BLOCK_SIZE 64
/*
* Spec: http://shadowsocks.org/en/spec/Stream-Ciphers.html
*
* Stream ciphers provide only confidentiality. Data integrity and authenticity is not guaranteed. Users should use AEAD
* ciphers whenever possible.
*
* Stream Encryption/Decryption
*
* Stream_encrypt is a function that takes a secret key, an initialization vector, a message, and produces a ciphertext
* with the same length as the message.
*
* Stream_encrypt(key, IV, message) => ciphertext
*
* Stream_decrypt is a function that takes a secret key, an initializaiton vector, a ciphertext, and produces the
* original message.
*
* Stream_decrypt(key, IV, ciphertext) => message
*
* TCP
*
* A stream cipher encrypted TCP stream starts with a randomly generated initializaiton vector, followed by encrypted
* payload data.
*
* [IV][encrypted payload]
*
* UDP
*
* A stream cipher encrypted UDP packet has the following structure:
*
* [IV][encrypted payload]
*
* Each UDP packet is encrypted/decrypted independently with a randomly generated initialization vector.
*
*/
#define NONE -1 #define NONE -1
#define TABLE 0 #define TABLE 0
#define RC4 1 #define RC4 1

Loading…
Cancel
Save