C# 解密AES密码文本

C# 解密AES密码文本,c#,.net,encryption,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 = {

考虑以下测试:

    [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);
    }
[测试]
公共无效测试256ECBPKCS7STREAM()
{
//504字节的纯文本
常量字符串inputString=新字符串('z',504);
var inputBytes=Encoding.UTF8.GetBytes(inputString);
字节[]键={
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=新的RijndaelManaged
{
BlockSize=256,//256位==32字节
键=键,
IV=键,//仅用于测试
模式=CipherMode.ECB,
Padding=PaddingMode.PKCS7
};
var enc=rij.CreateEncryptor();
var encBytes=enc.TransformFinalBlock(inputBytes,0,inputBytes.Length);
AreEqual(512,encBytes.Length);
var dec=rij.CreateDecryptor();
字节[]decBytes=新字节[inputBytes.Length];
int-decPos=0;
使用(var cipherMs=新内存流(encBytes))
{
var buf=新字节[32];
//处理除最后一个块以外的所有块
while(cipherMs.Read)(buf,0,buf.Length)=buf.Length&&
密码长度!=密码位置)
{
对于(int w=0;w!=buf.Length;)
{
w+=dec.TransformBlock(buf,0,buf.Length,decBytes,decPos);
decPos+=w;
}
}
//确保我们读取了所有块
Assert.IsTrue(ciphers.Length==ciphers.Position);
//处理最后一个块
var tailBytes=dec.TransformFinalBlock(buf,0,buf.Length);
//这里decPos==480,这意味着480字节被写入decBytes
//504-480=24个字节来自TransformFinalBlock
Assert.AreEqual(24,tailBytes.Length);//好的,下面是问题:
当第一次调用
TransformBlock
时,它将输入缓冲区的最后一个块复制到所谓的depad缓冲区,然后将其余的块转换并写入输出缓冲区。在接下来的调用中,它将数据从depad缓冲区转换,写入输出缓冲区,将输入缓冲区的最后一个块复制到depad缓冲区再次,将转换后的剩余块写入输出,就像第一次一样


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

@ArtjomB纯文本大小为504b字节,480字节被解码,504-480=24字节剩余。这24字节应由TransformFinalBlock返回。另一方面,56字节不适合32字节密码块。有趣的是。请记住,使用PaddingMode.PKCS7时,504字节的起始大小将不再适用。要加密明文,密码将填充这是512字节。这将是正确的32字节块大小或更常用的16字节块大小。虽然我仍然在考虑TrimeFieldBug行为。因此,当while循环读取密文返回时,缓冲区得到最后32个字节(480—512,当我们考虑填充时)。,但while条件随后失败,因此decPos没有在那里递增。但我仍然无法了解TransformFinalBlock如何产生56个字节。我当时预计tailBytes为32,然后您将去掉填充。通常所有这些对程序员来说都是不可见的,因为您只使用CryptoStream,但它是一个I有趣的谜题。@WDS>但是while条件随后失败,因此decPos不会像预期的那样增加:last
Read()
将最后一个块放入
buf
中,在第二个条件失败后,执行继续进行下面的
TransformFinalBlock
。啊,明白了。我希望我问这个问题听起来不是很愚蠢,但你是否确认tailBytes是56字节,或者你只是得出结论?这是真正困扰我的部分,TransformFinalBlock返回的是这个大小的字节数组。我希望它返回32个字节,如果不是32,则返回64个字节(可能是因为将最后一个块转换了两次或其他原因)。您是否查看了tailBytes数组的内容?这可能会提示发生了什么,除非它都是“z”字节