azalea_crypto/
lib.rs

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