everscale_network/adnl/
handshake.rs1use std::convert::TryInto;
2use std::sync::Arc;
3
4use aes::cipher::{StreamCipher, StreamCipherSeek};
5use everscale_crypto::ed25519;
6
7use super::encryption::*;
8use super::keystore::Key;
9use super::node_id::{NodeIdFull, NodeIdShort};
10use super::packet_view::*;
11use crate::util::FastHashMap;
12
13#[inline(always)]
14pub fn compute_handshake_prefix_len(version: Option<u16>) -> usize {
15 96 + if version.is_some() { 4 } else { 0 }
16}
17
18pub fn build_handshake_packet(
20 peer_id: &NodeIdShort,
21 peer_id_full: &NodeIdFull,
22 buffer: &mut Vec<u8>,
23 version: Option<u16>,
24) {
25 let temp_private_key = ed25519::SecretKey::generate(&mut rand::thread_rng());
27 let temp_private_key = ed25519::ExpandedSecretKey::from(&temp_private_key);
28 let temp_public_key = ed25519::PublicKey::from(&temp_private_key);
29
30 let shared_secret = temp_private_key.compute_shared_secret(peer_id_full.public_key());
31
32 let checksum: [u8; 32] = compute_packet_data_hash(version, buffer.as_slice());
34
35 let header_len = compute_handshake_prefix_len(version);
36 let buffer_len = buffer.len();
37 buffer.resize(header_len + buffer_len, 0);
38 buffer.copy_within(..buffer_len, header_len);
39
40 buffer[..32].copy_from_slice(peer_id.as_slice());
41 buffer[32..64].copy_from_slice(temp_public_key.as_bytes());
42
43 match version {
44 Some(version) => {
45 let mut xor = [
46 (version >> 8) as u8,
47 version as u8,
48 (version >> 8) as u8,
49 version as u8,
50 ];
51 for (i, byte) in buffer[..64].iter().enumerate() {
52 xor[i % 4] ^= *byte;
53 }
54 for (i, byte) in checksum.iter().enumerate() {
55 xor[i % 4] ^= *byte;
56 }
57 buffer[64..68].copy_from_slice(&xor);
58 buffer[68..100].copy_from_slice(&checksum);
59 build_packet_cipher(&shared_secret, &checksum).apply_keystream(&mut buffer[100..]);
60 }
61 None => {
62 buffer[64..96].copy_from_slice(&checksum);
63 build_packet_cipher(&shared_secret, &checksum).apply_keystream(&mut buffer[96..]);
64 }
65 }
66}
67
68pub fn parse_handshake_packet(
86 keys: &FastHashMap<NodeIdShort, Arc<Key>>,
87 buffer: &mut PacketView<'_>,
88) -> Result<Option<(NodeIdShort, Option<u16>)>, HandshakeError> {
89 const PUBLIC_KEY_RANGE: std::ops::Range<usize> = 32..64;
90
91 const DATA_START: usize = 96;
93 const CHECKSUM_RANGE: std::ops::Range<usize> = 64..DATA_START;
94 const DATA_RANGE: std::ops::RangeFrom<usize> = DATA_START..;
95
96 const EXT_DATA_START: usize = 100;
98 const EXT_CHECKSUM_RANGE: std::ops::Range<usize> = 68..EXT_DATA_START;
99 const EXT_DATA_RANGE: std::ops::RangeFrom<usize> = EXT_DATA_START..;
100
101 if buffer.len() < DATA_START {
102 return Err(HandshakeError::BadHandshakePacketLength);
103 }
104
105 let local_id = unsafe { &*(buffer.as_ptr() as *const NodeIdShort) };
108
109 let local_key = match keys.get(local_id) {
111 Some(key) => key,
112 None => return Ok(None),
114 };
115
116 let shared_secret =
118 match ed25519::PublicKey::from_bytes(buffer[PUBLIC_KEY_RANGE].try_into().unwrap()) {
119 Some(other_public_key) => local_key
120 .secret_key()
121 .compute_shared_secret(&other_public_key),
122 None => return Err(HandshakeError::InvalidPublicKey),
123 };
124
125 if buffer.len() > EXT_DATA_START {
126 if let Some(version) =
127 decode_version::<EXT_DATA_START>((&buffer[..EXT_DATA_START]).try_into().unwrap())
128 {
129 let mut cipher = build_packet_cipher(
131 &shared_secret,
132 &buffer[EXT_CHECKSUM_RANGE].try_into().unwrap(),
133 );
134
135 cipher.apply_keystream(&mut buffer[EXT_DATA_RANGE]);
137
138 if compute_packet_data_hash(Some(version), &buffer[EXT_DATA_RANGE]).as_slice()
140 == &buffer[EXT_CHECKSUM_RANGE]
141 {
142 buffer.remove_prefix(EXT_DATA_START);
144 return Ok(Some((*local_id, Some(version))));
145 }
146
147 cipher.seek(0);
149 cipher.apply_keystream(&mut buffer[EXT_DATA_RANGE]);
150 }
151 }
152
153 build_packet_cipher(&shared_secret, &buffer[CHECKSUM_RANGE].try_into().unwrap())
155 .apply_keystream(&mut buffer[DATA_RANGE]);
156
157 if compute_packet_data_hash(None, &buffer[DATA_RANGE]).as_slice() != &buffer[CHECKSUM_RANGE] {
159 return Err(HandshakeError::BadHandshakePacketChecksum);
160 }
161
162 buffer.remove_prefix(DATA_START);
164
165 Ok(Some((*local_id, None)))
166}
167
168#[derive(thiserror::Error, Debug)]
169pub enum HandshakeError {
170 #[error("Bad handshake packet length")]
171 BadHandshakePacketLength,
172 #[error("Bad handshake packet checksum")]
173 BadHandshakePacketChecksum,
174 #[error("Invalid public key")]
175 InvalidPublicKey,
176}