diff --git a/Cargo.lock b/Cargo.lock
index ae9f69708ab8130c9352d388dbb3b91435fc5f6f..3980db1ac196879e5f34ce65d1f84d86fd5bfc50 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6,6 +6,37 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
 
+[[package]]
+name = "aes"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561"
+dependencies = [
+ "aes-soft",
+ "aesni",
+ "cipher",
+]
+
+[[package]]
+name = "aes-soft"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072"
+dependencies = [
+ "cipher",
+ "opaque-debug",
+]
+
+[[package]]
+name = "aesni"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce"
+dependencies = [
+ "cipher",
+ "opaque-debug",
+]
+
 [[package]]
 name = "aho-corasick"
 version = "0.7.15"
@@ -75,6 +106,22 @@ dependencies = [
  "generic-array",
 ]
 
+[[package]]
+name = "block-modes"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0"
+dependencies = [
+ "block-padding",
+ "cipher",
+]
+
+[[package]]
+name = "block-padding"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
+
 [[package]]
 name = "bumpalo"
 version = "3.6.0"
@@ -125,6 +172,15 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "cipher"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801"
+dependencies = [
+ "generic-array",
+]
+
 [[package]]
 name = "command_attr"
 version = "0.3.3"
@@ -1678,8 +1734,10 @@ checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
 name = "ucc-discord-bot"
 version = "0.1.0"
 dependencies = [
+ "aes",
  "async-trait",
  "base64 0.13.0",
+ "block-modes",
  "chrono",
  "diesel",
  "guard",
@@ -1688,7 +1746,6 @@ dependencies = [
  "lazy_static",
  "ldap3",
  "log",
- "openssl",
  "rand 0.8.3",
  "rayon",
  "regex",
diff --git a/Cargo.toml b/Cargo.toml
index a3b8c832606bc37e2f6f1aaa85b85907ccf4251b..430f008f4b52bb57a2527351a7644c8a62189ebc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,8 +5,10 @@ authors = ["tec <tec@ucc.gu.uwa.edu.au>"]
 edition = "2018"
 
 [dependencies]
+aes = "0.6"
 async-trait = "0.1.42"
 base64 = "0.13.0"
+block-modes = "0.7"
 chrono = "0.4.19"
 diesel = { version = "1.4.5", features = ["sqlite"] }
 guard = "0.5.0"
@@ -15,7 +17,6 @@ indexmap = { version = "1.6.1", features = ["serde-1"] }
 lazy_static = "1.4.0"
 ldap3 = "0.9.1"
 log = "0.4.11"
-openssl = "0.10.32"
 rand = "0.8.1"
 rayon = "1.5.0"
 regex = "1.4.3"
diff --git a/src/token_management.rs b/src/token_management.rs
index f6d21f6caef515118fb40c45623721148272ce99..badad22ebde7d1c5908fd2e359d22992e046e3e1 100644
--- a/src/token_management.rs
+++ b/src/token_management.rs
@@ -1,30 +1,31 @@
+use aes::Aes128;
 use base64;
+use block_modes::block_padding::Pkcs7;
+use block_modes::{BlockMode, Cbc};
 use chrono::{prelude::Utc, DateTime};
-use openssl::symm::{decrypt, encrypt, Cipher};
 use rand::Rng;
 use serenity::model::user::User;
 use std::str;
 
+type Aes128Cbc = Cbc<Aes128, Pkcs7>;
 pub static TOKEN_LIFETIME: i64 = 300; // 5 minutes
 
 lazy_static! {
     static ref KEY: [u8; 32] = rand::thread_rng().gen::<[u8; 32]>();
-    static ref CIPHER: Cipher = Cipher::aes_256_cbc();
+    static ref IV: [u8; 16] = [0; 16];
+    static ref CIPHER: Aes128Cbc = Aes128Cbc::new_var(KEY.as_ref(), IV.as_ref()).unwrap();
 }
 
 fn text_encrypt(plaintext: &str) -> String {
-    let iv: &[u8; 16] = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
-    let encrypted_vec =
-        encrypt(*CIPHER, &*KEY, Some(iv), plaintext.as_bytes()).expect("encryption failed");
-    base64::encode(encrypted_vec.as_slice())
+    base64::encode(CIPHER.encrypt_vec(plaintext.as_bytes()))
 }
+
 fn text_decrypt(ciphertext: &str) -> Option<String> {
-    let iv: &[u8; 16] = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
     guard!(let Ok(cipher_vec) = base64::decode(ciphertext) else {
         warn!("Unable to decode base64 text");
         return None
     });
-    guard!(let Ok(decrypted_vec) = decrypt(*CIPHER, &*KEY, Some(iv), &cipher_vec) else {
+    guard!(let Ok(decrypted_vec) = CIPHER.decrypt_vec(&cipher_vec) else {
         warn!("Text decryption failed");
         return None
     });
@@ -75,7 +76,7 @@ pub fn parse_token(discord_user: &User, encrypted_token: &str) -> Result<String,
     let token_username = token_components[2];
     if token_discord_user != discord_user.id.0.to_string() {
         warn!("... attempt failed : DiscordID mismatch");
-        return Err(TokenError::DiscordIdMismatch)
+        return Err(TokenError::DiscordIdMismatch);
     }
     let time_delta_seconds = Utc::now().timestamp() - token_timestamp.timestamp();
     if time_delta_seconds > TOKEN_LIFETIME {
@@ -83,7 +84,7 @@ pub fn parse_token(discord_user: &User, encrypted_token: &str) -> Result<String,
             "... attempt failed : token expired ({} seconds old)",
             time_delta_seconds
         );
-        return Err(TokenError::TokenExpired)
+        return Err(TokenError::TokenExpired);
     }
     info!(
         "... verification successful (token {} seconds old)",
diff --git a/src/user_management.rs b/src/user_management.rs
index d932f0c9e14f09c11510a5c20af9551bc262bae2..ad3ceb0300b9c11e8a4289fe77755740e331db06 100644
--- a/src/user_management.rs
+++ b/src/user_management.rs
@@ -1,5 +1,3 @@
-use async_trait::async_trait;
-use rand::seq::SliceRandom;
 use regex::Regex;
 use serenity::{
     model::{channel::Message, guild::Member, id::RoleId},
@@ -89,9 +87,8 @@ impl Commands {
             send_message!(
                 msg.channel_id,
                 &ctx.http,
-                RANDOM_SASS
-                    .choose(&mut rand::thread_rng())
-                    .expect("We couldn't get any sass")
+                RANDOM_SASS[0] //.choose(&mut rand::thread_rng())
+                               //.expect("We couldn't get any sass")
             );
             return;
         }
@@ -161,7 +158,7 @@ impl Commands {
             return // Err()
         });
         guard!(let Ok(mut discord_member) = serenity::model::id::GuildId(CONFIG.server_id)
-            .member(ctx.http.clone(), msg.author.id) else {
+            .member(ctx.http.clone(), msg.author.id).await else {
             return // Err()
         });
 
@@ -177,7 +174,7 @@ impl Commands {
                 continue;
             }
             if discord_member.roles.contains(&RoleId::from(role))
-                && discord_member.remove_role(&ctx.http, role).is_err()
+                && discord_member.remove_role(&ctx.http, role).await.is_err()
             {
                 return; // Err()
             }
@@ -186,7 +183,10 @@ impl Commands {
         if !discord_member
             .roles
             .contains(&RoleId::from(registered_role))
-            && discord_member.add_role(&ctx.http, registered_role).is_err()
+            && discord_member
+                .add_role(&ctx.http, registered_role)
+                .await
+                .is_err()
         {
             return; // Err()
         }
@@ -197,41 +197,46 @@ impl Commands {
     pub async fn verify(ctx: Context, msg: Message, token: &str) {
         match parse_token(&msg.author, token) {
             Ok(name) => {
-                e!(
-                    "Unable to get member: {:?}",
-                    serenity::model::id::GuildId(CONFIG.server_id)
-                        .member(ctx.http.clone(), msg.author.id)
-                        .map(|mut member| async {
-                            let full_member = database::add_member(&msg.author.id.0, &name);
-                            e!(
-                                "Unable to remove role: {:?}",
-                                member.remove_role(&ctx.http, CONFIG.unregistered_member_role)
-                            );
-                            guard!(let Some(member_role) = Commands::get_registered_role(name) else {
-                                send_message!(msg.channel_id, ctx.http.clone(), "Couldn't find you in LDAP!");
-                                return
-                            });
-                            e!(
-                                "Unable to add role: {:?}",
-                                member.add_role(&ctx.http, member_role)
-                            );
-                            e!(
-                                "Unable to edit nickname: {:?}",
-                                member.edit(&ctx.http, |m| {
-                                    m.nickname(member_nickname(&full_member));
-                                    m
-                                })
-                            );
-                            let mut verification_message = MessageBuilder::new();
-                            verification_message.push(format!("Great, {}! Verification was successful. To provide a friendly introduction to yourself, consider doing ", &full_member.username));
-                            verification_message.push_mono(format!("{}set bio <info>", CONFIG.command_prefix));
-                            send_message!(
-                                msg.channel_id,
-                                ctx.http.clone(),
-                                verification_message.build()
-                            );
-                        })
-                );
+                if let Ok(mut member) = serenity::model::id::GuildId(CONFIG.server_id)
+                    .member(ctx.http.clone(), msg.author.id)
+                    .await
+                {
+                    let full_member = database::add_member(&msg.author.id.0, &name);
+                    e!(
+                        "Unable to remove role: {:?}",
+                        member
+                            .remove_role(&ctx.http, CONFIG.unregistered_member_role)
+                            .await
+                    );
+                    guard!(let Some(member_role) = Commands::get_registered_role(name) else {
+                        send_message!(msg.channel_id, ctx.http.clone(), "Couldn't find you in LDAP!");
+                        return
+                    });
+                    e!(
+                        "Unable to add role: {:?}",
+                        member.add_role(&ctx.http, member_role).await
+                    );
+                    e!(
+                        "Unable to edit nickname: {:?}",
+                        member
+                            .edit(&ctx.http, |m| {
+                                m.nickname(member_nickname(&full_member));
+                                m
+                            })
+                            .await
+                    );
+                    let mut verification_message = MessageBuilder::new();
+                    verification_message.push(format!("Great, {}! Verification was successful. To provide a friendly introduction to yourself, consider doing ", &full_member.username));
+                    verification_message
+                        .push_mono(format!("{}set bio <info>", CONFIG.command_prefix));
+                    send_message!(
+                        msg.channel_id,
+                        ctx.http.clone(),
+                        verification_message.build()
+                    );
+                } else {
+                    error!("Unable to get member: {:?}", name)
+                }
             }
             Err(reason) => send_message!(
                 msg.channel_id,
@@ -282,15 +287,17 @@ impl Commands {
         }
         let member = possible_member.unwrap();
         info!("Found matching profile, UCC username: {}", &member.username);
+        let user = match ctx.http.get_user(member.discord_id as _).await {
+            Ok(u) => u,
+            Err(e) => {
+                error!("Couldn't find matching Discord ID for username!");
+                return;
+            }
+        };
         let result = msg.channel_id.send_message(&ctx.http, |m| {
             m.embed(|embed| {
                 embed.colour(serenity::utils::Colour::LIGHTER_GREY);
-                embed.footer(|f| async {
-                    let user = &ctx
-                        .http
-                        .get_user(member.discord_id.clone() as u64)
-                        .await
-                        .expect("We expected this user to exist... they didn't ;(");
+                embed.footer(|f| {
                     f.text(&user.name);
                     f.icon_url(
                         user.static_avatar_url()