Replace openssl with RustCrypto

OpenSSL can be a pain to build at the best of times, so relying on a
pure Rust implementation of block ciphers makes life a little easier.
parent 5db256a7
Pipeline #295 canceled with stages
......@@ -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",
......
......@@ -5,8 +5,10 @@ authors = ["tec <[email protected]>"]
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"
......
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)",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment