aboutsummaryrefslogtreecommitdiff
path: root/azalea-auth
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2022-04-25 03:50:17 +0000
committerGitHub <noreply@github.com>2022-04-25 03:50:17 +0000
commitdac943e3d79def7d2c322450790f16f027735941 (patch)
tree3beafa3c8035c69a33b7d0f12779236bf786cf36 /azalea-auth
parentb7641ff308aab7840d2a2253ae50f8ee496b2a97 (diff)
parentf4dd3a9293367fa8f3d839a184e8055b22595204 (diff)
downloadazalea-drasl-dac943e3d79def7d2c322450790f16f027735941.tar.xz
Merge pull request #3 from mat-1/auth
Auth
Diffstat (limited to 'azalea-auth')
-rwxr-xr-xazalea-auth/Cargo.toml6
-rw-r--r--azalea-auth/src/encryption.rs94
-rwxr-xr-xazalea-auth/src/lib.rs3
3 files changed, 103 insertions, 0 deletions
diff --git a/azalea-auth/Cargo.toml b/azalea-auth/Cargo.toml
index aa9b7bdb..6279d903 100755
--- a/azalea-auth/Cargo.toml
+++ b/azalea-auth/Cargo.toml
@@ -6,4 +6,10 @@ version = "0.1.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+aes = "0.7.4"
+cfb8 = "0.7.1"
+num-bigint = "^0.4.3"
+rand = {version = "^0.8.4", features = ["getrandom"]}
+rsa_public_encrypt_pkcs1 = "0.4.0"
+sha-1 = "^0.10.0"
uuid = "^0.8.2"
diff --git a/azalea-auth/src/encryption.rs b/azalea-auth/src/encryption.rs
new file mode 100644
index 00000000..6f2e43a8
--- /dev/null
+++ b/azalea-auth/src/encryption.rs
@@ -0,0 +1,94 @@
+use aes::{
+ cipher::{AsyncStreamCipher, NewCipher},
+ Aes128,
+};
+use cfb8::Cfb8;
+use rand::{rngs::OsRng, RngCore};
+use sha1::{Digest, Sha1};
+
+fn generate_secret_key() -> [u8; 16] {
+ let mut key = [0u8; 16];
+ OsRng.fill_bytes(&mut key);
+ key
+}
+
+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(public_key);
+ digest.update(private_key);
+ digest.finalize().to_vec()
+}
+
+fn hex_digest(digest: &[u8]) -> String {
+ // Note that the Sha1.hexdigest() method used by minecraft is non standard.
+ // It doesn't match the digest method found in most programming languages
+ // and libraries. It works by treating the sha1 output bytes as one large
+ // integer in two's complement and then printing the integer in base 16,
+ // placing a minus sign if the interpreted number is negative.
+ num_bigint::BigInt::from_signed_bytes_be(digest).to_str_radix(16)
+}
+
+#[derive(Debug)]
+pub struct EncryptResult {
+ pub secret_key: [u8; 16],
+ pub encrypted_public_key: Vec<u8>,
+ pub encrypted_nonce: Vec<u8>,
+}
+
+pub fn encrypt(public_key: &[u8], nonce: &[u8]) -> Result<EncryptResult, String> {
+ // On receipt of a Encryption Request from the server, the client will
+ // generate a random 16-byte shared secret, to be used with the AES/CFB8
+ // stream cipher.
+ let secret_key = generate_secret_key();
+ // let hash = hex_digest(&digest_data(server_id.as_bytes(), public_key, &secret_key));
+
+ // this.keybytes = Crypt.encryptUsingKey(publicKey, secretKey.getEncoded());
+ // this.nonce = Crypt.encryptUsingKey(publicKey, arrby);
+ let encrypted_public_key: Vec<u8> =
+ rsa_public_encrypt_pkcs1::encrypt(&public_key, &secret_key)?;
+ let encrypted_nonce: Vec<u8> = rsa_public_encrypt_pkcs1::encrypt(&public_key, &nonce)?;
+
+ Ok(EncryptResult {
+ secret_key,
+ encrypted_public_key,
+ encrypted_nonce,
+ })
+}
+
+// TODO: update the aes and cfb8 crates
+pub type Aes128Cfb = Cfb8<Aes128>;
+
+pub fn create_cipher(key: &[u8]) -> Aes128Cfb {
+ Aes128Cfb::new_from_slices(&key, &key).unwrap()
+}
+
+pub fn encrypt_packet(cipher: &mut Aes128Cfb, packet: &mut [u8]) {
+ cipher.encrypt(packet);
+}
+pub fn decrypt_packet(cipher: &mut Aes128Cfb, packet: &mut [u8]) {
+ cipher.decrypt(packet);
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_generate_secret_key() {
+ let key = generate_secret_key();
+ assert_eq!(key.len(), 16);
+ }
+
+ #[test]
+ fn test_hex_digest() {
+ let digest = hex_digest(&digest_data(b"Notch", &[], &[]));
+ assert_eq!(digest, "4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48");
+
+ let digest = hex_digest(&digest_data(b"jeb_", &[], &[]));
+ assert_eq!(digest, "-7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1");
+
+ let digest = hex_digest(&digest_data(b"simon", &[], &[]));
+ assert_eq!(digest, "88e16a1019277b15d58faf0541e11910eb756f6");
+ }
+}
diff --git a/azalea-auth/src/lib.rs b/azalea-auth/src/lib.rs
index 773ea1d9..afe9eb33 100755
--- a/azalea-auth/src/lib.rs
+++ b/azalea-auth/src/lib.rs
@@ -1,3 +1,6 @@
//! Handle Minecraft authentication.
pub mod game_profile;
+pub mod encryption;
+
+