1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
/*! [odoh-rs] is a library that implements [Oblivious DNS over HTTPS (ODoH) protocol draft-04] in Rust. It can be used to implement an ODoH client or server (target). [odoh-client-rs] uses `odoh-rs` to implement its functionality, and is a good source of API usage examples, along with the tests in `odoh-rs`, in particular [test_vectors_for_odoh]. This library is interoperable with [odoh-go]. `odoh-rs` uses [hpke] as the underlying HPKE implementation. It supports the default Oblivious DoH ciphersuite `(KEM: X25519HkdfSha256, KDF: HkdfSha256, AEAD: AesGcm128)`. It does not provide crypto agility. [odoh-rs]: https://github.com/cloudflare/odoh-rs/ [Oblivious DNS over HTTPS (ODoH) protocol draft-04]: https://tools.ietf.org/html/draft-pauly-dprive-oblivious-doh-04 [odoh-client-rs]: https://github.com/cloudflare/odoh-client-rs/ [odoh-go]: https://github.com/cloudflare/odoh-go [test_vectors_for_odoh]: https://github.com/cloudflare/odoh-rs/src/protocol.rs#L639 [hpke]: https://docs.rs/hpke/0.3.1/hpke/index.html [protocol.rs]: https://github.com/cloudflare/odoh-rs/src/protocol.rs # Example API usage This example outlines the steps necessary for a successful ODoH query. ``` # use crate::odoh_rs::{ # key_utils::derive_keypair_from_seed, # protocol::{ # create_query_msg, create_response_msg, get_supported_config, parse_received_query, # parse_received_response, ObliviousDoHConfig, ObliviousDoHConfigContents, ObliviousDoHConfigs, # ObliviousDoHKeyPair, ObliviousDoHQueryBody, Serialize, ODOH_VERSION, # } # }; # use anyhow::Result; # use hex; # use hpke::{kem::X25519HkdfSha256, kex::KeyExchange, Kem as KemTrait, Serializable}; # use rand::Rng; # pub type Kem = X25519HkdfSha256; # pub type Kex = <Kem as KemTrait>::Kex; // Server generates a secret key pair fn generate_key_pair() -> ObliviousDoHKeyPair { // random bytes, should be 32 bytes for X25519 keys let ikm = rand::thread_rng().gen::<[u8; 32]>();; let (secret_key, public_key) = derive_keypair_from_seed(&ikm); let public_key_bytes = public_key.to_bytes().to_vec(); let odoh_public_key = ObliviousDoHConfigContents { kem_id: 0x0020, // DHKEM(X25519, HKDF-SHA256) kdf_id: 0x0001, // KDF(SHA-256) aead_id: 0x0001, // AEAD(AES-GCM-128) public_key: public_key_bytes, }; ObliviousDoHKeyPair { private_key: secret_key, public_key: odoh_public_key, } } #[tokio::main] async fn main() -> Result<()> { // Server generates a key pair and creates an `ObliviousDoHConfigs` struct from it // which it will distribute to clients via HTTPS records as outlined in the draft: // https://tools.ietf.org/html/draft-pauly-dprive-oblivious-doh-02#section-5 let key_pair = generate_key_pair(); let config = ObliviousDoHConfig::new(&key_pair.public_key.clone().to_bytes().unwrap()).unwrap(); let odohconfig = ObliviousDoHConfigs { configs: vec![config.clone()], } .to_bytes() .unwrap(); // Client gets `odohconfig` via an HTTPS record let client_config = get_supported_config(&odohconfig).unwrap(); // Client creates a query body let query = ObliviousDoHQueryBody::new(&vec![1, 2], Some(2)); // Client creates a query to send to the server let (oblivious_query, client_secret) = create_query_msg(&client_config, &query).unwrap(); // Server receives the query and parses it let (parsed_query, server_secret) = parse_received_query(&key_pair, &oblivious_query) .await .unwrap(); // Server generates a DNS response based on the query let resolver_resp = vec![1, 3, 4]; // Server creates an encrypted response msg to send to the client let generated_response = create_response_msg(&server_secret, &resolver_resp, None, &query) .await .unwrap(); // Client receives the server's encrypted DNS response and parses it to recover the plaintext DNS response. let parsed_response = parse_received_response(&client_secret, &generated_response, &query).unwrap(); Ok(()) } ``` */ pub mod key_utils; pub mod protocol;