2016-10-25 4 views
0

У меня есть функция стеганографии LSB под названием Stegolayer(), на которую я отправляю данные для скрытия. Мои исходные данные зашифрованы с помощью 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

ОК, как я разделил «bytestobehidden» после извлечения –

+0

как я прикрепляю эти байты к моему изображению и как я их читаю в процессе извлечения, дайте мне пример, чтобы понять это. –

+0

«output» - это путь зашифрованного файла после шифрования, да, это функция «comb()», которую я использую. –

ответ

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 байта, но вы должны убедиться, что никогда не будете иметь дело с размерами файлов больше 64 КБ. С другой стороны, 3 байта могут кодировать размер до 16 МБ, который, как я полагаю, будет достаточным.

+0

спасибо, этот код полезен для me.i отредактировал мой код, и он работает хорошо, когда я делаю шифрование и дешифрование в одном отладке, но когда я закрываю свое приложение после создания шифрования и запускаю его снова, чтобы сделать decryption.It снова дайте мне ту же ошибку, что вывод из 'RSAdecryption() 'равен null. –

+0

Хотя это может быть проблемой в вашем проекте, в схеме вещей это отдельный вопрос из заданного здесь вопроса, который посвящен разделению извлеченного потока байтов по частям. Я предлагаю вам задать новый вопрос, показывающий соответствующий код. Не стесняйтесь ссылаться на этот вопрос, если считаете, что это помогает в контексте. – Reti43