myph-v2~ rust shellcode loader with evasive capabilities |
| git clone https://github.com/djnnvx/myph-v2.git |
| log | files | refs | archive | README |
blowfish_cipher.rs (7500B)
1 use super::Encryptor; 2 use blowfish::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, KeyIvInit}; 3 use blowfish::Blowfish; 4 use rand::Rng; 5 6 type BlowfishCbcEnc = cbc::Encryptor<Blowfish>; 7 #[allow(dead_code)] 8 type BlowfishCbcDec = cbc::Decryptor<Blowfish>; 9 10 /// Blowfish cipher implementation with CBC mode 11 pub struct BlowfishEncryptor { 12 key: Vec<u8>, 13 } 14 15 impl BlowfishEncryptor { 16 /// Creates a new Blowfish encryptor with the given key 17 /// Blowfish supports key sizes from 4 to 56 bytes 18 pub fn new(key: &str) -> Self { 19 let key_data = key.as_bytes(); 20 21 // Ensure key is at least 4 bytes and at most 56 bytes 22 let key = if key_data.len() < 4 { 23 println!( 24 "[Blowfish] WARNING: Key length {} is less than 4 bytes, padding to 4 bytes", 25 key_data.len() 26 ); 27 // Pad short keys 28 let mut padded = key_data.to_vec(); 29 while padded.len() < 4 { 30 padded.push(0); 31 } 32 padded 33 } else if key_data.len() > 56 { 34 println!( 35 "[Blowfish] WARNING: Key length {} exceeds 56 bytes, truncating to 56 bytes", 36 key_data.len() 37 ); 38 // Truncate long keys 39 key_data[..56].to_vec() 40 } else { 41 key_data.to_vec() 42 }; 43 44 println!("[Blowfish] Using key length: {} bytes", key.len()); 45 46 Self { key } 47 } 48 } 49 50 impl Encryptor for BlowfishEncryptor { 51 fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>, String> { 52 // Generate random IV (8 bytes for Blowfish) 53 let mut rng = rand::thread_rng(); 54 let mut iv = [0u8; 8]; 55 rng.fill(&mut iv); 56 57 println!( 58 "[Blowfish] Generated random IV for encryption: {:02x?}", 59 &iv 60 ); 61 62 let cipher = BlowfishCbcEnc::new_from_slices(&self.key, &iv) 63 .map_err(|e| format!("Failed to create cipher: {:?}", e))?; 64 65 let ciphertext = cipher.encrypt_padded_vec_mut::<Pkcs7>(data); 66 67 // Prepend IV to ciphertext 68 let mut result = iv.to_vec(); 69 result.extend_from_slice(&ciphertext); 70 71 Ok(result) 72 } 73 74 fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>, String> { 75 if data.len() < 8 { 76 return Err("Ciphertext too short to contain IV".to_string()); 77 } 78 79 // Extract IV from beginning of data 80 let iv: [u8; 8] = data[..8].try_into().unwrap(); 81 let ciphertext = &data[8..]; 82 83 println!("[Blowfish] Extracted IV for decryption: {:02x?}", &iv); 84 85 let cipher = BlowfishCbcDec::new_from_slices(&self.key, &iv) 86 .map_err(|e| format!("Failed to create cipher: {:?}", e))?; 87 88 cipher 89 .decrypt_padded_vec_mut::<Pkcs7>(ciphertext) 90 .map_err(|e| format!("Decryption error: {:?}", e)) 91 } 92 93 fn key_size(&self) -> usize { 94 self.key.len() 95 } 96 97 fn algorithm_name(&self) -> &'static str { 98 "Blowfish-CBC" 99 } 100 101 fn uses_iv(&self) -> bool { 102 true 103 } 104 105 fn generate_decrypt_code(&self) -> &'static str { 106 r#"/// Decrypts Blowfish CBC encrypted data using the provided key 107 /// 108 /// Returns `Ok(Vec<u8>)` with decrypted data if successful, otherwise returns an error. 109 pub fn decrypt_blowfish(data: &[u8], key: &[u8]) -> Result<Vec<u8>, String> { 110 use blowfish::cipher::{block_padding::Pkcs7, BlockDecryptMut, KeyIvInit}; 111 use blowfish::Blowfish; 112 113 if data.len() < 8 { 114 return Err("Ciphertext too short to contain IV".to_string()); 115 } 116 117 if key.is_empty() || key.len() > 56 { 118 return Err("Key must be between 1 and 56 bytes for Blowfish".to_string()); 119 } 120 121 let iv: [u8; 8] = data[..8].try_into().unwrap(); 122 let ciphertext = &data[8..]; 123 124 type BlowfishCbcDec = cbc::Decryptor<Blowfish>; 125 let cipher = BlowfishCbcDec::new_from_slices(key, &iv) 126 .map_err(|e| format!("Failed to create cipher: {:?}", e))?; 127 128 cipher 129 .decrypt_padded_vec_mut::<Pkcs7>(ciphertext) 130 .map_err(|e| format!("Decryption error: {:?}", e)) 131 }"# 132 } 133 134 fn required_dependencies(&self) -> Vec<(&'static str, &'static str)> { 135 vec![("blowfish", "0.9"), ("cbc", "0.1")] 136 } 137 } 138 139 #[cfg(test)] 140 mod tests { 141 use super::*; 142 143 #[test] 144 fn test_blowfish_encrypt_decrypt() { 145 let encryptor = BlowfishEncryptor::new("my-secret-key-123"); 146 let plaintext = b"Hello, World!"; 147 148 let encrypted = encryptor.encrypt(plaintext).unwrap(); 149 assert_ne!(encrypted, plaintext); 150 151 let decrypted = encryptor.decrypt(&encrypted).unwrap(); 152 assert_eq!(decrypted, plaintext); 153 } 154 155 #[test] 156 fn test_blowfish_different_keys() { 157 let encryptor1 = BlowfishEncryptor::new("key1"); 158 let encryptor2 = BlowfishEncryptor::new("key2"); 159 let plaintext = b"Test data"; 160 161 let encrypted1 = encryptor1.encrypt(plaintext).unwrap(); 162 let encrypted2 = encryptor2.encrypt(plaintext).unwrap(); 163 164 assert_ne!(encrypted1, encrypted2); 165 } 166 167 #[test] 168 fn test_blowfish_empty_data() { 169 let encryptor = BlowfishEncryptor::new("key"); 170 let empty: &[u8] = &[]; 171 172 let encrypted = encryptor.encrypt(empty).unwrap(); 173 // Blowfish with padding will have at least one block (8 bytes) 174 assert!(encrypted.len() >= 8); 175 176 let decrypted = encryptor.decrypt(&encrypted).unwrap(); 177 assert_eq!(decrypted.len(), 0); 178 } 179 180 #[test] 181 fn test_blowfish_short_key() { 182 let encryptor = BlowfishEncryptor::new("ab"); 183 let plaintext = b"Test"; 184 185 let encrypted = encryptor.encrypt(plaintext).unwrap(); 186 let decrypted = encryptor.decrypt(&encrypted).unwrap(); 187 assert_eq!(decrypted, plaintext); 188 } 189 190 #[test] 191 fn test_blowfish_long_key() { 192 let encryptor = BlowfishEncryptor::new( 193 "this-is-a-very-long-key-that-exceeds-56-bytes-and-should-be-truncated", 194 ); 195 let plaintext = b"Test"; 196 197 let encrypted = encryptor.encrypt(plaintext).unwrap(); 198 let decrypted = encryptor.decrypt(&encrypted).unwrap(); 199 assert_eq!(decrypted, plaintext); 200 } 201 202 #[test] 203 fn test_blowfish_wrong_key_decryption() { 204 let encryptor1 = BlowfishEncryptor::new("correct-key"); 205 let encryptor2 = BlowfishEncryptor::new("wrong-key"); 206 let plaintext = b"Secret message"; 207 208 let encrypted = encryptor1.encrypt(plaintext).unwrap(); 209 let result = encryptor2.decrypt(&encrypted); 210 211 // Decryption with wrong key should fail or produce garbage 212 assert!(result.is_err() || result.unwrap() != plaintext); 213 } 214 215 #[test] 216 fn test_blowfish_long_data() { 217 let encryptor = BlowfishEncryptor::new("secret-key"); 218 let plaintext = b"This is a much longer message that exceeds the Blowfish block size"; 219 220 let encrypted = encryptor.encrypt(plaintext).unwrap(); 221 assert_ne!(encrypted, plaintext); 222 223 let decrypted = encryptor.decrypt(&encrypted).unwrap(); 224 assert_eq!(decrypted, plaintext); 225 } 226 227 #[test] 228 fn test_blowfish_binary_data() { 229 let encryptor = BlowfishEncryptor::new("key"); 230 let plaintext: Vec<u8> = (0..=255).collect(); 231 232 let encrypted = encryptor.encrypt(&plaintext).unwrap(); 233 assert_ne!(encrypted, plaintext); 234 235 let decrypted = encryptor.decrypt(&encrypted).unwrap(); 236 assert_eq!(decrypted, plaintext); 237 } 238 }