网络流上的对称加密(TCP 套接字)

时间:2021-01-07 06:16:22

标签: c# encryption tcp tcpclient networkstream

我正在开发一个简单的程序,它充当客户端和 HTTP 代理服务器之间的代理,当使用简单的 Stream.copytoasync 函数时,我在从客户端到代理交换数据并返回时没有问题。我尝试使用以下代码修改函数以添加简单的对称加密:

对于加密(客户端,从客户端流复制到服务器流):

public static async Task CopyEncrypt(this Stream source, Stream destination,string encryption_key, CancellationToken cancellationToken = default(CancellationToken), int bufferSize = 0x1000)
        {
            var buffer = new byte[bufferSize];
            int bytesRead;            
            while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
            {
               
                byte[] eca = Encrypt(buffer, encryption_key); 
                await destination.WriteAsync(eca, 0, eca.Length, cancellationToken);
                cancellationToken.ThrowIfCancellationRequested();                
            }
        }

用于解密(服务器端,取客户端发送的数据,转发给http代理):

public static async Task CopyDecrypt(this Stream source, Stream destination,string aeskey, CancellationToken cancellationToken = default(CancellationToken), int bufferSize = 0x1000)
        {
            var buffer = new byte[bufferSize];
            int bytesRead;            
            while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
            {

                byte[] eca = Decrypt(buffer, aeskey);
                await destination.WriteAsync(eca, 0, eca.Length, cancellationToken);
                cancellationToken.ThrowIfCancellationRequested();
            }
        }

我尝试了多种加密/解密功能,包括 AES、TripleDES、Rijndael。每当将这些与填充一起使用时,我通常会在解密时收到以下错误(对加密和解密使用相同的填充):

Padding is invalid and cannot be removed

在没有任何填充的情况下使用时,数据会被解密,但由于在发送标头后通过 HTTP 代理的过程失败,因此数据似乎没有正确/完整地传输。

虽然该过程在没有加密的情况下可以正常使用以下功能:

对于加密:

public static async Task CopyEncrypt(this Stream source, Stream destination,string encryption_key, CancellationToken cancellationToken = default(CancellationToken), int bufferSize = 0x1000)
        {
            var buffer = new byte[bufferSize];
            int bytesRead;

            while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
            {

                
                await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken);
                cancellationToken.ThrowIfCancellationRequested();

            }
        }

用于解密:

public static async Task CopyDecrypt(this Stream source, Stream destination,string aeskey, CancellationToken cancellationToken = default(CancellationToken), int bufferSize = 0x1000)
        {
            var buffer = new byte[bufferSize];
            int bytesRead;

            while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
            {

                await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken);
                cancellationToken.ThrowIfCancellationRequested();

            }
        }

1 个答案:

答案 0 :(得分:0)

您的 Encrypt/Decrypt 函数的签名让我相信他们试图将每个缓冲区视为一条完整的消息。这意味着将向每个缓冲区添加任何填充。

当您使用流时,您需要加密/解密为流。这样,任何填充都只会出现在流的末尾。

最简单的方法是使用 CryptoStream,然后您可以像复制常规流一样复制加密流。