当前位置: 首页 > 知识库问答 >
问题:

AES加密和解密导致文件与原始文件不同

严峰
2023-03-14

我已经决定在我的服务中实现文件传输的加密。在此之前的文件传输是没有加密的,它们的发送和接收都是完美无缺的,字节数完全相同。

现在,我将非对称对称加密引入到混合加密中,以便在数据通过TCP协议时对其进行加密。我使用asymmetric进行初始握手,将symmetric密钥传递给由asymmetric公钥加密的另一方。从那时起,文件的接收方定期调用发送方,发送方生成一个新的初始化矢量,用对称密钥加密数据,并发送给接收方,由接收方使用IV和相同的对称密钥解密。

我使用的块大小为2MB,因此生成的块的字节大小为2097152(最后一个块除外)。当AES使用paddingmode.pkcs7ciphermode.cbc加密此文件时,得到的字节大小为2097168。它在加密过程中增加了大约16个字节。

最初我认为这是我的问题所在,但当我在接收端解密数据时,它会返回2097152字节长度,并将其写入文件。我已经向自己证明了它确实可以加密和解密数据。

在一个足够小的文件上,从原件到发件人的文件大小似乎完全相同。然而,当我增加到更大的文件大小时,存在一个分解。在一个大小为26,246,026字节的视频文件(wildlife.wmv来自windows 7 install),我收到的是一个已完成的传输,其大小为26,246,218字节

为什么会有这种大小差别呢?我在这里做错了什么?

这是我的一些代码。

对于我的加密,我使用以下类来加密或解密,以字节数组的形式返回结果。

public class AesCryptor
{
    public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
    {
        using (SymmetricAlgorithm aes = new AesManaged())
        {
            aes.Key = key;
            aes.IV = iv;
            aes.Padding = PaddingMode.PKCS7;
            aes.Mode = CipherMode.CBC;

            using (ICryptoTransform encryptor = aes.CreateEncryptor(key, iv))
            {
                return Crypt(data, key, iv, encryptor);
            }
        }
    }

    public byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
    {
        using (SymmetricAlgorithm aes = new AesManaged())
        {
            aes.Key = key;
            aes.IV = iv;
            aes.Padding = PaddingMode.PKCS7;
            aes.Mode = CipherMode.CBC;

            using (ICryptoTransform decryptor = aes.CreateDecryptor(key, iv))
            {
                return Crypt(data, key, iv, decryptor);
            }
        }
    }

    private byte[] Crypt(byte[] data, byte[] key, byte[] iv, ICryptoTransform transform)
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
            {
                cryptoStream.Write(data, 0, data.Length);
                cryptoStream.FlushFinalBlock();
            }
            return memoryStream.ToArray();
        }
    }
}
        byte[] buffer;
        byte[] iv = new byte[symmetricEncryptionBitSize / 8];
        using (var rngCrypto = new RNGCryptoServiceProvider())
            rngCrypto.GetBytes(iv);

        AesCryptor cryptor = new AesCryptor();

        buffer = cryptor.Encrypt(chunkedFile.NextChunk(), symmetricPrivateKey, iv);
                    FileMessage message = hostChannel.ReceiveFile();
                    moreChunks = message.FileMetaData.MoreChunks;

                    UpdateTotalBytesTransferred(message);

                    writer.BaseStream.Position = filePosition;

                    byte[] decryptedStream;

                    // Copy the message stream out to a memory stream so we can work on it afterwards.
                    using (var memoryStream = new MemoryStream())
                    {
                        message.ChunkData.CopyTo(memoryStream);
                        decryptedStream = cryptor.Decrypt(memoryStream.ToArray(), symmetricPrivateKey, message.FileMetaData.InitializationVector);
                    }

                    writer.Write(decryptedStream);

顺便说一下,如果需要的话,NextChunk是一个非常简单的方法。

        public byte[] NextChunk()
    {
        if (MoreChunks) // If there are more chunks, procede with the next chunking operation, otherwise throw an exception.
        {
            byte[] buffer;
            using (BinaryReader reader = new BinaryReader(File.OpenRead(FilePath)))
            {
                reader.BaseStream.Position = CurrentPosition;
                buffer = reader.ReadBytes((int)MaximumChunkSize);
            }
            CurrentPosition += buffer.LongLength; // Sets the stream position to be used for the next call.

            return buffer;
        }
        else
            throw new InvalidOperationException("The last chunk of the file has already been returned.");
    }

