azalea_crypto/
lib.rs

1#![doc = include_str!("../README.md")]
2
3mod signing;
4
5use aes::{
6    Aes128,
7    cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit, inout::InOutBuf},
8};
9use rand::{RngCore, rngs::OsRng};
10use sha1::{Digest, Sha1};
11pub use signing::*;
12
13fn generate_secret_key() -> [u8; 16] {
14    let mut key = [0u8; 16];
15    OsRng.fill_bytes(&mut key);
16    key
17}
18
19pub fn digest_data(server_id: &[u8], public_key: &[u8], private_key: &[u8]) -> Vec<u8> {
20    let mut digest = Sha1::new();
21    digest.update(server_id);
22    digest.update(private_key);
23    digest.update(public_key);
24    digest.finalize().to_vec()
25}
26
27pub fn hex_digest(digest: &[u8]) -> String {
28    // Note that the Sha1.hexdigest() method used by minecraft is non standard.
29    // It doesn't match the digest method found in most programming languages
30    // and libraries. It works by treating the sha1 output bytes as one large
31    // integer in two's complement and then printing the integer in base 16,
32    // placing a minus sign if the interpreted number is negative.
33
34    num_bigint::BigInt::from_signed_bytes_be(digest).to_str_radix(16)
35}
36
37#[derive(Debug)]
38pub struct EncryptResult {
39    pub secret_key: [u8; 16],
40    pub encrypted_public_key: Vec<u8>,
41    pub encrypted_challenge: Vec<u8>,
42}
43
44pub fn encrypt(public_key: &[u8], challenge: &[u8]) -> Result<EncryptResult, String> {
45    // On receipt of a Encryption Request from the server, the client will
46    // generate a random 16-byte shared secret, to be used with the AES/CFB8
47    // stream cipher.
48    let secret_key = generate_secret_key();
49    // let hash = hex_digest(&digest_data(server_id.as_bytes(), public_key,
50    // &secret_key));
51
52    // this.keybytes = Crypt.encryptUsingKey(publicKey, secretKey.getEncoded());
53    // this.challenge = Crypt.encryptUsingKey(publicKey, arrby);
54    let encrypted_public_key: Vec<u8> = rsa_public_encrypt_pkcs1::encrypt(public_key, &secret_key)?;
55    let encrypted_challenge: Vec<u8> = rsa_public_encrypt_pkcs1::encrypt(public_key, challenge)?;
56
57    Ok(EncryptResult {
58        secret_key,
59        encrypted_public_key,
60        encrypted_challenge,
61    })
62}
63
64pub type Aes128CfbEnc = cfb8::Encryptor<Aes128>;
65pub type Aes128CfbDec = cfb8::Decryptor<Aes128>;
66
67pub fn create_cipher(key: &[u8]) -> (Aes128CfbEnc, Aes128CfbDec) {
68    (
69        Aes128CfbEnc::new_from_slices(key, key).unwrap(),
70        Aes128CfbDec::new_from_slices(key, key).unwrap(),
71    )
72}
73
74pub fn encrypt_packet(cipher: &mut Aes128CfbEnc, packet: &mut [u8]) {
75    let (chunks, rest) = InOutBuf::from(packet).into_chunks();
76    assert!(rest.is_empty());
77    cipher.encrypt_blocks_inout_mut(chunks);
78}
79pub fn decrypt_packet(cipher: &mut Aes128CfbDec, packet: &mut [u8]) {
80    let (chunks, rest) = InOutBuf::from(packet).into_chunks();
81    assert!(rest.is_empty());
82    cipher.decrypt_blocks_inout_mut(chunks);
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn test_generate_secret_key() {
91        let key = generate_secret_key();
92        assert_eq!(key.len(), 16);
93    }
94
95    #[test]
96    fn test_hex_digest() {
97        let digest = hex_digest(&digest_data(b"Notch", &[], &[]));
98        assert_eq!(digest, "4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48");
99
100        let digest = hex_digest(&digest_data(b"jeb_", &[], &[]));
101        assert_eq!(digest, "-7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1");
102
103        let digest = hex_digest(&digest_data(b"simon", &[], &[]));
104        assert_eq!(digest, "88e16a1019277b15d58faf0541e11910eb756f6");
105    }
106
107    #[test]
108    fn encode_packet_twice() {
109        let mut packet = vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
110        let (mut enc_cipher, _dec_cipher) = create_cipher(b"1234567890123456");
111        encrypt_packet(&mut enc_cipher, &mut packet);
112        assert_eq!(packet, vec![117, 151, 183, 45, 229, 232, 43, 181, 121, 16]);
113        let mut packet = vec![0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13];
114        encrypt_packet(&mut enc_cipher, &mut packet);
115        assert_eq!(
116            packet,
117            vec![185, 223, 129, 153, 173, 140, 133, 239, 59, 168]
118        );
119    }
120
121    #[test]
122    fn encode_packet_long() {
123        let mut packet = (0..=255).collect::<Vec<u8>>();
124        let (mut enc_cipher, _dec_cipher) = create_cipher(b"1234567890123456");
125        encrypt_packet(&mut enc_cipher, &mut packet);
126        assert_eq!(
127            packet,
128            vec![
129                117, 151, 183, 45, 229, 232, 43, 181, 121, 16, 185, 223, 129, 153, 173, 140, 133,
130                239, 59, 168, 148, 39, 97, 19, 22, 219, 78, 70, 116, 143, 21, 223, 155, 99, 201,
131                62, 133, 77, 244, 152, 254, 36, 135, 147, 45, 25, 66, 236, 2, 12, 101, 39, 140, 62,
132                7, 57, 19, 101, 217, 91, 142, 243, 0, 3, 100, 142, 160, 21, 219, 145, 151, 37, 11,
133                30, 190, 176, 26, 90, 143, 63, 255, 188, 254, 40, 41, 92, 163, 197, 8, 8, 111, 175,
134                49, 234, 82, 34, 5, 96, 162, 7, 217, 42, 77, 38, 127, 213, 207, 251, 34, 173, 34,
135                132, 23, 12, 118, 59, 51, 216, 173, 199, 137, 95, 132, 222, 243, 195, 81, 60, 205,
136                52, 65, 209, 125, 137, 5, 52, 219, 165, 248, 35, 173, 57, 200, 182, 162, 148, 70,
137                62, 102, 21, 220, 158, 71, 98, 47, 231, 196, 58, 8, 70, 160, 177, 159, 50, 20, 187,
138                31, 249, 68, 26, 142, 171, 239, 193, 10, 174, 14, 80, 238, 114, 124, 185, 253, 246,
139                47, 67, 37, 69, 70, 9, 69, 135, 13, 195, 253, 8, 241, 175, 170, 75, 231, 7, 92, 18,
140                38, 132, 65, 146, 202, 130, 238, 224, 30, 113, 168, 241, 159, 131, 238, 67, 1, 244,
141                74, 172, 86, 95, 192, 236, 198, 188, 81, 67, 49, 230, 166, 52, 224, 238, 11, 252,
142                0, 179, 56, 209, 231, 62, 146, 106, 18, 217, 138, 89, 110, 240, 255, 192
143            ]
144        );
145    }
146
147    #[test]
148    fn encode_decode_packet() {
149        let mut packet = vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
150        let (mut enc_cipher, mut dec_cipher) = create_cipher(b"1234567890123456");
151        encrypt_packet(&mut enc_cipher, &mut packet);
152        decrypt_packet(&mut dec_cipher, &mut packet);
153        assert_eq!(
154            packet,
155            vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09]
156        );
157    }
158}