Skip to content

Commit

Permalink
Add handshake decryption
Browse files Browse the repository at this point in the history
  • Loading branch information
hacker-volodya committed Feb 15, 2024
1 parent eb5a6fe commit dc13883
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 17 deletions.
9 changes: 9 additions & 0 deletions src/helper_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,15 @@ pub trait AdnlPrivateKey {
pub struct AdnlSecret([u8; 32]);

/// Wrapper struct to hold ADNL address, which is a hash of public key
#[derive(PartialEq)]
pub struct AdnlAddress([u8; 32]);

impl From<[u8; 32]> for AdnlAddress {
fn from(value: [u8; 32]) -> Self {
Self(value)
}
}

/// Session parameters for AES-CTR encryption of datagrams
pub struct AdnlAesParams {
rx_key: [u8; 32],
Expand Down Expand Up @@ -161,6 +168,8 @@ pub enum AdnlError {
TooShortPacket,
#[error("Incorrect ip address")]
IncorrectAddr(AddrParseError),
#[error("Receiver ADNL address mismatch")]
AddrMismatch,
#[error(transparent)]
OtherError(#[from] Error),
}
71 changes: 54 additions & 17 deletions src/primitives/handshake.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::primitives::AdnlAes;
use crate::{AdnlAddress, AdnlAesParams, AdnlClient, AdnlError, AdnlPublicKey, AdnlSecret};
use crate::{AdnlAddress, AdnlAesParams, AdnlClient, AdnlError, AdnlPrivateKey, AdnlPublicKey, AdnlSecret};
use aes::cipher::KeyIvInit;
use ctr::cipher::StreamCipher;
use sha2::{Digest, Sha256};
Expand Down Expand Up @@ -37,25 +37,14 @@ impl<P: AdnlPublicKey> AdnlHandshake<P> {

/// Serialize handshake to send it over the transport
pub fn to_bytes(&self) -> [u8; 256] {
let mut packet = [0u8; 256];
packet[..32].copy_from_slice(self.receiver.as_bytes());
packet[32..64].copy_from_slice(&self.sender.to_bytes());

let mut raw_params = self.aes_params.to_bytes();
let mut hasher = Sha256::new();
hasher.update(raw_params);
let hash: [u8; 32] = hasher.finalize().into();

let mut key = [0u8; 32];
key[..16].copy_from_slice(&self.secret.as_bytes()[..16]);
key[16..32].copy_from_slice(&hash[16..32]);
let mut nonce = [0u8; 16];
nonce[..4].copy_from_slice(&hash[..4]);
nonce[4..16].copy_from_slice(&self.secret.as_bytes()[20..32]);

let mut aes = AdnlAes::new(key.as_slice().into(), nonce.as_slice().into());
let hash = Self::sha256(raw_params);
let mut aes = Self::initialize_aes(&self.secret, &hash);
aes.apply_keystream(&mut raw_params);

let mut packet = [0u8; 256];
packet[..32].copy_from_slice(self.receiver.as_bytes());
packet[32..64].copy_from_slice(&self.sender.to_bytes());
packet[64..96].copy_from_slice(&hash);
packet[96..256].copy_from_slice(&raw_params);
packet
Expand All @@ -68,4 +57,52 @@ impl<P: AdnlPublicKey> AdnlHandshake<P> {
) -> Result<AdnlClient<T>, AdnlError> {
AdnlClient::perform_handshake(transport, self).await
}

fn initialize_aes(secret: &AdnlSecret, hash: &[u8]) -> AdnlAes {
let mut key = [0u8; 32];
key[..16].copy_from_slice(&secret.as_bytes()[..16]);
key[16..32].copy_from_slice(&hash[16..32]);

let mut nonce = [0u8; 16];
nonce[..4].copy_from_slice(&hash[..4]);
nonce[4..16].copy_from_slice(&secret.as_bytes()[20..32]);

AdnlAes::new(key.as_slice().into(), nonce.as_slice().into())
}

fn sha256(data: impl AsRef<[u8]>) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(data);
hasher.finalize().into()
}
}

impl AdnlHandshake<[u8; 32]> {
/// Deserialize and decrypt handshake
pub fn decrypt_from_raw<S: AdnlPrivateKey>(packet: [u8; 256], key: S) -> Result<Self, AdnlError> {
let receiver: [u8; 32] = packet[..32].try_into().unwrap();
let receiver = AdnlAddress::from(receiver);
let sender = packet[32..64].try_into().unwrap();
let hash: [u8; 32] = packet[64..96].try_into().unwrap();
let mut raw_params: [u8; 160] = packet[96..256].try_into().unwrap();

if key.public().address() != receiver {
return Err(AdnlError::AddrMismatch)
}

let secret = key.key_agreement(sender);
let mut aes = Self::initialize_aes(&secret, &hash);
aes.apply_keystream(&mut raw_params);

if hash != Self::sha256(raw_params) {
return Err(AdnlError::IntegrityError)
}

Ok(Self {
receiver,
sender,
aes_params: AdnlAesParams::from(raw_params),
secret,
})
}
}

0 comments on commit dc13883

Please sign in to comment.