2016-10-25 13 views
0

我有一個稱爲Stegolayer()的LSB隱寫函數,我向其發送要隱藏的數據。我的原始數據用AES加密,保存到output。除此之外,我還附加了使用RSA加密的文件字節散列碼和會話密鑰。在將它們結合在一起後,如何分割由各種部分組成的字節流

有效地,我的嵌入的祕密由加密數據+散列碼&會話密鑰作爲一個單字節流。解壓後,我怎麼分割這兩部分?

我構建bytestobehidden如下

EncryptFile(pass_txt.Text, loadedFilePath, output); 
      fileContainer = File.ReadAllBytes(output); 
      hashcode = SHA256.Create().ComputeHash(File.ReadAllBytes(loadedFilePath)); 
      Newpassword = CreateRandomPassword(pass_txt.Text.Length); 
      Newpasswordbytes = Byteconverter.GetBytes(Newpassword); 
      RSAplain= Combine(hashcode,Newpasswordbytes); 
      RSAcipher = RSAencryption(RSAplain, RSA.ExportParameters(false), false); 
      bytestobehidden = Combine(fileContainer, RSAcipher); 
      fileSize = bytestobehidden.Length; 
      if (8 * ((height * (width/3) * 3)/3 - 1) < fileSize + fileNameSize) 
      { 
       MessageBox.Show("File size is too large!\nPlease use a larger image to hide this file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
       return; 
      } 

      StegoLayer(); 

private byte[] Combine(byte[] a, byte[] b) 
    { 
     byte[] c = new byte[a.Length + b.Length]; 
     System.Buffer.BlockCopy(a, 0, c, 0, a.Length); 
     System.Buffer.BlockCopy(b, 0, c, a.Length, b.Length); 
     return c; 
    } 

public static void EncryptFile(string password, string in_file, string out_file) 
    { 
     CryptFile(password, in_file, out_file, true); 
    } 

    public static void DecryptFile(string password, string in_file, string out_file) 
    { 
     CryptFile(password, in_file, out_file, false); 
    } 
    public static void CryptFile(string password,string in_file, string out_file, bool encrypt) 
    { 
     // Create input and output file streams. 
     using (FileStream in_stream = 
      new FileStream(in_file, FileMode.Open, FileAccess.Read)) 
     { 
      using (FileStream out_stream = 
       new FileStream(out_file, FileMode.Create, 
        FileAccess.Write)) 
      { 
       // Encrypt/decrypt the input stream into 
       // the output stream. 
       CryptStream(password, in_stream, out_stream, encrypt); 
      } 
     } 
    } 
    // Encrypt the data in the input stream into the output stream. 
    public static void CryptStream(string password, 
     Stream in_stream, Stream out_stream, bool encrypt) 
    { 
     // Make an AES service provider. 
     AesCryptoServiceProvider aes_provider = 
      new AesCryptoServiceProvider(); 

     // Find a valid key size for this provider. 
     int key_size_bits = 0; 
     for (int i = 1024; i > 1; i--) 
     { 
      if (aes_provider.ValidKeySize(i)) 
      { 
       key_size_bits = i; 
       break; 
      } 
     } 
     //Debug.Assert(key_size_bits > 0); 
     // Console.WriteLine("Key size: " + key_size_bits); 

     // Get the block size for this provider. 
     int block_size_bits = aes_provider.BlockSize; 

     // Generate the key and initialization vector. 
     byte[] key = null; 
     byte[] iv = null; 
     byte[] salt = { 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 
    0xF1, 0xF0, 0xEE, 0x21, 0x22, 0x45 }; 
     MakeKeyAndIV(password, salt, key_size_bits, block_size_bits, 
      out key, out iv); 

     // Make the encryptor or decryptor. 
     ICryptoTransform crypto_transform; 
     if (encrypt) 
     { 
      crypto_transform = aes_provider.CreateEncryptor(key, iv); 
     } 
     else 
     { 
      crypto_transform = aes_provider.CreateDecryptor(key, iv); 
     } 

     // Attach a crypto stream to the output stream. 
     // Closing crypto_stream sometimes throws an 
     // exception if the decryption didn't work 
     // (e.g. if we use the wrong password). 
     try 
     { 
      using (CryptoStream crypto_stream = 
       new CryptoStream(out_stream, crypto_transform, 
        CryptoStreamMode.Write)) 
      { 
       // Encrypt or decrypt the file. 
       const int block_size = 1024; 
       byte[] buffer = new byte[block_size]; 
       int bytes_read; 
       while (true) 
       { 
        // Read some bytes. 
        bytes_read = in_stream.Read(buffer, 0, block_size); 
        if (bytes_read == 0) break; 

        // Write the bytes into the CryptoStream. 
        crypto_stream.Write(buffer, 0, bytes_read); 
       } 
      } // using crypto_stream 
     } 
     catch 
     { 
     } 

     crypto_transform.Dispose(); 
    } 
    // Use the password to generate key bytes. 
    private static void MakeKeyAndIV(string password, byte[] salt, 
     int key_size_bits, int block_size_bits, 
     out byte[] key, out byte[] iv) 
    { 
     Rfc2898DeriveBytes derive_bytes = 
      new Rfc2898DeriveBytes(password, salt, 1000); 

     key = derive_bytes.GetBytes(key_size_bits/8); 
     iv = derive_bytes.GetBytes(block_size_bits/8); 
    } 

我嘗試提取之後將其分割,但我不能再次獲得新的關鍵,我不知道我做錯了。

+0

OK,我該如何分割提取 –

+0

後「bytestobehidden」我怎麼重視這個字節到我的形象,我怎麼在提取讀他們,給我一個例子來理解它。 –

+0

'輸出'是加密後加密文件的路徑,是的,這是我使用的'combine()'函數。 –

回答

0

您可以在bytestobehidden開始這將表明哪裏拆分流加幾個字節。例如:

fileContainer = ... 
RSAcipher = ... 

byte[] header = new byte[3]; 
int fileLength = fileContainer.Length; 
header[0] = (byte) ((fileLength >> 16) & 0xff); 
header[1] = (byte) ((fileLength >> 8) & 0xff); 
header[2] = (byte) (fileLength & 0xff); 

byte[] bytestobehidden = Combine(header, fileContainer, RSAcipher); 

其中您可以簡單地修改Combine()以接受三個字節的數組。提取你的祕密後,你就可以做

int fileLength = (int) (bytestobehidden[0] << 16) + 
       (int) (bytestobehidden[1] << 8) + 
       (int) bytestobehidden[2]; 

byte[] fileContainer = new byte[fileLength]; 
byte[] RSACipher = new byte[bytestobehidden.Length-fileLength-3]; 
System.Array.Copy(bytestobehidden, 3, fileContainer, 0, fileLength); 
System.Array.Copy(bytestobehidden, fileLength+3, RSACipher, 0, bytestobehidden.Length-fileLength-3); 

&>><<bitwise operators。你可以修改頭只有2個字節長,但你必須確保你永遠不會處理大於64KB的文件大小。另一方面,3個字節可以編碼多達16 MB的大小,我認爲就足夠了。

+0

謝謝,這段代碼對我很有用。我編輯我的代碼,當我在一次調試中進行加密和解密時,它運行良好,但是當我在加密後關閉我的應用程序並再次運行它以進行解密時。再次給我同樣的錯誤,關於'RSAdecryption()'的輸出是空的。 –

+0

雖然這可能是您項目中的後續問題,但在事情的方案中,它與此處提出的問題是分開的問題,涉及將提取的字節流拆分成部分。我建議你問一個顯示相關代碼的新問題。如果您認爲它有幫助,請隨時鏈接回這個問題。 – Reti43

相關問題