use anyhow::Result;
use pbkdf2::pbkdf2_hmac;
use rust_tokio_kcp::NoneBlockCrypt;
use sha1::Sha1;
use std::sync::Arc;
pub use rust_tokio_kcp::BlockCrypt;
pub const SALT: &[u8] = b"kcp-go";
pub fn derive_key(password: &str) -> Vec<u8> {
let mut key = vec![0u8; 32];
pbkdf2_hmac::<Sha1>(password.as_bytes(), SALT, 4096, &mut key);
key
}
pub fn create_block_crypt(crypt: &str, key: &[u8]) -> Result<Option<Arc<dyn BlockCrypt>>> {
match crypt.to_lowercase().as_str() {
"auto" => {
Ok(None)
}
"none" => {
let crypt = NoneBlockCrypt::new(b"dummy_key").map_err(|e| anyhow::anyhow!("Failed to create None: {}", e))?;
Ok(Some(crypt))
}
"aes" | "aes-128" => {
let crypt = rust_tokio_kcp::Aes128BlockCrypt::new(&key[..16])
.map_err(|e| anyhow::anyhow!("Failed to create AES-128: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
"aes-192" => {
let crypt = rust_tokio_kcp::Aes192BlockCrypt::new(&key[..24])
.map_err(|e| anyhow::anyhow!("Failed to create AES-192: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
"aes-256" => {
let crypt = rust_tokio_kcp::Aes256BlockCrypt::new(&key[..32])
.map_err(|e| anyhow::anyhow!("Failed to create AES-256: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
"tea" => {
let crypt = rust_tokio_kcp::TeaBlockCrypt::new(&key[..16])
.map_err(|e| anyhow::anyhow!("Failed to create TEA: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
"xtea" => {
let crypt = rust_tokio_kcp::XteaBlockCrypt::new(&key[..16])
.map_err(|e| anyhow::anyhow!("Failed to create XTEA: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
"xor" | "simple_xor" => {
let crypt = rust_tokio_kcp::SimpleXorBlockCrypt::new(key)
.map_err(|e| anyhow::anyhow!("Failed to create SimpleXOR: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
"blowfish" => {
let crypt = rust_tokio_kcp::BlowfishBlockCrypt::new(key)
.map_err(|e| anyhow::anyhow!("Failed to create Blowfish: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
"cast5" => {
let crypt = rust_tokio_kcp::Cast5BlockCrypt::new(&key[..16])
.map_err(|e| anyhow::anyhow!("Failed to create CAST5: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
"3des" | "triple_des" => {
let crypt = rust_tokio_kcp::TripleDesBlockCrypt::new(&key[..24])
.map_err(|e| anyhow::anyhow!("Failed to create 3DES: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
"twofish" => {
let crypt = rust_tokio_kcp::TwofishBlockCrypt::new(key)
.map_err(|e| anyhow::anyhow!("Failed to create Twofish: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
"salsa20" => {
let crypt = rust_tokio_kcp::Salsa20BlockCrypt::new(key)
.map_err(|e| anyhow::anyhow!("Failed to create Salsa20: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
"sm4" => {
let crypt = rust_tokio_kcp::Sm4BlockCrypt::new(&key[..16])
.map_err(|e| anyhow::anyhow!("Failed to create SM4: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
"aes-128-gcm" => {
let crypt = rust_tokio_kcp::AesGcmBlockCrypt::new(&key[..16])
.map_err(|e| anyhow::anyhow!("Failed to create AES-128-GCM: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
_ => {
match key.len(){
16 => {
let crypt = rust_tokio_kcp::Aes128BlockCrypt::new(&key[..16])
.map_err(|e| anyhow::anyhow!("Failed to create AES-128: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
24 => {
let crypt = rust_tokio_kcp::Aes192BlockCrypt::new(&key[..24])
.map_err(|e| anyhow::anyhow!("Failed to create AES-192: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
32 => {
let crypt = rust_tokio_kcp::Aes256BlockCrypt::new(&key[..32])
.map_err(|e| anyhow::anyhow!("Failed to create AES-256: {}", e))?;
Ok(Some(Arc::new(crypt)))
}
_ => {
anyhow::bail!("Unsupported key length: {}", key.len())
}
}
}
}
}