Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

o5 Transport #26

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

members = [
"crates/lyrebird",
# "crates/o5",
"crates/o5",
"crates/o7",
"crates/obfs4",
"crates/ptrs",
Expand Down
2 changes: 1 addition & 1 deletion crates/lyrebird/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ anyhow = "1.0"
clap = { version = "4.4", features = ["derive"]}
fast-socks5 = "0.9.1"
futures = "0.3.29"
safelog = "0.3.5"
safelog = "0.4.0"
thiserror = "1.0.56"
tokio = { version = "1.34", features = ["io-util", "net", "macros", "sync", "signal"] }
tokio-util = "0.7.10"
Expand Down
63 changes: 56 additions & 7 deletions crates/o5/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,30 +1,79 @@
[package]
name = "o5"
version = "0.1.0"
version = "0.1.0-alpha.1"
edition = "2021"
authors = ["Jack Wampler <[email protected]>"]
rust-version = "1.81"
license = "MIT OR Apache-2.0"
description = "Pure rust implementation of the o5 pluggable transport"
keywords = ["tor", "censorship", "pluggable", "transports"]
categories = ["network-programming", "cryptography"]
repository = "https://github.com/jmwample/ptrs"


[lib]
name = "o5"
crate-type = ["cdylib", "rlib"]

[dependencies]
## Local
ptrs = { path="../ptrs", version="0.1.0" }

## PRNG
getrandom = "0.2.11"
rand = { version="0.8.5", features=["getrandom"]}
rand_core = "0.6.4"

## Crypto
digest = { version = "0.10.7", features=["mac", "core-api"]}
typenum = "1.17.0"
block-buffer = "0.10.4"
siphasher = "1.0.0"
sha2 = "0.10.8"
hmac = { version="0.12.1", features=["reset"]}
hkdf = "0.12.3"
crypto_secretbox = { version="0.1.1", features=["chacha20"]}
subtle = "2.5.0"
x25519-dalek = { version = "2.0.1", features = ["static_secrets", "getrandom", "reusable_secrets", "elligator2"], git = "https://github.com/jmwample/curve25519-dalek.git", branch = "elligator2-ntor"}
x25519-dalek = { version = "2.0.1", features = ["static_secrets", "getrandom", "reusable_secrets"]}

## Utils
pin-project = "1.1.3"
hex = "0.4.3"
futures = "0.3.29"
tracing = "0.1.40"
colored = "2.0.4"
serde_json = "1.0.114"
serde = "1.0.197"
base64 = "0.22.0"

# ntor_arti
## Networking tools
tokio = { version = "1.33", features = ["io-util", "rt-multi-thread", "net", "rt", "macros", "sync", "signal", "time", "fs"] }
tokio-util = { version = "0.7.10", features = ["codec", "io"]}
bytes = "1.5.0"

## ntor_arti
tor-cell = "0.23.0"
tor-llcrypto = "0.23.0"
tor-error = "0.23.0"
tor-bytes = "0.23.0"
cipher = "0.4.4"
zeroize = "1.7.0"
thiserror = "1.0.56"

curve25519-elligator2 = { version="0.1.0-alpha.1", features=["elligator2"] }

# o5 pqc
ml-kem = "0.2.1"
kem = "0.3.0-pre.0"
# kemeleon = { version="0.1.0-rc.1", path="../../../../elligantt/kemeleon"}
kemeleon = { version="0.1.0-rc.1", git="https://github.com/jmwample/kemeleon", branch="cleanup"}

[dev-dependencies]
hex = "0.4.3"
anyhow = "1.0"
tracing-subscriber = "0.3.18"
hex-literal = "0.4.1"
tor-basic-utils = "0.22.0"

# o5 pqc test
# pqc_kyber = {version="0.7.1", features=["kyber1024", "std"]}
ml-kem = "0.1.0"

[lints.rust]
# unexpected_cfgs are used to disable incomplete / WIP features and tests. This is
Expand Down
50 changes: 29 additions & 21 deletions crates/o5/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# o5 Pluggable Transport Library

A randomizing look like nothing pluggable transport library, spiritually a successor
to `obfs4`.
This is a spiritual successor to `obfs4` updating some of the more annoying / out of
date elements without worrying about being backward compatible.


⚠️ 🚧 WARNING This crate is still under construction 🚧 ⚠️
Expand All @@ -10,30 +10,38 @@ to `obfs4`.
- Not production ready
- do not rely on this for any security critical applications


## Changes from obfs4:


* adds `Kyber1024` to the Key exchange making it hybrid `Kyber1024X25519` (or `Kyber1024X`)
* Are Kyber1024 keys uniform random? I assume not.
* aligns algorithm with vanilla ntor
- obfs4 does an extra hash
* change mark and MAC from sha256-128 to sha256
- not sure why this was done in the first place
* padding change (/fix?)
* padding is a frame type, not just appended bytes
* version / params frame for negotiating (non-forward secret in the first exchange alongside PRNG seed)
* might add
- session tickets and resumption
- bidirectional heartbeats
- handshake complete frame type

## Differences from obfs4

- Frame / Packet / Message construction
- In obfs4 a "frame" consists of a signle "packet", encoded using xsalsa20Poly1305.
we use the same frame construction, but change a few key elements:
- the concept of "packets" is now called "messages"
- a frame can contain multiple messages
- update from xsalsa20poly1305 -> chacha20poly1305
- padding is given an explicit message type different than that of a payload and uses the mesage length header field
- (In obfs4 a frame that decodes to a payload packet type `\x00` with packet length 0 is asummed to all be padding)
- move payload to message type `\x01`
- padding takes message type `\x00`
- (Maybe) add bidirectional heartbeat messages
- Handshake
- x25519 key-exchange -> Kyber1024X25519 key-exchange
- the overhead padding of the current obfs4 handshake (resulting in paket length in [4096:8192]) is mostly unused
we exchange some of this unused padding for a kyber key to provide post-quantum security to the handshake.
- Are Kyber1024 keys uniform random? I assume not.
- NTor V3 handshake
- the obfs4 handshake uses (a custom version of) the ntor handshake to derive key materials
- (Maybe) change mark and MAC from sha256-128 to sha256
- handshake parameters encrypted under the key exchange public keys
- the client can provide initial parameters during the handshake, knowing that they are not forward secure.
- the server can provide messages with parameters / extensions in the handshake response (like prngseed)
- like the kyber key, this takes space out of the padding already used in the client handshake.
- (Maybe) session tickets and resumption
- (Maybe) handshake complete frame type

### Goals
* Stick closer to Codec / Framed implementation for all packets (hadshake included)
* use the tor/arti ntor v3 implementation


### Features to keep
- once a session is established, unrecognized frame types are ignored

Loading