diff --git a/.idea/sptprp.iml b/.idea/sptprp.iml index 7071692..a4b42e3 100644 --- a/.idea/sptprp.iml +++ b/.idea/sptprp.iml @@ -2,11 +2,11 @@ - + - + diff --git a/Cargo.lock b/Cargo.lock index 0f5db7b..a7958e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest", + "digest 0.10.6", ] [[package]] @@ -20,6 +20,18 @@ dependencies = [ "generic-array", ] +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "crypto-common" version = "0.1.6" @@ -30,6 +42,28 @@ dependencies = [ "typenum", ] +[[package]] +name = "curve25519-dalek" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.6" @@ -52,17 +86,110 @@ dependencies = [ ] [[package]] -name = "libsptprp" +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "libsrt" version = "0.1.0" dependencies = [ "blake2", + "rand", + "x25519-dalek", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.8", ] [[package]] name = "sptprprelay" version = "0.1.0" dependencies = [ - "libsptprp", + "libsrt", ] [[package]] @@ -71,14 +198,93 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "typenum" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "x25519-dalek" +version = "2.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5da623d8af10a62342bcbbb230e33e58a63255a58012f8653c578e54bab48df" +dependencies = [ + "curve25519-dalek", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] diff --git a/Cargo.toml b/Cargo.toml index 9a7e155..9af68f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] members = [ - "libsptprp", + "libsrt", "relay" ] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ceb59db --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# SRT + +SRT is a protocol and client system for **S**ecure **R**elayed **T**raffic, designed for quick ephemeral communication between two nodes and a common relay. It uses a modified Noise IKpsk2 handshake (no rekeying) to achieve perfect forward and backward security. +## Contact + diff --git a/libsptprp/Cargo.lock b/libsrt/Cargo.lock similarity index 100% rename from libsptprp/Cargo.lock rename to libsrt/Cargo.lock diff --git a/libsptprp/Cargo.toml b/libsrt/Cargo.toml similarity index 67% rename from libsptprp/Cargo.toml rename to libsrt/Cargo.toml index ec83357..eaf62ee 100644 --- a/libsptprp/Cargo.toml +++ b/libsrt/Cargo.toml @@ -1,9 +1,11 @@ [package] -name = "libsptprp" +name = "libsrt" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -blake2 = "0.10.6" \ No newline at end of file +blake2 = "0.10.6" +x25519-dalek = "2.0.0-pre.1" +rand = "0.8.5" \ No newline at end of file diff --git a/libsptprp/src/cryptography.rs b/libsrt/src/cryptography.rs similarity index 100% rename from libsptprp/src/cryptography.rs rename to libsrt/src/cryptography.rs diff --git a/libsptprp/src/lib.rs b/libsrt/src/lib.rs similarity index 60% rename from libsptprp/src/lib.rs rename to libsrt/src/lib.rs index 83eb8b7..cea9f69 100644 --- a/libsptprp/src/lib.rs +++ b/libsrt/src/lib.rs @@ -1,4 +1,5 @@ #[cfg(test)] pub mod tests; pub mod cryptography; -pub mod packets; \ No newline at end of file +pub mod packets; +pub mod tunnel; \ No newline at end of file diff --git a/libsptprp/src/packets/clientbound.rs b/libsrt/src/packets/clientbound.rs similarity index 67% rename from libsptprp/src/packets/clientbound.rs rename to libsrt/src/packets/clientbound.rs index 8ef7ad1..ef6b14f 100644 --- a/libsptprp/src/packets/clientbound.rs +++ b/libsrt/src/packets/clientbound.rs @@ -50,4 +50,30 @@ impl SptprpPacket for ChannelReadyPacket { channel: bytes[1..].try_into().unwrap() }) } +} + +#[derive(Debug, PartialEq)] +pub struct ChannelInUsePacket { + pub channel: [u8; 32] +} +impl SptprpPacket for ChannelInUsePacket { + const PACKET_ID: u8 = 0x05; + + fn to_bytes(&self) -> Vec { + let mut bytes = vec![0x05]; + bytes.extend_from_slice(&self.channel); + bytes + } + + fn from_bytes(bytes: &Vec) -> Result { + if bytes.len() != 33 { + return Err(PacketParseError::IncorrectPacketLength) + } + if bytes[0] != 0x05u8 { + return Err(PacketParseError::IncorrectPacketType) + } + Ok(Self { + channel: bytes[1..].try_into().unwrap() + }) + } } \ No newline at end of file diff --git a/libsptprp/src/packets/initbound.rs b/libsrt/src/packets/initbound.rs similarity index 100% rename from libsptprp/src/packets/initbound.rs rename to libsrt/src/packets/initbound.rs diff --git a/libsptprp/src/packets/mod.rs b/libsrt/src/packets/mod.rs similarity index 95% rename from libsptprp/src/packets/mod.rs rename to libsrt/src/packets/mod.rs index aafa3fa..5ce80e5 100644 --- a/libsptprp/src/packets/mod.rs +++ b/libsrt/src/packets/mod.rs @@ -9,7 +9,7 @@ TODO [x] 0x02 Channel Not Ready [x] 0x03 Channel Ready [x] 0x04 Relay Data -[ ] 0x05 Channel In Use +[x] 0x05 Channel In Use [ ] 0x06 Handshake Start [ ] 0x07 Handshake Response [ ] 0x08 Encrypted Data diff --git a/libsptprp/src/packets/recvbound.rs b/libsrt/src/packets/recvbound.rs similarity index 100% rename from libsptprp/src/packets/recvbound.rs rename to libsrt/src/packets/recvbound.rs diff --git a/libsptprp/src/packets/relaybound.rs b/libsrt/src/packets/relaybound.rs similarity index 100% rename from libsptprp/src/packets/relaybound.rs rename to libsrt/src/packets/relaybound.rs diff --git a/libsptprp/src/tests.rs b/libsrt/src/tests.rs similarity index 79% rename from libsptprp/src/tests.rs rename to libsrt/src/tests.rs index 8ed32e8..d6449ff 100644 --- a/libsptprp/src/tests.rs +++ b/libsrt/src/tests.rs @@ -1,5 +1,5 @@ use crate::cryptography::HASH; -use crate::packets::clientbound::{ChannelNotReadyPacket, ChannelReadyPacket}; +use crate::packets::clientbound::{ChannelInUsePacket, ChannelNotReadyPacket, ChannelReadyPacket}; use crate::packets::relaybound::{ChannelWaitPacket, RelayDataPacket}; use crate::packets::SptprpPacket; @@ -31,6 +31,15 @@ pub fn pkt_channel_ready() { channel: [0u8; 32], }, ChannelReadyPacket::from_bytes(&vec![3u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8]).unwrap()) } +#[test] +pub fn pkt_channel_in_use() { + assert_eq!(ChannelInUsePacket { + channel: [0u8; 32], + }.to_bytes(), [5u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8]); + assert_eq!(ChannelInUsePacket { + channel: [0u8; 32], + }, ChannelInUsePacket::from_bytes(&vec![5u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8]).unwrap()) +} #[test] pub fn hash() { diff --git a/libsrt/src/tunnel.rs b/libsrt/src/tunnel.rs new file mode 100644 index 0000000..4c5f472 --- /dev/null +++ b/libsrt/src/tunnel.rs @@ -0,0 +1,44 @@ +use std::net::SocketAddr; +use rand::rngs::OsRng; +use x25519_dalek::{EphemeralSecret, PublicKey}; +use crate::cryptography::HASH; + +/// The main tunnel state machine container +pub struct SPTunnel { + relay: SocketAddr, + channel_name: String, + pmk: [u8; 32], + cid: [u8; 32], + + e: EphemeralSecret, + ee: PublicKey, + eer: PublicKey, + + state: SPTunnelState +} +impl SPTunnel { + fn new(relay: SocketAddr, channel_name: String) -> Self { + // calculate the pmk and cid (various hashes of the channel name) + let pmk = HASH(&channel_name); + let cid = HASH(&pmk); + + // generate an ephemeral secret key + let e = EphemeralSecret::new(OsRng); + let ee = PublicKey::from(&e); + + SPTunnel { + relay, + channel_name, + pmk, + cid, + e, + ee, + eer: PublicKey::from([0u8; 32]), + state: SPTunnelState::NotConnected, + } + } +} + +pub enum SPTunnelState { + NotConnected +} \ No newline at end of file diff --git a/relay/Cargo.toml b/relay/Cargo.toml index f5b52fe..b4704a6 100644 --- a/relay/Cargo.toml +++ b/relay/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -libsptprp = { version = "0.1.0", path = "../libsptprp" } \ No newline at end of file +libsrt = { version = "0.1.0", path = "../libsrt" } \ No newline at end of file