diff --git a/Cargo.toml b/Cargo.toml index 754f9e1..e48458e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,3 +16,6 @@ rand = "0.8.5" aes = "0.7" rsa = "0.6" pkcs8 = "0.8" +crypto = { version = "0.5.1", features = ["digest"] } +sha1 = "0.10.6" +num-bigint = "0.4.5" diff --git a/src/encrypt.rs b/src/encrypt.rs index e6ada91..dbbfd34 100644 --- a/src/encrypt.rs +++ b/src/encrypt.rs @@ -8,7 +8,7 @@ use aes::cipher::{BlockEncrypt, BlockDecrypt, generic_array::GenericArray}; #[derive(Clone)] pub struct McCipher { - key: [u8; 16], + pub(crate) key: [u8; 16], state_en: [u8; 16], state_de: [u8; 16], } diff --git a/src/mc_types.rs b/src/mc_types.rs index f46951b..9a2517a 100644 --- a/src/mc_types.rs +++ b/src/mc_types.rs @@ -10,6 +10,9 @@ use async_trait::async_trait; use rsa::{RsaPrivateKey, RsaPublicKey}; use rsa::pkcs8::{EncodePublicKey, DecodePublicKey}; use rand::Rng; +use crypto::digest::Digest; +use sha1::Sha1; +use num_bigint::BigInt; use crate::login; use crate::encrypt::{self, McCipher}; @@ -73,6 +76,7 @@ pub struct ProtocolConnection<'a> { rsa_public_key: Option, aes_cipher: Option, verify_token: Option<[u8; 16]>, + server_id: String } impl<'a> ProtocolConnection<'a> { @@ -87,6 +91,7 @@ impl<'a> ProtocolConnection<'a> { rsa_public_key: None, aes_cipher: None, verify_token: None, + server_id: "".to_string(), } } @@ -109,7 +114,7 @@ impl<'a> ProtocolConnection<'a> { match &self.verify_token { Some (token) => Ok(login::clientbound::EncryptionRequest { - server_id: "".to_string(), + server_id: self.server_id.clone(), public_key: key .to_public_key_der()? .as_ref() @@ -127,6 +132,7 @@ impl<'a> ProtocolConnection<'a> { &mut self, request: login::clientbound::EncryptionRequest, ) -> Result { + self.server_id = request.server_id; self.rsa_public_key = Some( RsaPublicKey::from_public_key_der(&request.public_key)?); self.aes_cipher = Some(McCipher::create()); @@ -205,6 +211,23 @@ impl<'a> ProtocolConnection<'a> { aes_cipher: self.aes_cipher.clone(), })) } + + pub async fn server_id_hash(&self) -> Result { + let hash_data = match &self.aes_cipher { + Some(aes_cipher) => match &self.rsa_public_key { + Some(key) => [ + self.server_id.as_bytes(), + &aes_cipher.key, + key.to_public_key_der()?.as_ref(), + ].concat(), + None => return Err(Box::new(PacketError::EncryptionError)) + }, + None => return Err(Box::new(PacketError::EncryptionError)) + }; + let hash = BigInt::from_signed_bytes_be( + &Sha1::digest(hash_data)).to_str_radix(16); + Ok(hash) + } } unsafe impl<'a> Send for ProtocolConnection<'a> {}