如何分割由不同部分组成的字节流,将它们连接在一起

本文关键字:字节流 在一起 连接 部分组 何分割 分割 | 更新日期: 2023-09-27 18:15:00

我有一个名为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);
    }

我尝试在提取后分割它,但我无法再次检索新密钥,我不知道我做错了什么

如何分割由不同部分组成的字节流,将它们连接在一起

您可以在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);

&>><<是位运算符。您可以将头文件修改为仅2字节长,但必须确保永远不会处理大于64 kB的文件。另一方面,3字节可以编码16 MB的大小,我认为这已经足够了。