c# - 解密AES密文

标签 c# .net encryption

考虑以下测试:

    [Test]
    public void TestAes256EcbPkcs7Stream()
    {
        // 504 bytes of plain text
        const string inputString = new string('z', 504);
        var inputBytes = Encoding.UTF8.GetBytes(inputString);
        byte[] key = {
            0, 0, 0, 0, 0, 0, 0, 0,
            1, 0, 0, 0, 0, 0, 0, 0,
            2, 0, 0, 0, 0, 0, 0, 0,
            3, 0, 0, 0, 0, 0, 0, 0
        };
        var rij = new RijndaelManaged
        {
            BlockSize = 256, // 256 bits == 32 bytes
            Key = key,
            IV = key, // just for test
            Mode = CipherMode.ECB,
            Padding = PaddingMode.PKCS7
        };
        var enc = rij.CreateEncryptor();
        var encBytes = enc.TransformFinalBlock(inputBytes, 0, inputBytes.Length);
        Assert.AreEqual(512, encBytes.Length);
        var dec = rij.CreateDecryptor();
        byte[] decBytes = new byte[inputBytes.Length];
        int decPos = 0;
        using (var cipherMs = new MemoryStream(encBytes))
        {
            var buf = new byte[32];
            // process all blocks except the last one
            while (cipherMs.Read(buf, 0, buf.Length)==buf.Length &&
                cipherMs.Length!=cipherMs.Position)
            {
                for (int w = 0; w!=buf.Length;)
                {
                    w += dec.TransformBlock(buf, 0, buf.Length, decBytes, decPos);
                    decPos += w;
                }
            }
            // ensure that we read all blocks
            Assert.IsTrue(cipherMs.Length==cipherMs.Position);
            // process the last block
            var tailBytes = dec.TransformFinalBlock(buf, 0, buf.Length);
            // here decPos==480, that means 480 bytes were written to decBytes
            // and 504-480 = 24 bytes come from TransformFinalBlock
            Assert.AreEqual(24, tailBytes.Length); // <- fail, because the actual length is 56
            Buffer.BlockCopy(tailBytes, 0, decBytes, decPos, tailBytes.Length);
        }
        Assert.AreEqual(inputBytes, decBytes);
    }

出于某种原因,我得到了 56 字节的最终 block 而不是 24 字节。 我想,TransformBlock/TransformFinalBlock 应该以其他方式使用,但不幸的是,MSDN 文档对这些方法的解释不多。 有什么想法吗?

最佳答案

好的,事情是这样的: 第一次调用 TransformBlock 时,它将输入缓冲区的最后一个 block 复制到所谓的 depad 缓冲区,然后将剩余的 block 转换并写入输出缓冲区。在下一次调用期间,它从 depad 缓冲区转换数据,将其写入输出缓冲区,再次将输入缓冲区的最后一个 block 复制到 depad 缓冲区,并将转换后的剩余 block 写入输出,就像第一次一样。

TL;DR TransformBlock 缓存输入数据的最后一个 block ,因此当 TransformFinalBlock 被调用时,它可以获取最后一个 block 并删除填充。如果没有缓存,最后一个 block 可能由 TransformBlock 处理。在这种情况下,不会删除填充。

关于c# - 解密AES密文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32426898/

相关文章:

java - AES解密NodeJs中的文件

C++异或加密截断文件

c# - 带有 'same port' 的 WCF 多主机 header 导致错误

c# - 每个数据库行的 NUnit 测试?

c# - 如何将多个命名空间添加到 OData 服务中的 IEdmModel

c# - ASP.NET 的 SQL 注入(inject)过滤器方法

c# - 如何确定元组类型?

C# 更改方法的 EventArgs

c# - 无法解析/使用 System.ServiceModel.Security.WSTrustServiceContract 作为服务名称

windows - VBA:用于在注册表中存储敏感信息的用户特定 key