myph-v2.git


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 }