如何分割由不同部分组成的字节流,将它们连接在一起
本文关键字:字节流 在一起 连接 部分组 何分割 分割 | 更新日期: 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的大小,我认为这已经足够了。