myph-v2~ rust shellcode loader with evasive capabilities |
| git clone https://github.com/djnnvx/myph-v2.git |
| log | files | refs | archive | README |
twofish_cipher.rs (5863B)
1 use super::Encryptor; 2 use rand::Rng; 3 use sha2::{Digest, Sha256}; 4 use twofish::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyIvInit}; 5 use twofish::Twofish; 6 7 type TwofishCbcEnc = cbc::Encryptor<Twofish>; 8 #[allow(dead_code)] 9 type TwofishCbcDec = cbc::Decryptor<Twofish>; 10 11 /// Twofish cipher implementation with CBC mode 12 pub struct TwofishEncryptor { 13 key: [u8; 32], 14 } 15 16 impl TwofishEncryptor { 17 /// Creates a new Twofish encryptor with the given key 18 /// Uses SHA-256 to derive a proper 32-byte key from the input 19 pub fn new(key: &str) -> Self { 20 let mut hasher = Sha256::new(); 21 hasher.update(key.as_bytes()); 22 let hash = hasher.finalize(); 23 24 let mut key_bytes = [0u8; 32]; 25 key_bytes.copy_from_slice(&hash[..32]); 26 27 println!( 28 "[Twofish] Derived key from input (SHA-256): {:02x?}", 29 &key_bytes[..8] 30 ); 31 32 Self { key: key_bytes } 33 } 34 } 35 36 impl Encryptor for TwofishEncryptor { 37 fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>, String> { 38 let mut rng = rand::thread_rng(); 39 let mut iv = [0u8; 16]; 40 rng.fill(&mut iv); 41 42 println!( 43 "[Twofish] Generated random IV for encryption: {:02x?}", 44 &iv[..8] 45 ); 46 47 let cipher = TwofishCbcEnc::new(&self.key.into(), &iv.into()); 48 let ciphertext = cipher.encrypt_padded_vec_mut::<Pkcs7>(data); 49 50 let mut result = iv.to_vec(); 51 result.extend_from_slice(&ciphertext); 52 53 Ok(result) 54 } 55 56 fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>, String> { 57 if data.len() < 16 { 58 return Err("Ciphertext too short to contain IV".to_string()); 59 } 60 61 let iv: [u8; 16] = data[..16].try_into().unwrap(); 62 let ciphertext = &data[16..]; 63 64 println!("[Twofish] Extracted IV for decryption: {:02x?}", &iv[..8]); 65 66 let cipher = TwofishCbcDec::new(&self.key.into(), &iv.into()); 67 cipher 68 .decrypt_padded_vec_mut::<Pkcs7>(ciphertext) 69 .map_err(|e| format!("Decryption error: {:?}", e)) 70 } 71 72 fn key_size(&self) -> usize { 73 32 74 } 75 76 fn algorithm_name(&self) -> &'static str { 77 "Twofish-CBC" 78 } 79 80 fn uses_iv(&self) -> bool { 81 true 82 } 83 84 fn generate_decrypt_code(&self) -> &'static str { 85 r#"/// Decrypts Twofish CBC encrypted data using the provided key 86 /// 87 /// Returns `Ok(Vec<u8>)` with decrypted data if successful, otherwise returns an error. 88 pub fn decrypt_twofish(data: &[u8], key: &[u8]) -> Result<Vec<u8>, String> { 89 use twofish::cipher::{block_padding::Pkcs7, BlockDecryptMut, KeyIvInit}; 90 use twofish::Twofish; 91 92 if data.len() < 16 { 93 return Err("Ciphertext too short to contain IV".to_string()); 94 } 95 96 if key.len() != 32 { 97 return Err("Key must be 32 bytes for Twofish".to_string()); 98 } 99 100 let iv: [u8; 16] = data[..16].try_into().unwrap(); 101 let ciphertext = &data[16..]; 102 103 let key_array: [u8; 32] = key.try_into().map_err(|_| "Invalid key length".to_string())?; 104 105 type TwofishCbcDec = cbc::Decryptor<Twofish>; 106 let cipher = TwofishCbcDec::new(&key_array.into(), &iv.into()); 107 cipher 108 .decrypt_padded_vec_mut::<Pkcs7>(ciphertext) 109 .map_err(|e| format!("Decryption error: {:?}", e)) 110 }"# 111 } 112 113 fn required_dependencies(&self) -> Vec<(&'static str, &'static str)> { 114 vec![("twofish", "0.7"), ("cbc", "0.1")] 115 } 116 } 117 118 #[cfg(test)] 119 mod tests { 120 use super::*; 121 122 #[test] 123 fn test_twofish_encrypt_decrypt() { 124 let encryptor = TwofishEncryptor::new("my-secret-key-123"); 125 let plaintext = b"Hello, World!"; 126 127 let encrypted = encryptor.encrypt(plaintext).unwrap(); 128 assert_ne!(encrypted, plaintext); 129 130 let decrypted = encryptor.decrypt(&encrypted).unwrap(); 131 assert_eq!(decrypted, plaintext); 132 } 133 134 #[test] 135 fn test_twofish_different_keys() { 136 let encryptor1 = TwofishEncryptor::new("key1"); 137 let encryptor2 = TwofishEncryptor::new("key2"); 138 let plaintext = b"Test data"; 139 140 let encrypted1 = encryptor1.encrypt(plaintext).unwrap(); 141 let encrypted2 = encryptor2.encrypt(plaintext).unwrap(); 142 143 assert_ne!(encrypted1, encrypted2); 144 } 145 146 #[test] 147 fn test_twofish_empty_data() { 148 let encryptor = TwofishEncryptor::new("key"); 149 let empty: &[u8] = &[]; 150 151 let encrypted = encryptor.encrypt(empty).unwrap(); 152 assert!(encrypted.len() >= 16); 153 154 let decrypted = encryptor.decrypt(&encrypted).unwrap(); 155 assert_eq!(decrypted.len(), 0); 156 } 157 158 #[test] 159 fn test_twofish_wrong_key_decryption() { 160 let encryptor1 = TwofishEncryptor::new("correct-key"); 161 let encryptor2 = TwofishEncryptor::new("wrong-key"); 162 let plaintext = b"Secret message"; 163 164 let encrypted = encryptor1.encrypt(plaintext).unwrap(); 165 let result = encryptor2.decrypt(&encrypted); 166 167 assert!(result.is_err() || result.unwrap() != plaintext); 168 } 169 170 #[test] 171 fn test_twofish_long_data() { 172 let encryptor = TwofishEncryptor::new("secret-key"); 173 let plaintext = 174 b"This is a much longer message that exceeds the Twofish block size of 16 bytes"; 175 176 let encrypted = encryptor.encrypt(plaintext).unwrap(); 177 assert_ne!(encrypted, plaintext); 178 179 let decrypted = encryptor.decrypt(&encrypted).unwrap(); 180 assert_eq!(decrypted, plaintext); 181 } 182 183 #[test] 184 fn test_twofish_binary_data() { 185 let encryptor = TwofishEncryptor::new("key"); 186 let plaintext: Vec<u8> = (0..=255).collect(); 187 188 let encrypted = encryptor.encrypt(&plaintext).unwrap(); 189 assert_ne!(encrypted, plaintext); 190 191 let decrypted = encryptor.decrypt(&encrypted).unwrap(); 192 assert_eq!(decrypted, plaintext); 193 } 194 }