gpt4 book ai didi

c# - 使用 AES 在 C# 中安全传输文件

转载 作者:行者123 更新时间:2023-11-30 17:04:23 27 4
gpt4 key购买 nike

我正在尝试读取服务器上的文件(以 5KB 为单位),使用 AES 加密该 block 并将其发送到客户端。在客户端,我解密接收到的 block ,并附加到文件以取回原始文件。

但是,我在客户端收到的解密 block 大小与在服务器上加密的明文 block 不同。

例如我有一个 15.5 KB 的 exe 文件,所以我有 15.5*1024/5*1024 = 4 个 block (整数)来加密并发送给客户端(前 3 个 block 的长度为 5120 字节,最后一个 block 的长度为 512 字节)。然而,在客户端上,解密的 block 大小为 5057、4970、5016 和 512 字节,相当于 15.1 KB 的文件大小(小于服务器实际发送的大小)。

这是我的代码片段:

服务器(发送文件给客户端):

FileStream fs = new FileStream("lcd.exe", FileMode.Open, FileAccess.Read);

//block size = 5KB
int blockSize = 5 * 1024;

//calculate number of blocks in data
long numberOfBlocks = fs.Length / blockSize;

if (fs.Length % blockSize != 0) numberOfBlocks++;

byte[] numberOfBlocksBytes = BitConverter.GetBytes(numberOfBlocks);

//send number of blocks to client
SendMessage(sw, numberOfBlocksBytes);

int count = 0, offset = 0, numberOfBytesToRead=0;

Aes objAes = new Aes();

while (count < numberOfBlocks)
{
byte[] buffer;

numberOfBytesToRead = blockSize;

if (fs.Length < offset + blockSize)
{
numberOfBytesToRead = (int)(fs.Length - offset);

}

buffer = new byte[numberOfBytesToRead];

fs.Read(buffer, 0, numberOfBytesToRead);

//encrypt before sending
byte[] encryptedBuffer = objAes.Encrypt(buffer, Encoding.Default.GetBytes(sessionKey), initVector);

SendMessage(sw, encryptedBuffer);

offset += numberOfBytesToRead;

count++;

}

fs.Close();

接收文件的客户端代码:

byte[] numberOfBlocksBytes = ReadMessage(sr);

long numberOfBlocks = BitConverter.ToInt64(numberOfBlocksBytes, 0);

FileStream fs = new FileStream("lcd.exe", FileMode.Append, FileAccess.Write);

//block size = 5KB
int blockSize = 5 * 1024;

Aes objAes = new Aes();

int count = 0, offset = 0;

while (count < numberOfBlocks)
{

byte[] encryptedBuffer = ReadMessage(sr);

byte[] buffer = objAes.Decrypt(encryptedBuffer, sessionKey, initVector);

fs.Write(buffer, 0, buffer.Length);

offset += buffer.Length;

count++;

}

fs.Close();

我的加密 AES 代码:

private const int StandardKeyLength = 16;

public byte[] Encrypt(byte[] plainText, byte[] key, byte[] initVector)
{
if (key.Length != StandardKeyLength | initVector.Length != StandardKeyLength)
{
throw new ArgumentException("Key Length and Init Vector should be 16 bytes (128 bits) in size");
}

var bPlainBytes = plainText;

var objRm = new RijndaelManaged();

objRm.Key = key;
objRm.IV = initVector;
objRm.Padding = PaddingMode.PKCS7;
objRm.BlockSize = 128;

var ict = objRm.CreateEncryptor(objRm.Key, objRm.IV);

var objMs = new MemoryStream();
var objCs = new CryptoStream(objMs, ict, CryptoStreamMode.Write);

objCs.Write(bPlainBytes, 0, bPlainBytes.Length);

objCs.FlushFinalBlock();

var bEncrypted = objMs.ToArray();

return bEncrypted;
}

我的解密 AES 代码:

    public byte[] Decrypt(byte[] cipherText, byte[] key, byte[] initVector)
{
if (key.Length != StandardKeyLength | initVector.Length != StandardKeyLength)
{
throw new ArgumentException("Key Length and Init Vector should be 16 bytes (128 bits) in size");
}

var bCipherBytes = cipherText;

var objRm = new RijndaelManaged();
objRm.Key = key;
objRm.IV = initVector;
objRm.Padding = PaddingMode.PKCS7;
objRm.BlockSize = 128;

var ict = objRm.CreateDecryptor(objRm.Key, objRm.IV);
var objMs = new MemoryStream(bCipherBytes);
var objCs = new CryptoStream(objMs, ict, CryptoStreamMode.Read);

var streamobj = new StreamReader(objCs);

var strDecrypted = streamobj.ReadToEnd();

return (Encoding.Default.GetBytes(strDecrypted));
}

这些是我调试在服务器上发送文件 block 的 while 循环时得到的结果:

实际发送的文件大小:15.5 KB = 15872 字节

Buffer size(plaintext)    Encrypted Buffer Size(Sent)       Offset   Count5120                           5136                          5120      05120                           5136                         10240      15120                           5136                         15360      2 512                            528                         15872      3

这些是我调试在客户端接收文件 block 的 while 循环时得到的结果:

收到的实际文件大小:15.1 KB = 15555 字节

Received Buffersize    Decrypted Buffer Size       Offset   Count5136                           5057                 5057      05136                           4970                10027      15136                           5016                15043      2 528                            512                15555      3

很明显,发送和接收代码工作正常(因为发送的加密缓冲区大小 = 接收缓冲区大小)。然而,解密的缓冲区大小与缓冲区大小(明文)完全不匹配,除了最后一个 block 的长度为 512 字节。

解密可能有什么问题,因为我没有在客户端完全接收到文件?

最佳答案

您被绊倒了,因为在您的 Decrypt 语句中,您将密文视为一个字符串。具体来说,这些行:

var streamobj = new StreamReader(objCs);
var strDecrypted = streamobj.ReadToEnd();

return (Encoding.Default.GetBytes(strDecrypted));

相反,您希望在 CryptoStream 上调用 Read 以将原始字节数组读入缓冲区。然后,您可以返回该缓冲区,而无需尝试将其强制转换为字符串(使用流读取器会发生这种情况)。

你应该使用更像是:

public byte[] Decrypt(byte[] cipherText, byte[] key, byte[] initVector)
{
if (key.Length != StandardKeyLength | initVector.Length != StandardKeyLength)
{
throw new ArgumentException("Key Length and Init Vector should be 16 bytes (128 bits) in size");
}

var bCipherBytes = cipherText;

var objRm = new RijndaelManaged();
objRm.Key = key;
objRm.IV = initVector;
objRm.Padding = PaddingMode.PKCS7;
objRm.BlockSize = 128;

var ict = objRm.CreateDecryptor(objRm.Key, objRm.IV);
var objMs = new MemoryStream(bCipherBytes);
var objCs = new CryptoStream(objMs, ict, CryptoStreamMode.Read);

var buffer = new byte[cipherText.Length];
int readBytes = objCs.Read(buffer, 0, cipherText.Length);

var trimmedData = new byte[readBytes];
Array.Copy(buffer, trimmedData, readBytes);
return trimmedData;
}

我也建议你 t ake a look at the encryption utilities I maintain on Snipt .特别是对称加密和解密方法。您的代码目前缺少大量使用 block 和许多潜在的资源泄漏。

关于c# - 使用 AES 在 C# 中安全传输文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17488035/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com