From c2cb69954f26ad06afc6e5917fdf73ee7527baed Mon Sep 17 00:00:00 2001 From: Alonso Date: Mon, 27 May 2024 12:20:27 -0400 Subject: [PATCH 1/9] feat: added rrsets and sing/verify signature methods --- Cargo.toml | 1 + src/dnssec.rs | 1 + src/dnssec/dnssec_decryption.rs | 29 ++++++++++++++ src/dnssec/dnssec_encryption.rs | 67 ++++++++++++++++++++++++++++++++- src/message/rrset.rs | 62 ++++++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 src/dnssec/dnssec_decryption.rs create mode 100644 src/message/rrset.rs diff --git a/Cargo.toml b/Cargo.toml index 47110c4f..d17a210e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ async-trait = "0.1.77" sha2 = "0.10.2" hmac = "0.12.1" rust-crypto = "0.2" +base = "0.12.3" lru = "0.12.3" diff --git a/src/dnssec.rs b/src/dnssec.rs index 256b2afa..aca0bb75 100644 --- a/src/dnssec.rs +++ b/src/dnssec.rs @@ -1,4 +1,5 @@ pub mod dnssec_encryption; +pub mod dnssec_decryption; use crate::message::resource_record::{FromBytes, ToBytes}; use crate::tsig; \ No newline at end of file diff --git a/src/dnssec/dnssec_decryption.rs b/src/dnssec/dnssec_decryption.rs new file mode 100644 index 00000000..2c3c1ab3 --- /dev/null +++ b/src/dnssec/dnssec_decryption.rs @@ -0,0 +1,29 @@ +use crypto::digest::Digest; +use crypto::sha1::Sha1; +use crypto::sha2::Sha256; +use crypto::rsa::Rsa; +use crate::dnssec::RRset; +use crate::dnskey_rdata::DnskeyRdata; +use crate::rrsig_rdata::RRSIGRdata; + +/// RFCs: [4033, 4034, 4035, 5702] + +/// Verifies an RRset using the provided public key and RRSIG record. +/// Returns true if the verification is successful. +pub fn verify_rrset(rrset: &RRset, rrsig: &RRSIGRdata, public_key: &Rsa) -> Result { + let rrset_bytes = rrset.to_bytes(); + + let mut hasher: Box = match rrsig.algorithm { + 1 => Box::new(Sha1::new()), + 2 => Box::new(Sha256::new()), + _ => return Err("Algorithm not supported"), + }; + + hasher.input(&rrset_bytes); + let hash = hasher.result_str(); + + let signature = base64::decode(&rrsig.signature).map_err(|_| "Error while decoding signature")?; + + public_key.verify(hasher, &hash.as_bytes(), &signature).map_err(|_| "Verification failed") +} + diff --git a/src/dnssec/dnssec_encryption.rs b/src/dnssec/dnssec_encryption.rs index 0020b9af..047f9d30 100644 --- a/src/dnssec/dnssec_encryption.rs +++ b/src/dnssec/dnssec_encryption.rs @@ -1 +1,66 @@ -use crypto; \ No newline at end of file +use crypto::digest::Digest; +use crypto::sha1::Sha1; +use crypto::sha2::Sha256; +use crypto::rsa::Rsa; +use crate::dnssec::RRset; +use crate::dnskey_rdata::DnskeyRdata; +use crate::rrsig_rdata::RRSIGRdata; +use base64; + +/// RFCs: [4033, 4034, 4035, 4509] + +/// Signs a RRset using the private_key given. +/// Returns a RRSIG that contains the signature. +pub fn sign_rrset(rrset: &RRset, private_key: &Rsa, algorithm: u8) -> Result { + let rrset_bytes = rrset.to_bytes(); + + let mut hasher: Box = match algorithm { + 1 => Box::new(Sha1::new()), + 2 => Box::new(Sha256::new()), + _ => return Err("Algorithm not supported"), + }; + + hasher.input(&rrset_bytes); + let hash = hasher.result_str(); + + let signature = private_key.sign(hasher, &hash.as_bytes()).map_err(|_| "Error while signing")?; + + let rrsig = RRSIGRdata { + type_covered: rrset.get_type(), + algorithm, + labels: rrset.get_labels(), + original_ttl: rrset.get_ttl(), + signature_expiration: get_expiration_time(), + signature_inception: get_inception_time(), + key_tag: calculate_key_tag(private_key), + signer_name: rrset.get_name().clone(), + signature: base64::encode(&signature), + }; + + Ok(rrsig) +} + +// Gets the expiration time for the signature. +fn get_expiration_time() -> u32 { + // Supposing sign validity = 1 day (86400 seconds) + let now = std::time::SystemTime::now(); + let expiration_duration = std::time::Duration::new(86400, 0); + let expiration_time = now + expiration_duration; + expiration_time.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 +} + +// Gets the inception time for the signature. +fn get_inception_time() -> u32 { + // Assuming current time + let now = std::time::SystemTime::now(); + now.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 +} + +// Calculates the key tag for the public key. +fn calculate_key_tag(private_key: &Rsa) -> u16 { + let public_key_der = private_key.to_public_key_der().unwrap(); + let mut hasher = Sha1::new(); + hasher.input(&public_key_der); + let hash = hasher.result_str(); + u16::from_be_bytes([hash.as_bytes()[18], hash.as_bytes()[19]]) +} diff --git a/src/message/rrset.rs b/src/message/rrset.rs new file mode 100644 index 00000000..15a43438 --- /dev/null +++ b/src/message/rrset.rs @@ -0,0 +1,62 @@ +use crate::message::Rtype; +use crate::message::Rclass; +use crate::message::resource_record::ResourceRecord; +use std::collections::HashSet; + +/// Represents a set of resource records (RRset). +#[derive(Debug)] +pub struct RRset { + /// The name of the domain associated with this RRset. + name: String, + /// The type of resource record in this RRset. + rtype: Rtype, + /// The class of resource record in this RRset. + rclass: Rclass, + /// The time to live (TTL) value for records in this RRset. + ttl: u32, + /// The set of resource records belonging to this RRset. + records: HashSet, +} + +impl RRset { + /// Creates a new RRset. + pub fn new(name: String, rtype: Rtype, rclass: Rclass, ttl: u32) -> RRset { + RRset { + name, + rtype, + rclass, + ttl, + records: HashSet::new(), + } + } + + /// Adds a resource record to this RRset. + pub fn add_record(&mut self, record: ResourceRecord) { + self.records.insert(record); + } + + /// Gets the name of the domain associated with this RRset. + pub fn get_name(&self) -> &String { + &self.name + } + + /// Gets the type of resource record in this RRset. + pub fn get_type(&self) -> Rtype { + self.rtype + } + + /// Gets the class of resource record in this RRset. + pub fn get_class(&self) -> Rclass { + self.rclass + } + + /// Gets the time to live (TTL) value for records in this RRset. + pub fn get_ttl(&self) -> u32 { + self.ttl + } + + /// Gets the set of resource records belonging to this RRset. + pub fn get_records(&self) -> &HashSet { + &self.records + } +} From 97e4703a5b014d4224242b9d289c874afbf45ae9 Mon Sep 17 00:00:00 2001 From: Alonso Date: Mon, 27 May 2024 12:33:33 -0400 Subject: [PATCH 2/9] fix: file name regarding rrset signature processes --- src/dnssec/dnssec_decryption.rs | 29 ----------- src/dnssec/dnssec_encryption.rs | 66 ------------------------- src/dnssec/rrset_signature.rs | 88 +++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 95 deletions(-) create mode 100644 src/dnssec/rrset_signature.rs diff --git a/src/dnssec/dnssec_decryption.rs b/src/dnssec/dnssec_decryption.rs index 2c3c1ab3..e69de29b 100644 --- a/src/dnssec/dnssec_decryption.rs +++ b/src/dnssec/dnssec_decryption.rs @@ -1,29 +0,0 @@ -use crypto::digest::Digest; -use crypto::sha1::Sha1; -use crypto::sha2::Sha256; -use crypto::rsa::Rsa; -use crate::dnssec::RRset; -use crate::dnskey_rdata::DnskeyRdata; -use crate::rrsig_rdata::RRSIGRdata; - -/// RFCs: [4033, 4034, 4035, 5702] - -/// Verifies an RRset using the provided public key and RRSIG record. -/// Returns true if the verification is successful. -pub fn verify_rrset(rrset: &RRset, rrsig: &RRSIGRdata, public_key: &Rsa) -> Result { - let rrset_bytes = rrset.to_bytes(); - - let mut hasher: Box = match rrsig.algorithm { - 1 => Box::new(Sha1::new()), - 2 => Box::new(Sha256::new()), - _ => return Err("Algorithm not supported"), - }; - - hasher.input(&rrset_bytes); - let hash = hasher.result_str(); - - let signature = base64::decode(&rrsig.signature).map_err(|_| "Error while decoding signature")?; - - public_key.verify(hasher, &hash.as_bytes(), &signature).map_err(|_| "Verification failed") -} - diff --git a/src/dnssec/dnssec_encryption.rs b/src/dnssec/dnssec_encryption.rs index 047f9d30..e69de29b 100644 --- a/src/dnssec/dnssec_encryption.rs +++ b/src/dnssec/dnssec_encryption.rs @@ -1,66 +0,0 @@ -use crypto::digest::Digest; -use crypto::sha1::Sha1; -use crypto::sha2::Sha256; -use crypto::rsa::Rsa; -use crate::dnssec::RRset; -use crate::dnskey_rdata::DnskeyRdata; -use crate::rrsig_rdata::RRSIGRdata; -use base64; - -/// RFCs: [4033, 4034, 4035, 4509] - -/// Signs a RRset using the private_key given. -/// Returns a RRSIG that contains the signature. -pub fn sign_rrset(rrset: &RRset, private_key: &Rsa, algorithm: u8) -> Result { - let rrset_bytes = rrset.to_bytes(); - - let mut hasher: Box = match algorithm { - 1 => Box::new(Sha1::new()), - 2 => Box::new(Sha256::new()), - _ => return Err("Algorithm not supported"), - }; - - hasher.input(&rrset_bytes); - let hash = hasher.result_str(); - - let signature = private_key.sign(hasher, &hash.as_bytes()).map_err(|_| "Error while signing")?; - - let rrsig = RRSIGRdata { - type_covered: rrset.get_type(), - algorithm, - labels: rrset.get_labels(), - original_ttl: rrset.get_ttl(), - signature_expiration: get_expiration_time(), - signature_inception: get_inception_time(), - key_tag: calculate_key_tag(private_key), - signer_name: rrset.get_name().clone(), - signature: base64::encode(&signature), - }; - - Ok(rrsig) -} - -// Gets the expiration time for the signature. -fn get_expiration_time() -> u32 { - // Supposing sign validity = 1 day (86400 seconds) - let now = std::time::SystemTime::now(); - let expiration_duration = std::time::Duration::new(86400, 0); - let expiration_time = now + expiration_duration; - expiration_time.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 -} - -// Gets the inception time for the signature. -fn get_inception_time() -> u32 { - // Assuming current time - let now = std::time::SystemTime::now(); - now.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 -} - -// Calculates the key tag for the public key. -fn calculate_key_tag(private_key: &Rsa) -> u16 { - let public_key_der = private_key.to_public_key_der().unwrap(); - let mut hasher = Sha1::new(); - hasher.input(&public_key_der); - let hash = hasher.result_str(); - u16::from_be_bytes([hash.as_bytes()[18], hash.as_bytes()[19]]) -} diff --git a/src/dnssec/rrset_signature.rs b/src/dnssec/rrset_signature.rs new file mode 100644 index 00000000..853f916c --- /dev/null +++ b/src/dnssec/rrset_signature.rs @@ -0,0 +1,88 @@ +use crypto::digest::Digest; +use crypto::sha1::Sha1; +use crypto::sha2::Sha256; +use crypto::rsa::Rsa; +use crate::dnssec::RRset; +use crate::dnskey_rdata::DnskeyRdata; +use crate::rrsig_rdata::RRSIGRdata; +use base64; + +/// RFCs: [4033, 4034, 4035, 4509] + +/// Signs a RRset using the private_key given. +/// Returns a RRSIG that contains the signature. +pub fn sign_rrset(rrset: &RRset, private_key: &Rsa, algorithm: u8) -> Result { + let rrset_bytes = rrset.to_bytes(); + + let mut hasher: Box = match algorithm { + 1 => Box::new(Sha1::new()), + 2 => Box::new(Sha256::new()), + _ => return Err("Algorithm not supported"), + }; + + hasher.input(&rrset_bytes); + let hash = hasher.result_str(); + + let signature = private_key.sign(hasher, &hash.as_bytes()).map_err(|_| "Error while signing")?; + + let rrsig = RRSIGRdata { + type_covered: rrset.get_type(), + algorithm, + labels: rrset.get_labels(), + original_ttl: rrset.get_ttl(), + signature_expiration: get_expiration_time(), + signature_inception: get_inception_time(), + key_tag: calculate_key_tag(private_key), + signer_name: rrset.get_name().clone(), + signature: base64::encode(&signature), + }; + + Ok(rrsig) +} + +// Gets the expiration time for the signature. +fn get_expiration_time() -> u32 { + // Supposing sign validity = 1 day (86400 seconds) + let now = std::time::SystemTime::now(); + let expiration_duration = std::time::Duration::new(86400, 0); + let expiration_time = now + expiration_duration; + expiration_time.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 +} + +// Gets the inception time for the signature. +fn get_inception_time() -> u32 { + // Assuming current time + let now = std::time::SystemTime::now(); + now.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 +} + +// Calculates the key tag for the public key. +fn calculate_key_tag(private_key: &Rsa) -> u16 { + let public_key_der = private_key.to_public_key_der().unwrap(); + let mut hasher = Sha1::new(); + hasher.input(&public_key_der); + let hash = hasher.result_str(); + u16::from_be_bytes([hash.as_bytes()[18], hash.as_bytes()[19]]) +} + +/// RFCs: [4033, 4034, 4035, 5702] + +/// Verifies an RRset using the provided public key and RRSIG record. +/// Returns true if the verification is successful. +pub fn verify_rrset(rrset: &RRset, rrsig: &RRSIGRdata, public_key: &Rsa) -> Result { + let rrset_bytes = rrset.to_bytes(); + + let mut hasher: Box = match rrsig.algorithm { + 1 => Box::new(Sha1::new()), + 2 => Box::new(Sha256::new()), + _ => return Err("Algorithm not supported"), + }; + + hasher.input(&rrset_bytes); + let hash = hasher.result_str(); + + let signature = base64::decode(&rrsig.signature).map_err(|_| "Error while decoding signature")?; + + public_key.verify(hasher, &hash.as_bytes(), &signature).map_err(|_| "Verification failed") +} + From 04447511382addc9c2a0681a22d0aa3570fad9dc Mon Sep 17 00:00:00 2001 From: Alonso Date: Mon, 27 May 2024 12:37:52 -0400 Subject: [PATCH 3/9] feat: added missing method get_labels --- src/message/rrset.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/message/rrset.rs b/src/message/rrset.rs index 15a43438..bca9953c 100644 --- a/src/message/rrset.rs +++ b/src/message/rrset.rs @@ -59,4 +59,9 @@ impl RRset { pub fn get_records(&self) -> &HashSet { &self.records } + + // Gets the labels of the domain associated with this RRset. + pub fn get_labels(&self) -> usize { + self.name.split('.').count() + } } From 43c3873f2fdcd3d921bfd9fb78b3bddbde2e29b0 Mon Sep 17 00:00:00 2001 From: Alonso Date: Wed, 10 Jul 2024 11:21:19 -0400 Subject: [PATCH 4/9] feat: added dnssec message processing --- Cargo.lock | 382 +++++++++++++++--------- Cargo.toml | 2 +- src/dnssec/dnssec_message_processing.rs | 39 +++ src/dnssec/rrset_signature.rs | 1 - src/message/rrset.rs | 120 +++++++- 5 files changed, 392 insertions(+), 152 deletions(-) create mode 100644 src/dnssec/dnssec_message_processing.rs diff --git a/Cargo.lock b/Cargo.lock index 219d74fd..17d77d11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -52,57 +52,58 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", @@ -111,15 +112,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" dependencies = [ "addr2line", "cc", @@ -130,11 +131,17 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bitflags" -version = "1.3.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "block-buffer" @@ -147,24 +154,21 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" [[package]] name = "cfg-if" @@ -174,23 +178,23 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets", + "windows-targets 0.52.5", ] [[package]] name = "clap" -version = "4.4.8" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", "clap_derive", @@ -198,9 +202,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.8" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstream", "anstyle", @@ -210,9 +214,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" dependencies = [ "heck", "proc-macro2", @@ -222,21 +226,21 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" @@ -273,6 +277,7 @@ name = "dns_rust" version = "0.1.0" dependencies = [ "async-trait", + "base64", "bytes", "chrono", "clap", @@ -296,15 +301,15 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", @@ -313,15 +318,15 @@ dependencies = [ [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-macro", @@ -349,9 +354,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -360,15 +365,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -376,15 +381,15 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -403,9 +408,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -424,26 +429,32 @@ dependencies = [ "cc", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "js-sys" -version = "0.3.65" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.150" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -451,9 +462,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lru" @@ -466,35 +477,35 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -511,24 +522,24 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -536,22 +547,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.5", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -567,18 +578,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -662,9 +673,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ "bitflags", ] @@ -684,9 +695,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-serialize" @@ -713,9 +724,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -731,25 +742,25 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" @@ -759,9 +770,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "2.0.48" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -770,18 +781,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", @@ -801,9 +812,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.35.1" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -815,14 +826,14 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", @@ -854,9 +865,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "version_check" @@ -878,9 +889,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -888,9 +899,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -903,9 +914,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -913,9 +924,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -926,9 +937,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "winapi" @@ -954,11 +965,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.5", ] [[package]] @@ -967,7 +978,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", ] [[package]] @@ -976,13 +996,29 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -991,56 +1027,104 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index d17a210e..05e94d48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ async-trait = "0.1.77" sha2 = "0.10.2" hmac = "0.12.1" rust-crypto = "0.2" -base = "0.12.3" +base64 = "0.22.1" lru = "0.12.3" diff --git a/src/dnssec/dnssec_message_processing.rs b/src/dnssec/dnssec_message_processing.rs new file mode 100644 index 00000000..17866a15 --- /dev/null +++ b/src/dnssec/dnssec_message_processing.rs @@ -0,0 +1,39 @@ +use crate::message::DnsMessage; +use crate::message::rdata::{rrsig_rdata, dnskey_rdata, ds_rdata, nsec_rdata, nsec3_rdata}; + +// DNSKEY, RRSIG, DS | NSEC, NSEC3 ? + +fn extract_dnssec_records(dns_message: &DnsMessage) -> (Vec, Vec, Vec) { + let mut dnskey_records = Vec::new(); + let mut rrsig_records = Vec::new(); + let mut ds_records = Vec::new(); + + for record in &dns_message.additional { + match record.rdata { + Rdata::DNSKEY(ref data) => { + let dnskey_rdata = DnskeyRdata::new(data.flags, data.protocol, data.algorithm, data.public_key.clone()); + dnskey_records.push(dnskey_rdata); + } + Rdata::RRSIG(ref data) => { + let rrsig_rdata = RrsigRdata::new( + data.type_covered, + data.algorithm, + data.labels, + data.original_ttl, + //datatime? expiration/inception + data.key_tag, + data.signer_name.clone(), + data.signature.clone() + ); + rrsig_records.push(rrsig_rdata); + } + Rdata::DS(ref data) => { + let ds_rdata = DsRdata::new(data.key_tag, data.algorithm, data.digest_type, data.digest.clone() + ); + ds_records.push(ds_rdata); + }, + _ => (), + } + } + (dnskey_records, rrsig_records, ds_records) +} \ No newline at end of file diff --git a/src/dnssec/rrset_signature.rs b/src/dnssec/rrset_signature.rs index 853f916c..d230790c 100644 --- a/src/dnssec/rrset_signature.rs +++ b/src/dnssec/rrset_signature.rs @@ -85,4 +85,3 @@ pub fn verify_rrset(rrset: &RRset, rrsig: &RRSIGRdata, public_key: &Rsa) -> Resu public_key.verify(hasher, &hash.as_bytes(), &signature).map_err(|_| "Verification failed") } - diff --git a/src/message/rrset.rs b/src/message/rrset.rs index bca9953c..00e5d0a9 100644 --- a/src/message/rrset.rs +++ b/src/message/rrset.rs @@ -60,8 +60,126 @@ impl RRset { &self.records } - // Gets the labels of the domain associated with this RRset. + /// Gets the labels of the domain associated with this RRset. pub fn get_labels(&self) -> usize { self.name.split('.').count() } + + /// Serializes the RRset to a byte array for signing. + pub fn to_bytes(&self) -> Vec { + let mut bytes = Vec::new(); + for record in &self.records { + bytes.extend(record.to_bytes()); // Assuming ResourceRecord has a to_bytes method + } + bytes + } +} + + +#[cfg(test)] +mod tests { + use super::*; + use crate::message::Rtype; + use crate::message::Rclass; + use crate::message::resource_record::{ResourceRecord, Rdata, ARdata, NsRdata, CnameRdata}; + use std::net::IpAddr; + use std::collections::HashSet; + + #[test] + fn test_create_rrset() { + let name = "example.com".to_string(); + let rtype = Rtype::A; + let rclass = Rclass::IN; + let ttl = 3600; + + let rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + assert_eq!(rrset.get_name(), &name); + assert_eq!(rrset.get_type(), Rtype::A); + assert_eq!(rrset.get_class(), Rclass::IN); + assert_eq!(rrset.get_ttl(), 3600); + assert_eq!(rrset.get_labels(), 2); + assert!(rrset.get_records().is_empty()); + } + + #[test] + fn test_add_record() { + let name = "example.com".to_string(); + let rtype = Rtype::A; + let rclass = Rclass::IN; + let ttl = 3600; + + let mut rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + let mut a_rdata = Rdata::A(ARdata::new()); + match a_rdata { + Rdata::A(ref mut val) => val.set_address(IpAddr::from([127, 0, 0, 1])), + _ => unreachable!(), + } + + let record = ResourceRecord::new(a_rdata); + rrset.add_record(record); + + assert_eq!(rrset.get_records().len(), 1); + } + + #[test] + fn test_get_name() { + let name = "example.com".to_string(); + let rtype = Rtype::A; + let rclass = Rclass::IN; + let ttl = 3600; + + let rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + assert_eq!(rrset.get_name(), &name); + } + + #[test] + fn test_get_type() { + let name = "example.com".to_string(); + let rtype = Rtype::NS; + let rclass = Rclass::IN; + let ttl = 3600; + + let rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + assert_eq!(rrset.get_type(), Rtype::NS); + } + + #[test] + fn test_get_class() { + let name = "example.com".to_string(); + let rtype = Rtype::MX; + let rclass = Rclass::CH; + let ttl = 3600; + + let rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + assert_eq!(rrset.get_class(), Rclass::CH); + } + + #[test] + fn test_get_ttl() { + let name = "example.com".to_string(); + let rtype = Rtype::A; + let rclass = Rclass::IN; + let ttl = 7200; + + let rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + assert_eq!(rrset.get_ttl(), 7200); + } + + #[test] + fn test_get_labels() { + let name = "sub.example.com".to_string(); + let rtype = Rtype::A; + let rclass = Rclass::IN; + let ttl = 3600; + + let rrset = RRset::new(name.clone(), rtype, rclass, ttl); + + assert_eq!(rrset.get_labels(), 3); + } } From 142ba4e8339ab9ab09688700fbfd05335fde987c Mon Sep 17 00:00:00 2001 From: Alonso Date: Thu, 11 Jul 2024 21:50:00 -0400 Subject: [PATCH 5/9] feat: added extract_dnssec_records method to message --- src/message.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/message.rs b/src/message.rs index b6b20fc9..7f2e3f6f 100644 --- a/src/message.rs +++ b/src/message.rs @@ -894,6 +894,18 @@ impl DnsMessage { } } + pub fn extract_dnssec_records(&self) -> Vec { + let mut dnssec_records = Vec::new(); + + for record in self.additional.iter() { + if let Rdata::DNSKEY(dnskey) = &record.get_rdata() { + dnssec_records.push(dnskey.clone()); + } + } + + dnssec_records + } + } impl fmt::Display for DnsMessage { From 9d6d40ea01a504e3938079078b8e98b8a9e9faf8 Mon Sep 17 00:00:00 2001 From: Alonso Date: Thu, 11 Jul 2024 22:04:45 -0400 Subject: [PATCH 6/9] feat: added dnssec module --- src/dnssec/dnssec.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/dnssec/dnssec.rs diff --git a/src/dnssec/dnssec.rs b/src/dnssec/dnssec.rs new file mode 100644 index 00000000..fb49a618 --- /dev/null +++ b/src/dnssec/dnssec.rs @@ -0,0 +1,60 @@ +// src/dnssec.rs + +pub mod dnssec { + use super::message::{DnskeyRdata, RrsigRdata, DsRdata, DnsMessage, DnsError}; + use sha2::{Sha256, Sha512, Digest}; + use hmac::{Hmac, Mac, NewMac}; + use rust_crypto::rsa::{RSAPublicKey, RSAVerify}; + use base64::decode; + + pub fn fetch_dnskey_records(domain: &str) -> Result, DnsError> { + // Completar + Ok(vec![DnskeyRdata::new(256, 3, 8, vec![0x03, 0x01, 0x00, 0x01])]) + } + + pub fn verify_rrsig_signature( + rrsig: &RrsigRdata, + dnskey: &DnskeyRdata, + signed_data: &[u8] + ) -> Result { + rsa_verify(&dnskey.public_key, &rrsig.signature, signed_data) + } + + pub fn verify_ds_record( + ds: &DsRdata, + dnskey: &DnskeyRdata + ) -> Result { + let digest = compute_digest(ds.algorithm, &dnskey.to_bytes())?; + Ok(digest == ds.digest) + } + + fn rsa_verify( + public_key: &[u8], + signature: &[u8], + signed_data: &[u8] + ) -> Result { + let public_key = RSAPublicKey::from_der(public_key).map_err(|_| DnsError::VerificationFailed)?; + public_key.verify(signature, signed_data).map_err(|_| DnsError::VerificationFailed)?; + + Ok(true) + } + + fn compute_digest( + algorithm: u8, + data: &[u8] + ) -> Result, DnsError> { + match algorithm { + 1 => { + let mut hasher = Sha256::new(); + hasher.update(data); + Ok(hasher.finalize().to_vec()) + }, + 2 => { + let mut hasher = Sha512::new(); + hasher.update(data); + Ok(hasher.finalize().to_vec()) + }, + _ => Err(DnsError::UnsupportedAlgorithm), + } + } +} From 549c3211e4cb33583de2dbcf3eac2ef7bcdce806 Mon Sep 17 00:00:00 2001 From: Alonso Date: Fri, 12 Jul 2024 02:16:29 -0400 Subject: [PATCH 7/9] feat: added DnsErrors and decrypting --- src/dnssec/dnssec.rs | 78 +++++-------- src/dnssec/dnssec_message_processing.rs | 44 ++----- src/dnssec/rrset_signature.rs | 148 +++++++++++------------- src/message.rs | 12 -- 4 files changed, 108 insertions(+), 174 deletions(-) diff --git a/src/dnssec/dnssec.rs b/src/dnssec/dnssec.rs index fb49a618..a25d22d0 100644 --- a/src/dnssec/dnssec.rs +++ b/src/dnssec/dnssec.rs @@ -1,60 +1,34 @@ -// src/dnssec.rs +use crate::client::ClientUDPConnection; +use crate::message::{DnsMessage, ResourceRecord}; +use crate::dnssec_message_processing::extract_dnssec_records; +use crate::rrset_signature::{verify_rrsig, verify_ds}; +use crate::dnskey_rdata::DnskeyRdata; +use crate::client::client_error::ClientError; +use std::net::IpAddr; +use tokio::time::Duration; -pub mod dnssec { - use super::message::{DnskeyRdata, RrsigRdata, DsRdata, DnsMessage, DnsError}; - use sha2::{Sha256, Sha512, Digest}; - use hmac::{Hmac, Mac, NewMac}; - use rust_crypto::rsa::{RSAPublicKey, RSAVerify}; - use base64::decode; +pub async fn fetch_dnskey_records(domain: &str, server_addr: IpAddr, timeout_duration: Duration) -> Result, ClientError> { + let conn = ClientUDPConnection::new(server_addr, timeout_duration); - pub fn fetch_dnskey_records(domain: &str) -> Result, DnsError> { - // Completar - Ok(vec![DnskeyRdata::new(256, 3, 8, vec![0x03, 0x01, 0x00, 0x01])]) - } - - pub fn verify_rrsig_signature( - rrsig: &RrsigRdata, - dnskey: &DnskeyRdata, - signed_data: &[u8] - ) -> Result { - rsa_verify(&dnskey.public_key, &rrsig.signature, signed_data) - } + let dns_query = DnsMessage::new_query_message( + domain.into(), + Qtype::DNSKEY, + Qclass::IN, + 0, + false, + 1, + ); - pub fn verify_ds_record( - ds: &DsRdata, - dnskey: &DnskeyRdata - ) -> Result { - let digest = compute_digest(ds.algorithm, &dnskey.to_bytes())?; - Ok(digest == ds.digest) - } + let response = conn.send(dns_query).await?; - fn rsa_verify( - public_key: &[u8], - signature: &[u8], - signed_data: &[u8] - ) -> Result { - let public_key = RSAPublicKey::from_der(public_key).map_err(|_| DnsError::VerificationFailed)?; - public_key.verify(signature, signed_data).map_err(|_| DnsError::VerificationFailed)?; + let dns_response = DnsMessage::from_bytes(&response)?; + let mut dnskey_records = Vec::new(); - Ok(true) - } - - fn compute_digest( - algorithm: u8, - data: &[u8] - ) -> Result, DnsError> { - match algorithm { - 1 => { - let mut hasher = Sha256::new(); - hasher.update(data); - Ok(hasher.finalize().to_vec()) - }, - 2 => { - let mut hasher = Sha512::new(); - hasher.update(data); - Ok(hasher.finalize().to_vec()) - }, - _ => Err(DnsError::UnsupportedAlgorithm), + for record in dns_response.get_answer() { + if let Rdata::DNSKEY(dnskey) = &record.get_rdata() { + dnskey_records.push(dnskey.clone()); } } + + Ok(dnskey_records) } diff --git a/src/dnssec/dnssec_message_processing.rs b/src/dnssec/dnssec_message_processing.rs index 17866a15..783e32a6 100644 --- a/src/dnssec/dnssec_message_processing.rs +++ b/src/dnssec/dnssec_message_processing.rs @@ -1,39 +1,19 @@ -use crate::message::DnsMessage; -use crate::message::rdata::{rrsig_rdata, dnskey_rdata, ds_rdata, nsec_rdata, nsec3_rdata}; +use crate::message::{DnsMessage, Rdata, ResourceRecord}; -// DNSKEY, RRSIG, DS | NSEC, NSEC3 ? +pub fn extract_dnssec_records(dns_response: &DnsMessage) -> (Vec, Vec) { + let answers = dns_response.get_answer(); + let additionals = dns_response.get_additional(); -fn extract_dnssec_records(dns_message: &DnsMessage) -> (Vec, Vec, Vec) { let mut dnskey_records = Vec::new(); let mut rrsig_records = Vec::new(); - let mut ds_records = Vec::new(); - for record in &dns_message.additional { - match record.rdata { - Rdata::DNSKEY(ref data) => { - let dnskey_rdata = DnskeyRdata::new(data.flags, data.protocol, data.algorithm, data.public_key.clone()); - dnskey_records.push(dnskey_rdata); - } - Rdata::RRSIG(ref data) => { - let rrsig_rdata = RrsigRdata::new( - data.type_covered, - data.algorithm, - data.labels, - data.original_ttl, - //datatime? expiration/inception - data.key_tag, - data.signer_name.clone(), - data.signature.clone() - ); - rrsig_records.push(rrsig_rdata); - } - Rdata::DS(ref data) => { - let ds_rdata = DsRdata::new(data.key_tag, data.algorithm, data.digest_type, data.digest.clone() - ); - ds_records.push(ds_rdata); - }, - _ => (), + for record in answers.iter().chain(additionals.iter()) { + match record.get_rdata() { + Rdata::DNSKEY(_) => dnskey_records.push(record.clone()), + Rdata::RRSIG(_) => rrsig_records.push(record.clone()), + _ => {} } } - (dnskey_records, rrsig_records, ds_records) -} \ No newline at end of file + + (dnskey_records, rrsig_records) +} diff --git a/src/dnssec/rrset_signature.rs b/src/dnssec/rrset_signature.rs index d230790c..ff13c55a 100644 --- a/src/dnssec/rrset_signature.rs +++ b/src/dnssec/rrset_signature.rs @@ -1,87 +1,79 @@ -use crypto::digest::Digest; -use crypto::sha1::Sha1; -use crypto::sha2::Sha256; -use crypto::rsa::Rsa; -use crate::dnssec::RRset; -use crate::dnskey_rdata::DnskeyRdata; -use crate::rrsig_rdata::RRSIGRdata; -use base64; +use sha2::{Sha256, Digest}; +use rust_crypto::digest::Digest as RustDigest; +use rust_crypto::sha1::Sha1; +use base64::encode; +use crate::message::rdata::{DnskeyRdata, RrsigRdata, Rdata}; +use crate::message::resource_record::ResourceRecord; +use crate::client::client_error::ClientError; -/// RFCs: [4033, 4034, 4035, 4509] +pub fn verify_rrsig(rrsig: &RrsigRdata, dnskey: &DnskeyRdata, rrset: &[ResourceRecord]) -> Result { + let mut rrsig_data = Vec::new(); + rrsig_data.extend_from_slice(&rrsig.type_covered.to_be_bytes()); + rrsig_data.push(rrsig.algorithm); + rrsig_data.push(rrsig.labels); + rrsig_data.extend_from_slice(&rrsig.original_ttl.to_be_bytes()); + rrsig_data.extend_from_slice(&rrsig.expiration.to_be_bytes()); + rrsig_data.extend_from_slice(&rrsig.inception.to_be_bytes()); + rrsig_data.extend_from_slice(&rrsig.key_tag.to_be_bytes()); + rrsig_data.extend_from_slice(rrsig.signer_name.to_bytes()?); -/// Signs a RRset using the private_key given. -/// Returns a RRSIG that contains the signature. -pub fn sign_rrset(rrset: &RRset, private_key: &Rsa, algorithm: u8) -> Result { - let rrset_bytes = rrset.to_bytes(); - - let mut hasher: Box = match algorithm { - 1 => Box::new(Sha1::new()), - 2 => Box::new(Sha256::new()), - _ => return Err("Algorithm not supported"), - }; - - hasher.input(&rrset_bytes); - let hash = hasher.result_str(); - - let signature = private_key.sign(hasher, &hash.as_bytes()).map_err(|_| "Error while signing")?; - - let rrsig = RRSIGRdata { - type_covered: rrset.get_type(), - algorithm, - labels: rrset.get_labels(), - original_ttl: rrset.get_ttl(), - signature_expiration: get_expiration_time(), - signature_inception: get_inception_time(), - key_tag: calculate_key_tag(private_key), - signer_name: rrset.get_name().clone(), - signature: base64::encode(&signature), - }; - - Ok(rrsig) -} + let mut rrset_sorted = rrset.to_vec(); + rrset_sorted.sort_by(|a, b| a.name.cmp(&b.name)); -// Gets the expiration time for the signature. -fn get_expiration_time() -> u32 { - // Supposing sign validity = 1 day (86400 seconds) - let now = std::time::SystemTime::now(); - let expiration_duration = std::time::Duration::new(86400, 0); - let expiration_time = now + expiration_duration; - expiration_time.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 -} + for rr in rrset_sorted.iter() { + rrsig_data.extend_from_slice(rr.name.to_bytes()?); + rrsig_data.extend_from_slice(&rr.ttl.to_be_bytes()); + rrsig_data.extend_from_slice(&(rr.rdata.to_bytes().len() as u16).to_be_bytes()); + rrsig_data.extend_from_slice(&rr.rdata.to_bytes()?); + } -// Gets the inception time for the signature. -fn get_inception_time() -> u32 { - // Assuming current time - let now = std::time::SystemTime::now(); - now.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as u32 -} + let signature = rrsig.signature.clone(); + let mut hasher = Sha256::new(); + hasher.update(rrsig_data); + let hashed = hasher.finalize(); -// Calculates the key tag for the public key. -fn calculate_key_tag(private_key: &Rsa) -> u16 { - let public_key_der = private_key.to_public_key_der().unwrap(); - let mut hasher = Sha1::new(); - hasher.input(&public_key_der); - let hash = hasher.result_str(); - u16::from_be_bytes([hash.as_bytes()[18], hash.as_bytes()[19]]) + match dnskey.algorithm { + 3 => { + //DSA/SHA1 + let mut sha1 = Sha1::new(); + sha1.input(&rrsig_data); + let digest = sha1.result_str(); + Ok(digest == encode(&signature)) + }, + 5 => { + //RSA/SHA1 + let mut sha1 = Sha1::new(); + sha1.input(&rrsig_data); + let digest = sha1.result_str(); + Ok(digest == encode(&signature)) + }, + 8 => { + //RSA/SHA256 + let hashed = Sha256::digest(&rrsig_data); + Ok(encode(&hashed) == encode(&signature)) + }, + _ => Err(ClientError::new("Unknown DNSKEY algorithm")), + } } -/// RFCs: [4033, 4034, 4035, 5702] +pub fn verify_ds(ds_record: &ResourceRecord, dnskey: &DnskeyRdata) -> Result { + if let Rdata::DS(ds_rdata) = &ds_record.get_rdata() { + let dnskey_bytes = dnskey.to_bytes()?; + let hashed_key = match ds_rdata.algorithm { + 1 => { + let mut hasher = Sha1::new(); + hasher.input(&dnskey_bytes); + hasher.result_str() + }, + 2 => { + let hashed = Sha256::digest(&dnskey_bytes); + encode(&hashed) + }, + _ => return Err(ClientError::new("Unknown DS algorithm")), + }; -/// Verifies an RRset using the provided public key and RRSIG record. -/// Returns true if the verification is successful. -pub fn verify_rrset(rrset: &RRset, rrsig: &RRSIGRdata, public_key: &Rsa) -> Result { - let rrset_bytes = rrset.to_bytes(); - - let mut hasher: Box = match rrsig.algorithm { - 1 => Box::new(Sha1::new()), - 2 => Box::new(Sha256::new()), - _ => return Err("Algorithm not supported"), - }; - - hasher.input(&rrset_bytes); - let hash = hasher.result_str(); - - let signature = base64::decode(&rrsig.signature).map_err(|_| "Error while decoding signature")?; - - public_key.verify(hasher, &hash.as_bytes(), &signature).map_err(|_| "Verification failed") + Ok(ds_rdata.digest == hashed_key) + } else { + Err(ClientError::new("Provided record is not a DS record")) + } } diff --git a/src/message.rs b/src/message.rs index 7f2e3f6f..b6b20fc9 100644 --- a/src/message.rs +++ b/src/message.rs @@ -894,18 +894,6 @@ impl DnsMessage { } } - pub fn extract_dnssec_records(&self) -> Vec { - let mut dnssec_records = Vec::new(); - - for record in self.additional.iter() { - if let Rdata::DNSKEY(dnskey) = &record.get_rdata() { - dnssec_records.push(dnskey.clone()); - } - } - - dnssec_records - } - } impl fmt::Display for DnsMessage { From 42e435b96f808b7b7b008e0a404daded06dcc135 Mon Sep 17 00:00:00 2001 From: Alonso Date: Fri, 12 Jul 2024 10:21:42 -0400 Subject: [PATCH 8/9] fix: deleted unused files --- src/dnssec/dnssec_decryption.rs | 0 src/dnssec/dnssec_encryption.rs | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/dnssec/dnssec_decryption.rs delete mode 100644 src/dnssec/dnssec_encryption.rs diff --git a/src/dnssec/dnssec_decryption.rs b/src/dnssec/dnssec_decryption.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/src/dnssec/dnssec_encryption.rs b/src/dnssec/dnssec_encryption.rs deleted file mode 100644 index e69de29b..00000000 From 51104d5d344402e23d65a98ba2c6989223f0f97d Mon Sep 17 00:00:00 2001 From: Alonso Date: Sun, 14 Jul 2024 18:20:59 -0400 Subject: [PATCH 9/9] fix: rrset_signature --- src/dnssec/dnssec.rs | 23 +++-------------------- src/dnssec/rrset_signature.rs | 18 ++++-------------- 2 files changed, 7 insertions(+), 34 deletions(-) diff --git a/src/dnssec/dnssec.rs b/src/dnssec/dnssec.rs index a25d22d0..899bf857 100644 --- a/src/dnssec/dnssec.rs +++ b/src/dnssec/dnssec.rs @@ -1,27 +1,10 @@ -use crate::client::ClientUDPConnection; -use crate::message::{DnsMessage, ResourceRecord}; +use crate::message::{DnsMessage, Rdata, ResourceRecord}; use crate::dnssec_message_processing::extract_dnssec_records; use crate::rrset_signature::{verify_rrsig, verify_ds}; -use crate::dnskey_rdata::DnskeyRdata; +use crate::message::rdata::DnskeyRdata; use crate::client::client_error::ClientError; -use std::net::IpAddr; -use tokio::time::Duration; -pub async fn fetch_dnskey_records(domain: &str, server_addr: IpAddr, timeout_duration: Duration) -> Result, ClientError> { - let conn = ClientUDPConnection::new(server_addr, timeout_duration); - - let dns_query = DnsMessage::new_query_message( - domain.into(), - Qtype::DNSKEY, - Qclass::IN, - 0, - false, - 1, - ); - - let response = conn.send(dns_query).await?; - - let dns_response = DnsMessage::from_bytes(&response)?; +pub async fn fetch_dnskey_records(dns_response: &DnsMessage) -> Result, ClientError> { let mut dnskey_records = Vec::new(); for record in dns_response.get_answer() { diff --git a/src/dnssec/rrset_signature.rs b/src/dnssec/rrset_signature.rs index ff13c55a..25cd1669 100644 --- a/src/dnssec/rrset_signature.rs +++ b/src/dnssec/rrset_signature.rs @@ -28,28 +28,18 @@ pub fn verify_rrsig(rrsig: &RrsigRdata, dnskey: &DnskeyRdata, rrset: &[ResourceR } let signature = rrsig.signature.clone(); - let mut hasher = Sha256::new(); - hasher.update(rrsig_data); - let hashed = hasher.finalize(); + let hashed = Sha256::digest(&rrsig_data); match dnskey.algorithm { - 3 => { - //DSA/SHA1 - let mut sha1 = Sha1::new(); - sha1.input(&rrsig_data); - let digest = sha1.result_str(); - Ok(digest == encode(&signature)) - }, - 5 => { - //RSA/SHA1 + 3 | 5 => { + // (DSA/RSA)/SHA1 let mut sha1 = Sha1::new(); sha1.input(&rrsig_data); let digest = sha1.result_str(); Ok(digest == encode(&signature)) }, 8 => { - //RSA/SHA256 - let hashed = Sha256::digest(&rrsig_data); + // RSA/SHA256 Ok(encode(&hashed) == encode(&signature)) }, _ => Err(ClientError::new("Unknown DNSKEY algorithm")),