编辑:似乎每传输一个块,也就是每加密一次,我就增加了16字节的文件大小。在文件大小极小的情况下不会发生这种情况。

共有1个答案

夏知
2023-03-14

我解决了问题。

结果我在消息数据中发送了加密块数据的chunklengt。因此,对于我发送的每一个块,即使我解密并写入了正确的文件数据,我还是将流位置提前加密数据的长度。这意味着每次解密时,当传输超过1个块时(这就是为什么只有1个块大小的小文件没有问题),我会在文件大小上增加16个字节。

帮助我的人可能无法理解这一点,因为我没有包括客户端或服务器端的所有数据来查看这一点。但谢天谢地我自己回答了。

            FileMessage message = new FileMessage();
            message.FileMetaData = new FileMetaData(chunkedFile.MoreChunks, chunkedFile.ChunkLength, chunkedFile.CurrentPosition, iv);
            message.ChunkData = new MemoryStream(buffer);
using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(fileWritePath)))
            {
                writer.BaseStream.SetLength(0);

                while (moreChunks)
                {
                    FileMessage message = hostChannel.ReceiveFile();
                    moreChunks = message.FileMetaData.MoreChunks;

                    UpdateTotalBytesTransferred(message);

                    writer.BaseStream.Position = filePosition;

                    byte[] decryptedStream;

                    // Copy the message stream out to a memory stream so we can work on it afterwards.
                    using (var memoryStream = new MemoryStream())
                    {
                        message.ChunkData.CopyTo(memoryStream);
                        Debug.WriteLine("Received Encrypted buffer Length: " + memoryStream.Length);
                        decryptedStream = cryptor.Decrypt(memoryStream.ToArray(), symmetricPrivateKey, message.FileMetaData.InitializationVector);
                        Debug.WriteLine("Received Decrypted buffer Length: " + decryptedStream.Length);
                    }

                    writer.Write(decryptedStream);

                    TotalBytesTransferred = message.FileMetaData.FilePosition;

                    filePosition += message.FileMetaData.ChunkLength;
                }

                OnTransferComplete(this, EventArgs.Empty);
                StopSession();
            }

一个如此简单的虫子,但它并没有迅速地向我扑来。

 类似资料:
  • 我正在尝试用AES加密一个大文件,然后解密,与原件进行比较。 这堂课总结了工作。它适用于.txt文件,但不适用于.mp3、.pdf等文件。 我们将非常感谢你的帮助。

  • 我使用Botan库进行加密,我的加密代码如下所示。 这段代码看起来很好,可以加密输入文件。我发布这段代码是为了确定加密是否有错误。(但我假设加密做得正确)

  • 我是加密新手。这个问题是我上一个问题的子问题。我有一个用OpenSSL util加密的文件: 我用这个代码来解密它: 而且很有效。但这是一个测试案例。实际情况是,我用以下参数对文件进行了加密: openssl aes-256-cbc-nosalt-in fileIn-out fileOUT-p-k KEY 请注意,出现了'-no盐'参数。问题是PBEKeySpec需要不为空,也不为空的和参数。它也

  • 我使用以下命令加密了一个文件 openssl rand 32>test.key openssl enc-aes-256-cbc-iter 10000-pbkdf2-salt-输入test.txt-输出test.txt.enc-通过文件:test.key 我的代码 我得到的错误 我引用了以下链接 尝试使用时,仍然得到错误

  • 我需要设置一个Python进程,它能够获取特定文件夹中的每个ZIP文件,并将其解压缩,以便访问和处理其中的数据。提供ZIP文件的人显然使用Java例程来实现这一点,但由于我不懂Java(甚至不懂密码学),所以我想使用Python。他们给了我: 一个密码 一个初始化向量 他们还指定使用这种类型的命令行:

  • 我正在尝试构建一个程序,该程序接收一个文件(任意大小的EXE),对其进行加密并将其复制到一个结构中。然后稍后对其进行解密,并确保其与使用时相同。 我有一个艰难的时间加密,然后解密文件。它似乎没有正确加密,我不知道如何测试它。 以下是我的问题: 我在这里做错了什么? 是否有更好的库使用AES加密?或者我应该坚持openSSL 让我们说我想用另一个键说“你好世界”。我能不能用这个字符串作为加密算法的参