我正在尝试编写客户端软件,该软件使用c#对设备执行AES加密和解密。
使用System.Security.Cryptography中的AES类,将加密消息发送到设备没有问题。设备成功解密了这些。
解密从设备收到的消息时会出现问题。我们收到消息:“填充无效,无法删除。”
我在网上搜索并尝试了三种不同的方法,但都有相同的错误 - 见下文。我还尝试了三种方法而没有设置KeySize属性。
除了使用C#编写客户端之外,还编写了一个python客户端,其中一切正常 - 使用python aes库。 因此,有了python版本,我能够比较接收到的cipherText的长度,该长度为32字节,是一个字节数组。 15个字节是填充。 我真的很感激帮助。
Option 1
byte[] messageBuffer = null;
using (Aes aesAlg = Aes.Create())
{
aesAlg.BlockSize = 128;
aesAlg.KeySize = 128;
aesAlg.Mode = CipherMode.CBC;
aesAlg.Key = encryptionKey; //used by device to encrypt. encryptionKey is a 16 byte array
aesAlg.IV = sentIV; //This agrees with the IV that was used to encrypt the message by the device. sentIV is a 16 byte array
//aesAlg.Padding = PaddingMode.PKCS7; // this makes no difference
byte[] cipherText = encryptedMessagePart; //encryptedMessagePart is byte[] encryptedMessagePart
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
try
{
messageBuffer = decryptor.TransformFinalBlock(cipherText, 0, cipherText.Length); //****fails here ********************
}
catch (Exception ex)
{
....;
}
}
Option 2
byte[] messageBuffer = new byte [1024];
using (Aes aesAlg = Aes.Create())
{
aesAlg.BlockSize = 128;
aesAlg.KeySize = 128;
aesAlg.Mode = CipherMode.CBC;
aesAlg.Key = encryptionKey; //used by device to encrypt. encryptionKey is a 16 byte array
aesAlg.IV = sentIV; //This agrees with the IV that was used to encrypt the message by the device. sentIV is a 16 byte array
//aesAlg.Padding = PaddingMode.PKCS7; // this makes no difference
byte[] cipherText = encryptedMessagePart; //encryptedMessagePart is byte[] encryptedMessagePart
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (var msDecrypt = new MemoryStream(cipherText))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
try
{
var zx = csDecrypt.Read(messageBuffer, 0, cipherText.Length); //****fails here ********************
}
catch (Exception ex)
{
....;
}
}
}
}
Option 3
byte[] messageBuffer = new byte [1024];
using (Aes aesAlg = Aes.Create())
{
aesAlg.BlockSize = 128;
aesAlg.KeySize = 128;
aesAlg.Mode = CipherMode.CBC;
aesAlg.Key = encryptionKey; //used by device to encrypt. encryptionKey is a 16 byte array
aesAlg.IV = sentIV; //This agrees with the IV that was used to encrypt the message by the device. sentIV is a 16 byte array
//aesAlg.Padding = PaddingMode.PKCS7; // this makes no difference
byte[] cipherText = encryptedMessagePart; //encryptedMessagePart is byte[] encryptedMessagePart
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (var msDecrypt = new MemoryStream(cipherText))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
try
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
var pt = srDecrypt.ReadToEnd(); //****fails here ********************
messageBuffer = Utils.GetBytes(pt); //convert to bytes
}
catch (Exception ex)
{
....;
}
}
}
}
}
答案 0 :(得分:1)
对于密钥或邮件已损坏的任何内容,预计会出现填充错误。对于小于一个块的小消息,也可能是IV处理不正确。由于该设备似乎正在使用C#,这是最可能的原因。
使用ISO 10126 padding的可能性要小得多,但可能性很小。 PKCS#7填充消息可以使用ISO 10126 unpadding例程取消填充。然而,反之亦然,因为PKCS#7依赖于填充中的所有值是正确的,而不仅仅是最后一个。在ISO 10126填充中,只有最后一个字节表示使用的填充字节数;其他字节可以有任何值。
你当然可以随便看看。只需指示“无填充”并以十六进制打印出消息。如果消息是完全垃圾,则消息或更可能是密钥不正确。如果它看起来没问题那么你应该能够区分填充方法和最后一个字节;关于填充的维基百科文章列出了所有常见的方案。
答案 1 :(得分:1)
我通过在解密例程中非常简单地解决了这个问题,通过以下方式将填充模式显式设置为none:
aesAlg.Padding = PaddingMode.None;
在原始的python例程中,未使用填充模式。 我错误地认为,如果不声明填充模式,则填充模式将为none。 (以防万一,加密程序仅用python编写。解密程序则用Python和C#编写)