mirror of
https://github.com/shadowsocks/shadowsocks-rust.git
synced 2026-11-06 16:14:11 +00:00
Add experimental SIV support (#81)
* add optional miscreant support * add miscreant test * fix miscreant version * update README + add `aes-128-pmac-siv`, `aes-256-pmac-siv` + remove `aes-192-gcm`
This commit is contained in:
Generated
+68
-33
@@ -1,36 +1,7 @@
|
||||
[root]
|
||||
name = "shadowsocks-rust"
|
||||
version = "1.6.8"
|
||||
dependencies = [
|
||||
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byte_string 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-cpupool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libsodium-ffi 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"md-5 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"qrcode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"subprocess 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-signal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"typenum 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
[[package]]
|
||||
name = "aesni"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
@@ -137,6 +108,14 @@ dependencies = [
|
||||
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clear_on_drop"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "coco"
|
||||
version = "0.1.1"
|
||||
@@ -351,6 +330,18 @@ dependencies = [
|
||||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miscreant"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aesni 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clear_on_drop 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"subtle 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "net2"
|
||||
version = "0.2.31"
|
||||
@@ -533,6 +524,41 @@ dependencies = [
|
||||
"url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shadowsocks-rust"
|
||||
version = "1.6.8"
|
||||
dependencies = [
|
||||
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byte_string 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-cpupool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libsodium-ffi 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"md-5 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miscreant 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"qrcode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"subprocess 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-signal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"typenum 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.3.0"
|
||||
@@ -559,6 +585,11 @@ dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "1.5.1"
|
||||
@@ -722,6 +753,7 @@ dependencies = [
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum aesni 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ef0ab1be561c7753c0c416e1b73466c5a07a134c222f4115a4c76ea6526eb56a"
|
||||
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
|
||||
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
|
||||
"checksum arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd1479b7c29641adbd35ff3b5c293922d696a92f25c8c975da3e0acbc87258f"
|
||||
@@ -737,6 +769,7 @@ dependencies = [
|
||||
"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b8c532887f1a292d17de05ae858a8fe50a301e196f9ef0ddb7ccd0d1d00f180"
|
||||
"checksum clear_on_drop 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27fc408dd80e7fe9d5b1c8cee6c2add84bea237d8dee70880a76ae7957f6d3a6"
|
||||
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
|
||||
"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
|
||||
"checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a"
|
||||
@@ -765,6 +798,7 @@ dependencies = [
|
||||
"checksum mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0e8411968194c7b139e9105bc4ae7db0bae232af087147e72f0616ebf5fdb9cb"
|
||||
"checksum mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1731a873077147b626d89cc6c2a0db6288d607496c5d10c0cfcf3adc697ec673"
|
||||
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||
"checksum miscreant 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7dc55762103c586148e451ce13e0fbc0ec9f92b90ae70042a2ffc0d77ddb1c"
|
||||
"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
|
||||
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
|
||||
"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
|
||||
@@ -792,6 +826,7 @@ dependencies = [
|
||||
"checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d"
|
||||
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
|
||||
"checksum subprocess 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "78a77399f1ffa6f2ee3595ab8e329381bbeaf640d59073821519e6a0aa957f9d"
|
||||
"checksum subtle 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32dbfc4beea0a08bfe33114d0f5e5092f35f6fa387a955b4a2c68888cdd7b0f2"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
|
||||
"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
|
||||
|
||||
@@ -58,6 +58,7 @@ url = "1.5"
|
||||
byte_string = "1.0"
|
||||
libsodium-ffi = { version = "0.1", optional = true }
|
||||
futures-cpupool = "0.1"
|
||||
miscreant = { version = "0.2", optional = true }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
tokio-signal = "0.1"
|
||||
|
||||
@@ -56,7 +56,7 @@ make install
|
||||
```
|
||||
|
||||
Then `sslocal`, `ssserver` and `ssurl` will be installed in `/usr/local/bin` (variable PREFIX).
|
||||
|
||||
|
||||
### **Build standalone binaries**
|
||||
|
||||
Requirements:
|
||||
@@ -170,12 +170,13 @@ $ ssserver -s "[::]:8388" -m "aes-256-gcm" -k "hello-kitty" --plugin "obfs-local
|
||||
* `dummy` (No encryption, just for debugging)
|
||||
|
||||
### AEAD Ciphers
|
||||
* `aes-128-gcm`, `aes-192-gcm`, `aes-256-gcm`
|
||||
* `aes-128-gcm`, `aes-256-gcm`
|
||||
* `chacha20-ietf-poly1305`
|
||||
* `aes-128-pmac-siv`, `aes-256-pmac-siv` (experimental)
|
||||
|
||||
## Useful Tools
|
||||
|
||||
1. `ssurl` is for encoding and decoding ShadowSocks URLs (SIP002). Example:
|
||||
1. `ssurl` is for encoding and decoding ShadowSocks URLs (SIP002). Example:
|
||||
|
||||
```plain
|
||||
ss://YWVzLTI1Ni1jZmI6cGFzc3dvcmQ@127.0.0.1:8388/?plugin=obfs-local%3Bobfs%3Dhttp%3Bobfs-host%3Dwww.baidu.com
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
use crypto::cipher::{CipherCategory, CipherResult, CipherType};
|
||||
|
||||
use crypto::ring::RingAeadCipher;
|
||||
#[cfg(feature = "miscreant")]
|
||||
use crypto::siv::MiscreantCipher;
|
||||
|
||||
use ring::digest::SHA1;
|
||||
use ring::hkdf;
|
||||
@@ -37,6 +39,10 @@ pub fn new_aead_encryptor(t: CipherType, key: &[u8], nonce: &[u8]) -> BoxAeadEnc
|
||||
CipherType::Aes256Gcm |
|
||||
CipherType::ChaCha20Poly1305 => Box::new(RingAeadCipher::new(t, key, nonce, true)),
|
||||
|
||||
#[cfg(feature = "miscreant")]
|
||||
CipherType::Aes128PmacSiv |
|
||||
CipherType::Aes256PmacSiv => Box::new(MiscreantCipher::new(t, key, nonce)),
|
||||
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
@@ -50,6 +56,10 @@ pub fn new_aead_decryptor(t: CipherType, key: &[u8], nonce: &[u8]) -> BoxAeadDec
|
||||
CipherType::Aes256Gcm |
|
||||
CipherType::ChaCha20Poly1305 => Box::new(RingAeadCipher::new(t, key, nonce, false)),
|
||||
|
||||
#[cfg(feature = "miscreant")]
|
||||
CipherType::Aes128PmacSiv |
|
||||
CipherType::Aes256PmacSiv => Box::new(MiscreantCipher::new(t, key, nonce)),
|
||||
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
+58
-19
@@ -67,35 +67,40 @@ impl From<::openssl::error::ErrorStack> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
const CIPHER_AES_128_CFB: &'static str = "aes-128-cfb";
|
||||
const CIPHER_AES_128_CFB_1: &'static str = "aes-128-cfb1";
|
||||
const CIPHER_AES_128_CFB_8: &'static str = "aes-128-cfb8";
|
||||
const CIPHER_AES_128_CFB_128: &'static str = "aes-128-cfb128";
|
||||
const CIPHER_AES_128_CFB: &str = "aes-128-cfb";
|
||||
const CIPHER_AES_128_CFB_1: &str = "aes-128-cfb1";
|
||||
const CIPHER_AES_128_CFB_8: &str = "aes-128-cfb8";
|
||||
const CIPHER_AES_128_CFB_128: &str = "aes-128-cfb128";
|
||||
|
||||
const CIPHER_AES_256_CFB: &'static str = "aes-256-cfb";
|
||||
const CIPHER_AES_256_CFB_1: &'static str = "aes-256-cfb1";
|
||||
const CIPHER_AES_256_CFB_8: &'static str = "aes-256-cfb8";
|
||||
const CIPHER_AES_256_CFB_128: &'static str = "aes-256-cfb128";
|
||||
const CIPHER_AES_256_CFB: &str = "aes-256-cfb";
|
||||
const CIPHER_AES_256_CFB_1: &str = "aes-256-cfb1";
|
||||
const CIPHER_AES_256_CFB_8: &str = "aes-256-cfb8";
|
||||
const CIPHER_AES_256_CFB_128: &str = "aes-256-cfb128";
|
||||
|
||||
const CIPHER_RC4: &'static str = "rc4";
|
||||
const CIPHER_RC4_MD5: &'static str = "rc4-md5";
|
||||
const CIPHER_RC4: &str = "rc4";
|
||||
const CIPHER_RC4_MD5: &str = "rc4-md5";
|
||||
|
||||
const CIPHER_TABLE: &'static str = "table";
|
||||
const CIPHER_TABLE: &str = "table";
|
||||
|
||||
#[cfg(feature = "sodium")]
|
||||
const CIPHER_CHACHA20: &'static str = "chacha20";
|
||||
const CIPHER_CHACHA20: &str = "chacha20";
|
||||
#[cfg(feature = "sodium")]
|
||||
const CIPHER_SALSA20: &'static str = "salsa20";
|
||||
const CIPHER_SALSA20: &str = "salsa20";
|
||||
#[cfg(feature = "sodium")]
|
||||
const CIPHER_XSALSA20: &'static str = "xsalsa20";
|
||||
const CIPHER_XSALSA20: &str = "xsalsa20";
|
||||
#[cfg(feature = "sodium")]
|
||||
const CIPHER_CHACHA20_IETF: &'static str = "chacha20-ietf";
|
||||
const CIPHER_CHACHA20_IETF: &str = "chacha20-ietf";
|
||||
|
||||
const CIPHER_DUMMY: &'static str = "dummy";
|
||||
#[cfg(feature = "miscreant")]
|
||||
const CIPHER_AES_128_PMAC_SIV: &str = "aes-128-pmac-siv";
|
||||
#[cfg(feature = "miscreant")]
|
||||
const CIPHER_AES_256_PMAC_SIV: &str = "aes-256-pmac-siv";
|
||||
|
||||
const CIPHER_AES_128_GCM: &'static str = "aes-128-gcm";
|
||||
const CIPHER_AES_256_GCM: &'static str = "aes-256-gcm";
|
||||
const CIPHER_CHACHA20_POLY1305: &'static str = "chacha20-ietf-poly1305";
|
||||
const CIPHER_DUMMY: &str = "dummy";
|
||||
|
||||
const CIPHER_AES_128_GCM: &str = "aes-128-gcm";
|
||||
const CIPHER_AES_256_GCM: &str = "aes-256-gcm";
|
||||
const CIPHER_CHACHA20_POLY1305: &str = "chacha20-ietf-poly1305";
|
||||
|
||||
/// ShadowSocks cipher type
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
@@ -129,6 +134,11 @@ pub enum CipherType {
|
||||
Aes256Gcm,
|
||||
|
||||
ChaCha20Poly1305,
|
||||
|
||||
#[cfg(feature = "miscreant")]
|
||||
Aes128PmacSiv,
|
||||
#[cfg(feature = "miscreant")]
|
||||
Aes256PmacSiv,
|
||||
}
|
||||
|
||||
/// Category of ciphers
|
||||
@@ -168,6 +178,11 @@ impl CipherType {
|
||||
CipherType::Aes256Gcm => AES_256_GCM.key_len(),
|
||||
|
||||
CipherType::ChaCha20Poly1305 => CHACHA20_POLY1305.key_len(),
|
||||
|
||||
#[cfg(feature = "miscreant")]
|
||||
CipherType::Aes128PmacSiv => 32,
|
||||
#[cfg(feature = "miscreant")]
|
||||
CipherType::Aes256PmacSiv => 64,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,6 +278,11 @@ impl CipherType {
|
||||
CipherType::Aes128Gcm => AES_128_GCM.nonce_len(),
|
||||
CipherType::Aes256Gcm => AES_256_GCM.nonce_len(),
|
||||
CipherType::ChaCha20Poly1305 => CHACHA20_POLY1305.nonce_len(),
|
||||
|
||||
#[cfg(feature = "miscreant")]
|
||||
CipherType::Aes128PmacSiv => 8,
|
||||
#[cfg(feature = "miscreant")]
|
||||
CipherType::Aes256PmacSiv => 8,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,6 +314,11 @@ impl CipherType {
|
||||
CipherType::Aes128Gcm |
|
||||
CipherType::Aes256Gcm |
|
||||
CipherType::ChaCha20Poly1305 => CipherCategory::Aead,
|
||||
|
||||
#[cfg(feature = "miscreant")]
|
||||
CipherType::Aes128PmacSiv |
|
||||
CipherType::Aes256PmacSiv => CipherCategory::Aead,
|
||||
|
||||
_ => CipherCategory::Stream,
|
||||
}
|
||||
}
|
||||
@@ -307,6 +332,10 @@ impl CipherType {
|
||||
CipherType::Aes256Gcm => AES_256_GCM.tag_len(),
|
||||
CipherType::ChaCha20Poly1305 => CHACHA20_POLY1305.tag_len(),
|
||||
|
||||
#[cfg(feature = "miscreant")]
|
||||
CipherType::Aes128PmacSiv |
|
||||
CipherType::Aes256PmacSiv => 16,
|
||||
|
||||
_ => panic!("Only support AEAD ciphers, found {:?}", self),
|
||||
}
|
||||
}
|
||||
@@ -356,6 +385,11 @@ impl FromStr for CipherType {
|
||||
|
||||
CIPHER_CHACHA20_POLY1305 => Ok(CipherType::ChaCha20Poly1305),
|
||||
|
||||
#[cfg(feature = "miscreant")]
|
||||
CIPHER_AES_128_PMAC_SIV => Ok(CipherType::Aes128PmacSiv),
|
||||
#[cfg(feature = "miscreant")]
|
||||
CIPHER_AES_256_PMAC_SIV => Ok(CipherType::Aes256PmacSiv),
|
||||
|
||||
_ => Err(Error::UnknownCipherType),
|
||||
}
|
||||
}
|
||||
@@ -391,6 +425,11 @@ impl Display for CipherType {
|
||||
CipherType::Aes128Gcm => write!(f, "{}", CIPHER_AES_128_GCM),
|
||||
CipherType::Aes256Gcm => write!(f, "{}", CIPHER_AES_256_GCM),
|
||||
CipherType::ChaCha20Poly1305 => write!(f, "{}", CIPHER_CHACHA20_POLY1305),
|
||||
|
||||
#[cfg(feature = "miscreant")]
|
||||
CipherType::Aes128PmacSiv => write!(f, "{}", CIPHER_AES_128_PMAC_SIV),
|
||||
#[cfg(feature = "miscreant")]
|
||||
CipherType::Aes256PmacSiv => write!(f, "{}", CIPHER_AES_256_PMAC_SIV),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ pub mod ring;
|
||||
pub mod dummy;
|
||||
pub mod aead;
|
||||
pub mod stream;
|
||||
#[cfg(feature = "miscreant")]
|
||||
pub mod siv;
|
||||
#[cfg(feature = "sodium")]
|
||||
pub mod sodium;
|
||||
|
||||
|
||||
+10
-25
@@ -57,32 +57,17 @@ impl RingAeadCipher {
|
||||
macro_rules! seal_or_open {
|
||||
( $item:ident, $key:ident, $crypt:ident ) => {
|
||||
RingAeadCryptoVariant::$item($key::new(&$crypt, key).unwrap(), Bytes::from(nonce))
|
||||
};
|
||||
( $crypt:ident ) => {
|
||||
if is_seal { seal_or_open!(Seal, SealingKey, $crypt) }
|
||||
else { seal_or_open!(Open, OpeningKey, $crypt) }
|
||||
}
|
||||
}
|
||||
|
||||
match t {
|
||||
CipherType::Aes128Gcm => {
|
||||
if is_seal {
|
||||
seal_or_open!(Seal, SealingKey, AES_128_GCM)
|
||||
} else {
|
||||
seal_or_open!(Open, OpeningKey, AES_128_GCM)
|
||||
}
|
||||
}
|
||||
CipherType::Aes256Gcm => {
|
||||
if is_seal {
|
||||
seal_or_open!(Seal, SealingKey, AES_256_GCM)
|
||||
} else {
|
||||
seal_or_open!(Open, OpeningKey, AES_256_GCM)
|
||||
}
|
||||
}
|
||||
CipherType::ChaCha20Poly1305 => {
|
||||
if is_seal {
|
||||
seal_or_open!(Seal, SealingKey, CHACHA20_POLY1305)
|
||||
} else {
|
||||
seal_or_open!(Open, OpeningKey, CHACHA20_POLY1305)
|
||||
}
|
||||
}
|
||||
|
||||
CipherType::Aes128Gcm => seal_or_open!(AES_128_GCM),
|
||||
CipherType::Aes256Gcm => seal_or_open!(AES_256_GCM),
|
||||
CipherType::ChaCha20Poly1305 => seal_or_open!(CHACHA20_POLY1305),
|
||||
_ => panic!("unsupported cipher in ring {:?}", t),
|
||||
}
|
||||
}
|
||||
@@ -115,8 +100,8 @@ impl AeadEncryptor for RingAeadCipher {
|
||||
|
||||
if let RingAeadCryptoVariant::Seal(ref key, ref nonce) = self.cipher {
|
||||
seal_in_place(key, nonce, &[], &mut buf, tag_len).unwrap();
|
||||
output.clone_from_slice(&buf[..input.len()]);
|
||||
tag.clone_from_slice(&buf[input.len()..]);
|
||||
output.copy_from_slice(&buf[..input.len()]);
|
||||
tag.copy_from_slice(&buf[input.len()..]);
|
||||
} else {
|
||||
unreachable!("encrypt is called on a non-seal cipher");
|
||||
}
|
||||
@@ -134,7 +119,7 @@ impl AeadDecryptor for RingAeadCipher {
|
||||
let r = if let RingAeadCryptoVariant::Open(ref key, ref nonce) = self.cipher {
|
||||
match open_in_place(key, nonce, &[], 0, &mut buf) {
|
||||
Ok(buf) => {
|
||||
output.clone_from_slice(&buf[..input.len()]);
|
||||
output.copy_from_slice(&buf[..input.len()]);
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => {
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
//! Cipher defined with Miscreant
|
||||
|
||||
use std::{iter, ptr};
|
||||
|
||||
use miscreant::{Aes128PmacSiv, Aes256PmacSiv};
|
||||
|
||||
use crypto::{AeadDecryptor, AeadEncryptor};
|
||||
use crypto::{CipherResult, CipherType};
|
||||
use crypto::aead::{increase_nonce, make_skey};
|
||||
use crypto::cipher::Error;
|
||||
|
||||
use bytes::{BufMut, BytesMut};
|
||||
|
||||
use byte_string::ByteStr;
|
||||
|
||||
|
||||
/// AEAD ciphers provided by Miscreant
|
||||
pub enum MiscreantCryptoVariant {
|
||||
Aes128(Aes128PmacSiv),
|
||||
Aes256(Aes256PmacSiv)
|
||||
}
|
||||
|
||||
/// AEAD Cipher context
|
||||
///
|
||||
/// According to SIP004, the `nonce` has to incr 1 after each encrypt/decrypt.
|
||||
pub struct MiscreantCipher {
|
||||
cipher: MiscreantCryptoVariant,
|
||||
nonce: BytesMut
|
||||
}
|
||||
|
||||
impl MiscreantCipher {
|
||||
/// Initialize context
|
||||
pub fn new(t: CipherType, key: &[u8], salt: &[u8]) -> Self {
|
||||
// NOTE: Don't need check salt is duplicated. :)
|
||||
|
||||
let nonce_size = t.iv_size();
|
||||
let mut nonce = BytesMut::with_capacity(nonce_size);
|
||||
unsafe {
|
||||
nonce.set_len(nonce_size);
|
||||
ptr::write_bytes(nonce.as_mut_ptr(), 0, nonce_size);
|
||||
}
|
||||
|
||||
let skey = make_skey(t, key, salt);
|
||||
let cipher = Self::new_variant(t, &skey);
|
||||
MiscreantCipher { cipher: cipher, nonce: nonce }
|
||||
}
|
||||
|
||||
fn new_variant(t: CipherType, key: &[u8]) -> MiscreantCryptoVariant {
|
||||
match t {
|
||||
CipherType::Aes128PmacSiv => {
|
||||
let mut skey = [0; 32];
|
||||
skey.copy_from_slice(key);
|
||||
MiscreantCryptoVariant::Aes128(Aes128PmacSiv::new(&skey))
|
||||
},
|
||||
CipherType::Aes256PmacSiv => {
|
||||
let mut skey = [0; 64];
|
||||
skey.copy_from_slice(key);
|
||||
MiscreantCryptoVariant::Aes256(Aes256PmacSiv::new(&skey))
|
||||
},
|
||||
_ => panic!("unsupported cipher in miscreant {:?}", t),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AeadEncryptor for MiscreantCipher {
|
||||
fn encrypt(&mut self, input: &[u8], output: &mut [u8], tag: &mut [u8]) {
|
||||
let tag_len = tag.len();
|
||||
let buf_len = input.len() + tag_len;
|
||||
|
||||
let mut buf = BytesMut::with_capacity(buf_len);
|
||||
unsafe {
|
||||
buf.set_len(buf_len);
|
||||
}
|
||||
buf[tag_len..].copy_from_slice(input);
|
||||
|
||||
match self.cipher {
|
||||
MiscreantCryptoVariant::Aes128(ref mut cipher) => {
|
||||
cipher.seal_in_place(iter::once(&self.nonce), &mut buf);
|
||||
tag.copy_from_slice(&buf[..tag_len]);
|
||||
output.copy_from_slice(&buf[tag_len..]);
|
||||
},
|
||||
MiscreantCryptoVariant::Aes256(ref mut cipher) => {
|
||||
cipher.seal_in_place(iter::once(&self.nonce), &mut buf);
|
||||
tag.copy_from_slice(&buf[..tag_len]);
|
||||
output.copy_from_slice(&buf[tag_len..]);
|
||||
}
|
||||
}
|
||||
|
||||
increase_nonce(&mut self.nonce);
|
||||
}
|
||||
}
|
||||
|
||||
impl AeadDecryptor for MiscreantCipher {
|
||||
fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> CipherResult<()> {
|
||||
let mut buf = BytesMut::with_capacity(input.len() + tag.len());
|
||||
buf.put_slice(tag);
|
||||
buf.put_slice(input);
|
||||
|
||||
let result = match self.cipher {
|
||||
MiscreantCryptoVariant::Aes128(ref mut cipher) =>
|
||||
cipher.open_in_place(iter::once(&self.nonce), &mut buf),
|
||||
MiscreantCryptoVariant::Aes256(ref mut cipher) =>
|
||||
cipher.open_in_place(iter::once(&self.nonce), &mut buf)
|
||||
};
|
||||
|
||||
result
|
||||
.map(|buf| {
|
||||
output.copy_from_slice(buf);
|
||||
increase_nonce(&mut self.nonce);
|
||||
})
|
||||
.map_err(|_| {
|
||||
error!("AEAD decrypt failed, nonce={:?}, input={:?}, tag={:?}, err: decrypt failure",
|
||||
ByteStr::new(&self.nonce),
|
||||
ByteStr::new(input),
|
||||
ByteStr::new(tag));
|
||||
Error::AeadDecryptFailed
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crypto::{CipherType, AeadEncryptor, AeadDecryptor};
|
||||
|
||||
fn test_miscreant(ct: CipherType) {
|
||||
let key = ct.bytes_to_key(b"PassWORD");
|
||||
let message = b"message";
|
||||
|
||||
let iv = ct.gen_init_vec();
|
||||
|
||||
let mut enc = MiscreantCipher::new(ct, &key[..], &iv[..]);
|
||||
let mut encrypted_msg = vec![0; message.len()];
|
||||
let mut tag = [0; 16];
|
||||
enc.encrypt(message, &mut encrypted_msg, &mut tag);
|
||||
|
||||
assert_ne!(message, &encrypted_msg[..]);
|
||||
|
||||
let mut dec = MiscreantCipher::new(ct, &key[..], &iv[..]);
|
||||
let mut decrypted_msg = vec![0; encrypted_msg.len()];
|
||||
dec.decrypt(&encrypted_msg[..], &mut decrypted_msg, &tag).unwrap();
|
||||
|
||||
assert_eq!(&decrypted_msg[..], message);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rust_crypto_cipher_chacha20() {
|
||||
test_miscreant(CipherType::Aes128PmacSiv);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rust_crypto_cipher_salsa20() {
|
||||
test_miscreant(CipherType::Aes256PmacSiv);
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,8 @@ extern crate byteorder;
|
||||
extern crate rand;
|
||||
extern crate typenum;
|
||||
extern crate digest;
|
||||
#[cfg(feature = "miscreant")]
|
||||
extern crate miscreant;
|
||||
#[cfg(feature = "sodium")]
|
||||
extern crate libsodium_ffi;
|
||||
extern crate md_5 as md5;
|
||||
|
||||
Reference in New Issue
Block a user