2
考虑以下测试:解密AES密文
[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个字节的最后一个模块,而不是24个字节。 我想,TransformBlock
/TransformFinalBlock
应以其他方式使用,但不幸的是,MSDN文档没有解释太多这些方法。 有什么想法?
@ArtjomB。纯文本大小为504字节,解码480字节,剩余504-480 = 24字节。这些24个字节应该由TransformFinalBlock返回。另一方面,56字节不适合32字节的密码块。 – nitrocaster
有趣。请记住,使用PaddingMode.PKCS7,您的504字节起始大小不再适用。为了加密明文,密码将其填充到512字节。对于32字节块大小或更常用的16字节块大小,情况将会如此。我仍然在考虑TransformFinalBlock的行为。 – WDS
因此,当while循环读入密文时,缓冲区获得最后32个字节(当我们考虑填充时,为480 - 512),但while条件失败,因此decPos不会在那里增加。我仍然无法得到TransformFinalBlock如何产生56个字节。我本来预计tailBytes在这一点上是32,然后你会去掉填充。通常所有这些对程序员都是不可见的,因为你只是使用CryptoStream,但这是一个有趣的难题。 – WDS