nurtex-encrypt 1.2.0

Library for Minecraft protocol encryption.
Documentation
use aes::Aes128;
use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit, inout::InOutBuf};
use rand::{Rng, thread_rng};
use sha1::{Digest, Sha1};

pub type AesEncryptor = cfb8::Encryptor<Aes128>;
pub type AesDecryptor = cfb8::Decryptor<Aes128>;

fn generate_secret_key() -> [u8; 16] {
  let mut key = [0u8; 16];
  thread_rng().fill(&mut key);
  key
}

pub fn digest_data(server_id: &[u8], public_key: &[u8], private_key: &[u8]) -> Vec<u8> {
  let mut digest = Sha1::new();
  digest.update(server_id);
  digest.update(private_key);
  digest.update(public_key);
  digest.finalize().to_vec()
}

#[derive(Debug)]
pub struct EncryptResult {
  pub secret_key: [u8; 16],
  pub encrypted_public_key: Vec<u8>,
  pub encrypted_challenge: Vec<u8>,
}

pub fn encrypt(public_key: &[u8], challenge: &[u8]) -> Option<EncryptResult> {
  let secret_key = generate_secret_key();

  let encrypted_public_key = rsa_public_encrypt_pkcs1::encrypt(public_key, &secret_key).ok()?;
  let encrypted_challenge = rsa_public_encrypt_pkcs1::encrypt(public_key, challenge).ok()?;

  Some(EncryptResult {
    secret_key,
    encrypted_public_key,
    encrypted_challenge,
  })
}

pub fn create_cipher(key: &[u8]) -> (AesEncryptor, AesDecryptor) {
  (AesEncryptor::new_from_slices(key, key).unwrap(), AesDecryptor::new_from_slices(key, key).unwrap())
}

pub fn encrypt_packet(cipher: &mut AesEncryptor, packet: &mut [u8]) {
  let (chunks, _) = InOutBuf::from(packet).into_chunks();
  cipher.encrypt_blocks_inout_mut(chunks);
}

pub fn decrypt_packet(cipher: &mut AesDecryptor, packet: &mut [u8]) {
  let (chunks, _) = InOutBuf::from(packet).into_chunks();
  cipher.decrypt_blocks_inout_mut(chunks);
}