handling key submission from client and responding with server public key
This commit is contained in:
parent
328c011109
commit
6e954a9795
43
dnstp/src/clients.rs
Normal file
43
dnstp/src/clients.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
use aes_gcm_siv::Aes256GcmSiv;
|
||||||
|
|
||||||
|
pub struct Client {
|
||||||
|
pub first_seen: SystemTime,
|
||||||
|
pub shared_key: Aes256GcmSiv
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Client {
|
||||||
|
|
||||||
|
pub fn new(shared_key: Aes256GcmSiv) -> Client
|
||||||
|
{
|
||||||
|
Client {
|
||||||
|
first_seen: SystemTime::now(),
|
||||||
|
shared_key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Clients {
|
||||||
|
client_map: HashMap<String, Client>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clients {
|
||||||
|
|
||||||
|
pub fn new() -> Clients
|
||||||
|
{
|
||||||
|
Clients {
|
||||||
|
client_map: HashMap::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn add_from(&mut self, client_id: String, shared_key: Aes256GcmSiv)
|
||||||
|
// {
|
||||||
|
// self.client_map.insert(client_id, Client::new(shared_key));
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn add(&mut self, client_id: String, client:Client)
|
||||||
|
{
|
||||||
|
self.client_map.insert(client_id, client);
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,7 @@
|
|||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use p256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret, NistP256};
|
use p256::{PublicKey, ecdh::EphemeralSecret, NistP256};
|
||||||
use p256::elliptic_curve::ecdh::SharedSecret;
|
use p256::elliptic_curve::ecdh::SharedSecret;
|
||||||
use aes_gcm_siv::{aead::{Aead, KeyInit}, AeadCore, Aes256GcmSiv, Nonce};
|
use aes_gcm_siv::{aead::{Aead, KeyInit}, AeadCore, Aes256GcmSiv, Nonce};
|
||||||
|
|
||||||
|
@ -7,8 +7,9 @@ mod byte;
|
|||||||
pub mod processor;
|
pub mod processor;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
pub mod net;
|
pub mod net;
|
||||||
mod string;
|
pub mod string;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
|
mod clients;
|
||||||
|
|
||||||
pub use config::DomainConfig;
|
pub use config::DomainConfig;
|
@ -75,18 +75,18 @@ impl DNSMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_resp_from_request(request: &DNSMessage, ip: impl Fn(&DNSQuestion) -> Ipv4Addr) -> DNSMessage
|
pub fn a_resp_from_request(&self, ip: impl Fn(&DNSQuestion) -> Ipv4Addr) -> DNSMessage
|
||||||
{
|
{
|
||||||
let mut response = DNSMessage{
|
let mut response = DNSMessage{
|
||||||
header: request.header.clone(),
|
header: self.header.clone(),
|
||||||
questions: request.questions.clone(),
|
questions: self.questions.clone(),
|
||||||
answer_records: vec![],
|
answer_records: vec![],
|
||||||
authority_records: vec![],
|
authority_records: vec![],
|
||||||
additional_records: vec![],
|
additional_records: vec![],
|
||||||
peer: request.peer
|
peer: self.peer
|
||||||
};
|
};
|
||||||
|
|
||||||
response.answer_records = request.questions
|
response.answer_records = self.questions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x|
|
.map(|x|
|
||||||
ResourceRecord::from_query(x,
|
ResourceRecord::from_query(x,
|
||||||
@ -107,4 +107,28 @@ impl DNSMessage {
|
|||||||
|
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn empty_resp_from_request(&self) -> DNSMessage
|
||||||
|
{
|
||||||
|
let mut response = DNSMessage{
|
||||||
|
header: self.header.clone(),
|
||||||
|
questions: self.questions.clone(),
|
||||||
|
answer_records: vec![],
|
||||||
|
authority_records: vec![],
|
||||||
|
additional_records: vec![],
|
||||||
|
peer: self.peer
|
||||||
|
};
|
||||||
|
|
||||||
|
response.header.direction = Direction::Response;
|
||||||
|
response.header.response = ResponseCode::NoError;
|
||||||
|
response.header.answer_record_count = 0;
|
||||||
|
response.header.authority_record_count = 0;
|
||||||
|
response.header.additional_record_count = 0;
|
||||||
|
|
||||||
|
if response.header.recursion_desired {
|
||||||
|
response.header.recursion_available = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
response
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
use urlencoding::decode;
|
use urlencoding::decode;
|
||||||
use crate::byte::{push_split_bytes, two_byte_combine};
|
use crate::byte::{push_split_bytes, two_byte_combine};
|
||||||
use crate::string::encode_domain_name;
|
use crate::string::encode_domain_name;
|
||||||
@ -25,6 +26,28 @@ pub enum QType {
|
|||||||
ANY = 255,
|
ANY = 255,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for QType {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
QType::A => write!(f, "A"),
|
||||||
|
QType::NS => write!(f, "NS"),
|
||||||
|
QType::CNAME => write!(f, "CNAME"),
|
||||||
|
QType::SOA => write!(f, "SOA"),
|
||||||
|
QType::WKS => write!(f, "WKS"),
|
||||||
|
QType::PTR => write!(f, "PTR"),
|
||||||
|
QType::HINFO => write!(f, "HINFO"),
|
||||||
|
QType::MINFO => write!(f, "MINFO"),
|
||||||
|
QType::MX => write!(f, "MX"),
|
||||||
|
QType::TXT => write!(f, "TXT"),
|
||||||
|
QType::RP => write!(f, "RP"),
|
||||||
|
QType::AAAA => write!(f, "AAAA"),
|
||||||
|
QType::SRV => write!(f, "SRV"),
|
||||||
|
QType::OPT => write!(f, "OPT"),
|
||||||
|
QType::ANY => write!(f, "ANY"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<u16> for QType {
|
impl TryFrom<u16> for QType {
|
||||||
type Error = u16;
|
type Error = u16;
|
||||||
|
|
||||||
|
30
dnstp/src/message/record/cname_rdata.rs
Normal file
30
dnstp/src/message/record/cname_rdata.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use std::fmt::{Debug, Formatter};
|
||||||
|
use crate::message::record::RData;
|
||||||
|
use crate::string::encode_domain_name;
|
||||||
|
|
||||||
|
pub struct CnameRdata {
|
||||||
|
pub rdata: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for CnameRdata {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("CNAME")
|
||||||
|
.field("Host", &self.rdata)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RData for CnameRdata {
|
||||||
|
fn to_bytes(&self) -> Vec<u8> {
|
||||||
|
encode_domain_name(&self.rdata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CnameRdata {
|
||||||
|
pub fn from(rdata: String) -> CnameRdata
|
||||||
|
{
|
||||||
|
CnameRdata {
|
||||||
|
rdata
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,8 @@ pub use aaaa_rdata::AAAARdata;
|
|||||||
mod txt_rdata;
|
mod txt_rdata;
|
||||||
pub use txt_rdata::TXTRdata;
|
pub use txt_rdata::TXTRdata;
|
||||||
|
|
||||||
|
mod cname_rdata;
|
||||||
|
pub use cname_rdata::CnameRdata;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
@ -1,16 +1,112 @@
|
|||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use p256::ecdh::EphemeralSecret;
|
use p256::ecdh::EphemeralSecret;
|
||||||
use crate::crypto::{get_random_asym_pair, trim_public_key};
|
use crate::clients::Client;
|
||||||
use crate::message::DNSMessage;
|
use crate::crypto::{asym_to_sym_key, fatten_public_key, get_random_asym_pair, get_shared_asym_secret, trim_public_key};
|
||||||
|
use crate::message::{ARdata, DNSMessage, DNSQuestion, QClass, QType, ResourceRecord};
|
||||||
|
use crate::message::record::CnameRdata;
|
||||||
|
use crate::string::{append_base_domain_to_key, strip_base_domain_from_key};
|
||||||
|
|
||||||
pub fn get_key_response(request: DNSMessage) -> DNSMessage
|
pub struct KeySwapContext {
|
||||||
{
|
pub new_client: Client,
|
||||||
DNSMessage::a_resp_from_request(&request, |_| Ipv4Addr::from([127, 0, 0, 1]))
|
pub response: DNSMessage,
|
||||||
|
pub server_public: String,
|
||||||
|
pub client_public: String
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_key_request_with_base_domain(base_domain: String) -> (EphemeralSecret, String)
|
pub fn get_key_request_with_base_domain(base_domain: String) -> (EphemeralSecret, String)
|
||||||
{
|
{
|
||||||
let (private, public) = get_random_asym_pair();
|
let (private, public) = get_random_asym_pair();
|
||||||
|
|
||||||
(private, vec![trim_public_key(&public), base_domain].join("."))
|
(private, append_base_domain_to_key(trim_public_key(&public), &base_domain))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_fattened_public_key(key_question: &DNSQuestion) -> (String, String)
|
||||||
|
{
|
||||||
|
let public_key = &key_question.qname;
|
||||||
|
let (trimmed_public_key, base_domain) = strip_base_domain_from_key(public_key);
|
||||||
|
|
||||||
|
(fatten_public_key(&trimmed_public_key), base_domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Copy, Clone)]
|
||||||
|
pub enum KeyDecodeError {
|
||||||
|
QuestionCount(usize),
|
||||||
|
FirstQuestionNotA(QType),
|
||||||
|
SecondQuestionNotA(QType),
|
||||||
|
SharedSecretDerivation,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_key_request(message: DNSMessage) -> Result<KeySwapContext, KeyDecodeError>
|
||||||
|
{
|
||||||
|
if message.questions.len() == 2 {
|
||||||
|
|
||||||
|
if message.questions[0].qtype != QType::A
|
||||||
|
{
|
||||||
|
return Err(KeyDecodeError::FirstQuestionNotA(message.questions[0].qtype));
|
||||||
|
}
|
||||||
|
|
||||||
|
let key_question = &message.questions[1];
|
||||||
|
|
||||||
|
if key_question.qtype != QType::A
|
||||||
|
{
|
||||||
|
return Err(KeyDecodeError::SecondQuestionNotA(key_question.qtype));
|
||||||
|
}
|
||||||
|
|
||||||
|
let (fattened_public_key, base_domain) = get_fattened_public_key(&key_question);
|
||||||
|
let (server_private, server_public) = get_random_asym_pair();
|
||||||
|
|
||||||
|
let shared_secret = get_shared_asym_secret(server_private, fattened_public_key);
|
||||||
|
|
||||||
|
match shared_secret {
|
||||||
|
Ok(secret) => {
|
||||||
|
|
||||||
|
let sym_key = asym_to_sym_key(&secret);
|
||||||
|
let new_client = Client::new(sym_key);
|
||||||
|
let mut response = message.empty_resp_from_request();
|
||||||
|
|
||||||
|
let first_record = ResourceRecord {
|
||||||
|
name_offset: 12,
|
||||||
|
answer_type: QType::A,
|
||||||
|
class: QClass::Internet,
|
||||||
|
ttl: 0,
|
||||||
|
rd_length: 4,
|
||||||
|
r_data: Box::new(ARdata::from(Ipv4Addr::from([127,0,0,1])))
|
||||||
|
};
|
||||||
|
|
||||||
|
let second_record = ResourceRecord {
|
||||||
|
name_offset: 12 + (&message.questions[0]).to_bytes().len() as u16,
|
||||||
|
answer_type: QType::CNAME,
|
||||||
|
class: QClass::Internet,
|
||||||
|
ttl: 0,
|
||||||
|
rd_length: 4,
|
||||||
|
r_data: Box::new(
|
||||||
|
CnameRdata::from(
|
||||||
|
append_base_domain_to_key(
|
||||||
|
trim_public_key(&server_public),
|
||||||
|
&base_domain
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
response.answer_records = vec![
|
||||||
|
first_record, second_record
|
||||||
|
];
|
||||||
|
|
||||||
|
return Ok(KeySwapContext {
|
||||||
|
new_client,
|
||||||
|
response,
|
||||||
|
server_public,
|
||||||
|
client_public: key_question.qname.to_string()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
return Err(KeyDecodeError::SharedSecretDerivation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Err(KeyDecodeError::QuestionCount(message.questions.len()));
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,14 +1,16 @@
|
|||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::sync::mpsc;
|
use std::sync::{Arc, mpsc, Mutex};
|
||||||
use std::sync::mpsc::{Receiver, Sender};
|
use std::sync::mpsc::{Receiver, Sender};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use log::info;
|
use log::{error, info};
|
||||||
|
use crate::clients::Clients;
|
||||||
use crate::config::DomainConfig;
|
use crate::config::DomainConfig;
|
||||||
|
|
||||||
use crate::message::DNSMessage;
|
use crate::message::DNSMessage;
|
||||||
use crate::net::{NetworkMessage, NetworkMessagePtr};
|
use crate::net::{NetworkMessage, NetworkMessagePtr};
|
||||||
use crate::message_parser::parse_message;
|
use crate::message_parser::parse_message;
|
||||||
use crate::processor::print_error;
|
use crate::processor::print_error;
|
||||||
|
use crate::processor::request::encryption::{decode_key_request, KeyDecodeError};
|
||||||
|
|
||||||
pub mod encryption;
|
pub mod encryption;
|
||||||
|
|
||||||
@ -18,7 +20,9 @@ mod tests;
|
|||||||
pub struct RequestProcesor {
|
pub struct RequestProcesor {
|
||||||
message_channel: Option<Sender<NetworkMessagePtr>>,
|
message_channel: Option<Sender<NetworkMessagePtr>>,
|
||||||
domain_config: DomainConfig,
|
domain_config: DomainConfig,
|
||||||
encryption_endpoint: String
|
encryption_endpoint: String,
|
||||||
|
|
||||||
|
clients: Arc<Mutex<Clients>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RequestProcesor {
|
impl RequestProcesor {
|
||||||
@ -28,7 +32,8 @@ impl RequestProcesor {
|
|||||||
RequestProcesor {
|
RequestProcesor {
|
||||||
message_channel: None,
|
message_channel: None,
|
||||||
domain_config,
|
domain_config,
|
||||||
encryption_endpoint: fq_key_endpoint
|
encryption_endpoint: fq_key_endpoint,
|
||||||
|
clients: Arc::new(Mutex::new(Clients::new()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,13 +44,13 @@ impl RequestProcesor {
|
|||||||
|
|
||||||
let mut base_domain_equality = self.domain_config.base_domain.clone();
|
let mut base_domain_equality = self.domain_config.base_domain.clone();
|
||||||
base_domain_equality.insert_str(0, ".");
|
base_domain_equality.insert_str(0, ".");
|
||||||
let base_domain_len = base_domain_equality.len() + 1;
|
|
||||||
|
|
||||||
let fq_key_endpoint = self.encryption_endpoint.clone();
|
let fq_key_endpoint = self.encryption_endpoint.clone();
|
||||||
|
let clients = self.clients.clone();
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
|
|
||||||
// let fq_key_endpoint = fq_key_endpoint;
|
let clients = clients;
|
||||||
|
|
||||||
for m in rx
|
for m in rx
|
||||||
{
|
{
|
||||||
@ -61,7 +66,36 @@ impl RequestProcesor {
|
|||||||
{
|
{
|
||||||
info!("[{}] received encryption key request", peer);
|
info!("[{}] received encryption key request", peer);
|
||||||
|
|
||||||
|
match decode_key_request(r)
|
||||||
|
{
|
||||||
|
Ok(context) => {
|
||||||
|
|
||||||
|
clients.lock().unwrap().add(context.client_public, context.new_client);
|
||||||
|
|
||||||
|
sending_channel.send(Box::new(
|
||||||
|
NetworkMessage {
|
||||||
|
buffer: Box::new(context.response.to_bytes()),
|
||||||
|
peer: context.response.peer
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
match e {
|
||||||
|
KeyDecodeError::QuestionCount(qc) => {
|
||||||
|
error!("[{}] failed to parse public key, wrong question count [{}]", peer, qc);
|
||||||
|
}
|
||||||
|
KeyDecodeError::FirstQuestionNotA(qtype) => {
|
||||||
|
error!("[{}] failed to parse public key, first question wasn't an A request [{}]", peer, qtype);
|
||||||
|
}
|
||||||
|
KeyDecodeError::SecondQuestionNotA(qtype) => {
|
||||||
|
error!("[{}] failed to parse public key, second question wasn't an A request [{}]", peer, qtype);
|
||||||
|
}
|
||||||
|
KeyDecodeError::SharedSecretDerivation => {
|
||||||
|
error!("[{}] failed to parse public key, failed to derived shared secret", peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::sync::mpsc::{Receiver, Sender};
|
use std::sync::mpsc::{Receiver, Sender};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use log::{error, info};
|
use log::info;
|
||||||
use crate::message::{QuestionParseError, RecordParseError};
|
|
||||||
use crate::net::raw_request::NetworkMessagePtr;
|
use crate::net::raw_request::NetworkMessagePtr;
|
||||||
use crate::message_parser::{HeaderParseError, parse_message, MessageParseError};
|
use crate::message_parser::parse_message;
|
||||||
use crate::processor::print_error;
|
use crate::processor::print_error;
|
||||||
|
|
||||||
pub struct ResponseProcesor {
|
pub struct ResponseProcesor {
|
||||||
@ -25,7 +24,7 @@ impl ResponseProcesor {
|
|||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
|
|
||||||
for mut m in rx
|
for m in rx
|
||||||
{
|
{
|
||||||
let peer = m.peer.clone();
|
let peer = m.peer.clone();
|
||||||
|
|
||||||
|
@ -21,3 +21,25 @@ pub fn encode_domain_name(name: &String) -> Vec<u8>
|
|||||||
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn strip_base_domain_from_key(public_key: &String) -> (String, String)
|
||||||
|
{
|
||||||
|
let periods: Vec<_> = public_key.rmatch_indices(".").collect();
|
||||||
|
|
||||||
|
if periods.len() >= 2 {
|
||||||
|
(public_key[0 .. periods[1].0].to_string(),
|
||||||
|
public_key[periods[1].0 .. ].to_string())
|
||||||
|
}
|
||||||
|
else if periods.len() == 1 {
|
||||||
|
(public_key[0 .. periods[0].0].to_string(),
|
||||||
|
public_key[periods[0].0 .. ].to_string())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
(public_key.to_string(), String::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_base_domain_to_key(trimmed_key: String, base_domain: &String) -> String
|
||||||
|
{
|
||||||
|
vec![trimmed_key, base_domain.to_string()].join(".")
|
||||||
|
}
|
75
dnstp/tests/key_swap.rs
Normal file
75
dnstp/tests/key_swap.rs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||||
|
use dnstplib::crypto::{asym_to_sym_key, decrypt, encrypt, generate_aes_nonce, get_random_asym_pair, get_shared_asym_secret, trim_public_key};
|
||||||
|
use dnstplib::message::{DNSHeader, DNSMessage, DNSQuestion};
|
||||||
|
use dnstplib::message::QClass::Internet;
|
||||||
|
use dnstplib::message::QType::A;
|
||||||
|
use dnstplib::processor::request::encryption::decode_key_request;
|
||||||
|
use dnstplib::string::append_base_domain_to_key;
|
||||||
|
#[test]
|
||||||
|
fn test_key_swap()
|
||||||
|
{
|
||||||
|
////////////
|
||||||
|
// CLIENT
|
||||||
|
////////////
|
||||||
|
|
||||||
|
// generate pair
|
||||||
|
let (client_private, client_public) = get_random_asym_pair();
|
||||||
|
|
||||||
|
// generate public key submission domain
|
||||||
|
let serialised_client_public = append_base_domain_to_key(
|
||||||
|
trim_public_key(&client_public),
|
||||||
|
&"sarsoo.xyz".to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
let message = DNSMessage {
|
||||||
|
header: DNSHeader::new_request(1, Some(1)),
|
||||||
|
questions: vec![
|
||||||
|
DNSQuestion {
|
||||||
|
qname: "static.sarsoo.xyz".to_string(),
|
||||||
|
qtype: A,
|
||||||
|
qclass: Internet
|
||||||
|
},
|
||||||
|
DNSQuestion {
|
||||||
|
qname: serialised_client_public,
|
||||||
|
qtype: A,
|
||||||
|
qclass: Internet
|
||||||
|
}
|
||||||
|
],
|
||||||
|
answer_records: vec![],
|
||||||
|
authority_records: vec![],
|
||||||
|
additional_records: vec![],
|
||||||
|
peer: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from([127,0,0,1]), 5000)),
|
||||||
|
};
|
||||||
|
|
||||||
|
/////////////////
|
||||||
|
// SERVER
|
||||||
|
/////////////////
|
||||||
|
|
||||||
|
// handle message "received by client"
|
||||||
|
let resp = decode_key_request(message).unwrap();
|
||||||
|
|
||||||
|
////////////
|
||||||
|
// CLIENT
|
||||||
|
////////////
|
||||||
|
|
||||||
|
// client has received message from above and constructs shared secret
|
||||||
|
let shared_secret_client = asym_to_sym_key(&get_shared_asym_secret(client_private, resp.server_public).unwrap());
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
// TEST ENCRYPTION/DECRYPTION
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
let nonce = generate_aes_nonce();
|
||||||
|
let payload = "hello world!".to_string();
|
||||||
|
|
||||||
|
// CLIENT encrypts something
|
||||||
|
let encrypted = encrypt(&shared_secret_client, &nonce, &payload.clone().into_bytes()).unwrap();
|
||||||
|
|
||||||
|
// SERVER decrypts it
|
||||||
|
let decrypted = decrypt(&resp.new_client.shared_key, &nonce, &encrypted).unwrap();
|
||||||
|
|
||||||
|
let decrypted_payload = String::from_utf8(decrypted).unwrap();
|
||||||
|
|
||||||
|
// is it the same?
|
||||||
|
assert_eq!(payload, decrypted_payload);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user