从文件加密数据,并通过MemoryStream(byte [])使用C#/ .Net在套接字上发送 [英] Encrypting data from file and sending on a socket via MemoryStream( byte[] ) using C# / .Net

查看:337
本文介绍了从文件加密数据,并通过MemoryStream(byte [])使用C#/ .Net在套接字上发送的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个套接字服务器需要将加密的二进制文件传输给连接的客户端。
这些文件需要加密,最好是不使用将磁盘上的文件复制到磁盘上。

We have a sockets server that needs to transfer encrypted binary files to connected clients. The files need to be encrypted when requests for them arrive, preferably without making encrypted copies of files on disk first.

事实上我们使用异步套接字API,Sockets.NetworkStream 不能被使用。相反,我们需要使用带有byte []缓冲区的Socket.BeginSend()作为输入。

Due to the fact that we use asynchronous sockets API, Sockets.NetworkStream cannot be used. Instead, we need to utilize Socket.BeginSend() with a byte[] buffer as the input.

看起来很直接的可能性是将CryptoStream与MemoryStream一起使用加密内容的目的地。 MemoryStream本身将使用byte []缓冲区作为自己的数据存储库。

A seemingly straight forward possibility is to use CryptoStream with a MemoryStream as its destination for encrypted content. MemoryStream itself would use a byte [] buffer as its own data repository.

例如:

int blockSizeBytes = 1024 * 64;
byte [] plainData = new byte [blockSizeBytes];
byte [] encData = new byte [blockSizeBytes];
MemoryStream memory = new MemoryStream( encData );

ICryptoTransform encryptor = ... any ***CryptoServiceProvider.CreateEncryptor();
CryptoStream csEnc = new CryptoStream( memory, encryptor, CryptoStreamMode.Write );

文件可以一次读取和加密缓冲区,然后通过套接字发送给客户例如:

A file can be read and encrypted a buffer at a time, which would then be sent over the socket to the client. For example:

Socket clientSocket = ...; // connected peer.
int bytesRead = 0;
FileStream streamIn = new FileStream( strInputFile, FileMode.Open );
do
{
    bytesRead = streamIn.Read( plainData , 0, blockSizeBytes );
    if (bytesRead > 0)
    {
        csEnc.Write( plainData , 0, bytesRead );   // Write to crypto stream

        // At this point the underlying byte array encData will hold the most recently
        // encrypted buffer of data.

        // Ideally we would send the encData buffer over the socket to the client via 
        // the following pseudo-code:

        // 1) How can we determine the precise number of encoded bytes to send?
        clientSocket.BeginSend( encData, 0, bytesRead, ... /* other params */ );

        ...

        memory.Seek( 0, SeekOrigin.Begin );  // Reset memory stream back to start
    }
}
while (bytesRead > 0);

streamIn.Close();  // close intput file stream

outEnc.FlushFinalBlock();  // Deal with padding, etc.

// Send the final buffer with all the necessary padding to the client.
// 2) Again, how can we determine the exact number of encoded bytes to send?
clientSocket.BeginSend( encData, 0, ??how-many-bytes??, ... );

outEnc.Close();

为了测试目的,我们将编码的缓冲区写入文件而不是套接字。当尝试解密生成的文件时,会抛出以下异常: CryptographicException:要解密的数据的长度无效。

For testing purposes we wrote out the encoded buffers to file instead of the socket. When trying to decrypt the resulting file, the following exception is thrown: CryptographicException: Length of the data to decrypt is invalid.

可以在上面的项目1)和2)中,我们不知道要传送到客户端的编码字节的精确数量(或保存到文件)。我们尝试将memory.Position作为FlushFinalBlock()之后的缓冲区大小,虽然没有成功。

As can be seen in items 1) and 2) above, we don't know the precise number of encoded bytes to transfer to the client (or save to a file). We tried memory.Position as the buffer size after FlushFinalBlock(), though without success.

请注意,当CryptoStream使用FileStream作为其输出时,即MemoryStream也不使用byte []缓冲区,生成的文件被正常加密,然后成功解密。但是,我们的目标是能够直接写出加密的byte []缓冲区,而不需要输出流。

Please note, when CryptoStream is using a FileStream for its output, i.e., neither MemoryStream nor byte[] buffers are used, the resulting file is encrypted normally and then subsequently decrypted successfully. Our goal, though, is to be able to write out encrypted byte[] buffers directly without output streams.

如果具有byte []缓冲区的MemoryStream不可行,那么其他的替代方案是能够缓存缓冲区并将其转发,例如socket?

If MemoryStream with byte[] buffer is not feasible, are there other alternatives to be able to incrementally encrypt buffers and forward them on, e.g., socket?

推荐答案

code> memory.Position 作为计数参数 clientSocket.BeginSend(...)方法,并且能够成功地往返(即加密然后解密加密的数据)。如果这不适合你,那么值得提供一个完整的,独立的,可编译的例子来代表这个问题的代码。

I've tested this using memory.Position as the Count parameter in both clientSocket.BeginSend(...) methods, and was able to round-trip (i.e. encrypt then decrypt the encrypted data) successfully. If this isn't working for you, it'd be worth providing code for a complete, self-contained, compilable example that demonstrates the issue.

这篇关于从文件加密数据,并通过MemoryStream(byte [])使用C#/ .Net在套接字上发送的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