【发布时间】:2015-03-14 02:19:00
【问题描述】:
我正在尝试读取文件,对其进行加密,然后通过套接字将其发送到服务器,并在那里写入。然后反过来,在服务器上读取,发送给客户端,解密,再写入。
我使用 C# Aes 类的问题是,输入大小不等于输出大小。
例如,当我从文件中读取 4096 字节时,输出大小为 4112 字节,多出 16 字节。好的,所以在服务器上发送和写入了 4112 个字节,但是当我再次获取文件时,我只能通过套接字发送最多 4096 个字节,然后,当然,客户端上的解密函数会抛出异常,即填充无效,无法删除。当然,我可以尝试在客户端读取更少的字节,但这也不起作用。
我是一位非常有经验的 C++ 程序员,我已经使用 OpenSsl 完成了这项工作,它的工作原理非常棒。输入大小一直是输出大小,我不知道我在 C# 中的函数有什么问题。
这是发送部分:
byte[] SendData = new byte[4096];
iBytesRead = FileRead.Read (SendData, 0, 4096);
SendData = aes.encrypt (Encoding.Default.GetString (SendData, 0, iBytesRead), iBytesRead);
String a = aes.decrypt (SendData); // no problems here because the size is correct
Socket.sendB (SendData, SendData.Length);
以及从服务器接收的部分:
byte[] WriteData = new byte[4096],
Temp;
if ((iBytesReceived = Socket.receiveB (ref WriteData)) == 0)
break;
if (Encoding.ASCII.GetString (WriteData, 0, iBytesReceived) == "end")
break;
for (uint i = 0; i < iBytesReceived; i++)
Temp[i] = WriteData[i];
byte[] a = Encoding.Default.GetBytes (aes.decrypt (Temp));
FileWrite.Write (a, 0, Temp.Length);
Aes 函数:
public byte[] encrypt(String _InStr, int _InStrLength)
{
if (!bKeySet)
return ErrorReturn;
byte[] encrypted;
using (Aes aes = Aes.Create ())
{
aes.Key = Key;
aes.IV = IV;
//aes.Padding = PaddingMode.PKCS7;
//aes.BlockSize = 128;
//aes.KeySize = 128;
//aes.Mode = CipherMode.CFB;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
// Create the streams used for encryption.
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(_InStr);
}
}
ms.Close ();
encrypted = ms.ToArray ();
}
}
return encrypted;
}
public String decrypt(byte[] _InStr)
{
if (!bKeySet)
return "";
String plaintext;
using (Aes aes = Aes.Create ())
{
aes.Key = Key;
aes.IV = IV;
//aes.Padding = PaddingMode.PKCS7;
//aes.BlockSize = 128;
//aes.KeySize = 128;
//aes.Mode = CipherMode.CBC;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(_InStr))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
plaintext = srDecrypt.ReadToEnd ();
}
}
}
}
return plaintext;
}
【问题讨论】:
-
使用 NoPadding 时,输入大小只能等于输出大小。 PKCS7Padding 总是产生 1-16 个额外字节(对于 AES)来填充到 16 的倍数。因此您可能会尝试读取 4095 字节而不是 4096。目前尚不清楚为什么不能使用较小的缓冲区。
-
@ArtjomB。然后我在加密函数中得到这个:
The input data is not a complete block
标签: c# sockets encryption aes