odoh-rs

![Latest Version] docs.rs

[odoh-rs] is a library that implements [RFC 9230] Oblivious DNS over HTTPS protocol 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 [testvectorsfor_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 full crypto agility.

Example API Usage

This example outlines the steps necessary for a successful ODoH query.

```rust // Use a seed to initialize a RNG. Note you should rely on some // random source. let mut rng = StdRng::from_seed([0; 32]);

// Generate a key pair on server side. let key_pair = ObliviousDoHKeyPair::new(&mut rng);

// Create client configs from the key pair. It can be distributed // to the clients. let publickey = keypair.public().clone(); let clientconfigs: ObliviousDoHConfigs = vec![ObliviousDoHConfig::from(publickey)].into(); let clientconfigsbytes = compose(&client_configs).unwrap().freeze();

// ... distributing clientconfigsbytes ...

// Parse and extract first supported config from client configs on client side. let clientconfigs: ObliviousDoHConfigs = parse(&mut clientconfigsbytes.clone()).unwrap(); let clientconfig = clientconfigs.intoiter().next().unwrap(); let configcontents = clientconfig.into();

// This is a example client request. This library doesn't validate // DNS message. let query = ObliviousDoHMessagePlaintext::new(b"What's the IP of one.one.one.one?", 0);

// Encrypt the above request. The clientsecret returned will be // used later to decrypt server's response. let (queryenc, clisecret) = encryptquery(&query, &config_contents, &mut rng).unwrap();

// ... sending query_enc to the server ...

// Server decrypt request. let (querydec, srvsecret) = decryptquery(&queryenc, &keypair).unwrap(); asserteq!(query, query_dec);

// Server could now resolve the decrypted query, and compose a response. let response = ObliviousDoHMessagePlaintext::new(b"The IP is 1.1.1.1", 0);

// server encrypt response let nonce = ResponseNonce::default(); let responseenc = encryptresponse(&querydec, &response, srvsecret, nonce).unwrap();

// ... sending response_enc back to the client ...

// client descrypt response let responsedec = decryptresponse(&query, &responseenc, clisecret).unwrap(); asserteq!(response, responsedec); ```