nurtex_protocol/connection/
utils.rs1use nurtex_encrypt::{digest_data, encrypt};
2
3use crate::packets::login::{ClientsideEncryptionRequest, ServersideEncryptionResponse};
4
5pub fn handle_encryption_request(request: &ClientsideEncryptionRequest) -> Option<(ServersideEncryptionResponse, [u8; 16])> {
7 if let Some(encryption) = encrypt(&request.public_key, &request.verify_token) {
8 let response = ServersideEncryptionResponse {
9 shared_secret: encryption.encrypted_public_key,
10 verify_token: encryption.encrypted_challenge,
11 };
12
13 Some((response, encryption.secret_key))
14 } else {
15 None
16 }
17}
18
19pub fn get_server_hash(server_id: &str, shared_secret: &[u8; 16], public_key: &[u8]) -> String {
21 let hash = digest_data(server_id.as_bytes(), public_key, shared_secret);
22 create_minecraft_hash(&hash)
23}
24
25fn create_minecraft_hash(hash: &[u8]) -> String {
27 let is_negative = (hash[0] & 0x80) == 0x80;
28
29 let hash_value = if is_negative {
30 let mut result = Vec::with_capacity(hash.len());
31 let mut carry = true;
32
33 for &byte in hash.iter().rev() {
34 let inverted = !byte;
35
36 if carry {
37 let (sum, overflow) = inverted.overflowing_add(1);
38 result.push(sum);
39 carry = overflow;
40 } else {
41 result.push(inverted);
42 }
43 }
44
45 result.reverse();
46
47 result
48 } else {
49 hash.to_vec()
50 };
51
52 let hex = hash_value.iter().map(|b| format!("{:02x}", b)).collect::<String>();
53
54 let trimmed = hex.trim_start_matches('0');
55
56 if is_negative {
57 format!("-{}", if trimmed.is_empty() { "0" } else { trimmed })
58 } else {
59 if trimmed.is_empty() { "0" } else { trimmed }.to_string()
60 }
61}