我们正在开发一个应用程序,该应用程序必须处理由 LoraWan ( https://www.lora-alliance.org )加密的数据
我们已经找到了他们如何加密数据的文档,并且在过去的几天里一直在阅读它(https://www.lora-alliance.org/sites/default/files/2018-04/lorawatm_specification_-v1 .1.pdf ) 但目前仍然无法解决我们的问题。
我们必须使用带有零填充的 AES 128 位 ECB 解密来解密消息,但问题是它不起作用,因为我们收到的加密消息对于 AES 128 来说不够长,因此算法返回“数据不是完成块”的最后一行异常。
我们收到的一个示例密钥是这样的:D6740C0B8417FF1295D878B130784BC5(不是真正的密钥)。它是 32 个字符长,因此是 32 个字节,但如果将其视为十六进制,则它变为 16 个字节长,这是 AES 128 位所需要的。这是我们用来从字符串转换十六进制的代码:
public static string HextoString(string InputText)
{byte[] hex= Enumerable.Range(0, InputText.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(InputText.Substring(x, 2), 16))
.ToArray();
return System.Text.Encoding.ASCII.GetString(hex);}
(上面代码需要注意的一点是,我们不确定要使用什么编码,因为我们在 Lora 文档中找不到它并且他们没有告诉我们,但是根据这个小设置,我们可能会搞砸我们的解密(尽管我们已经尝试了所有可能的组合,ascii、utf8、utf7 等))
我们收到的示例消息是:d3 73 4c,我们假设它也是十六进制的。这只有 6 个字节,如果我们将其从十六进制转换为普通字节,则需要 3 个字节,而我们需要最少的 16 个字节来匹配密钥长度。
这是我们正在使用的 Aes 128 解密代码:
private static string Aes128Decrypt(string cipherText, string key){
string decrypted = null;
var cipherPlainTextBytes = HexStringToByteArray(cipherText);
//var cipherPlainTextBytes = ForcedZeroPadding(HexStringToByteArray(cipherText));
var keyBytes = HexStringToByteArray(key);
using (var aes = new AesCryptoServiceProvider())
{
aes.KeySize = 128;
aes.Key = keyBytes;
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.Zeros;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream ms = new MemoryStream(cipherPlainTextBytes, 0, cipherPlainTextBytes.Length))
{
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs))
{
decrypted = sr.ReadToEnd();
}
}
}
}
return decrypted;}
所以很明显这将在 sr.ReadToEnd() 处返回“数据是一个不完整的块”。
正如您从示例中看到的那样,在注释掉的行中,我们还尝试使用正确长度的完整零字节数组(16 - cipherText)将文本“填充”到正确的大小,在这种情况下,算法运行很好,但它返回完整的乱码,而不是原始文本。
我们已经尝试了所有的操作模式,并且也使用了填充模式。除了密文和该文本的密钥,他们没有为我们提供任何东西。也没有初始化向量,所以我们假设我们应该每次都生成它(但对于 ECB,它甚至不需要 iirc)
更重要的是,他们能够很好地加密-解密他们的消息。最令人费解的是,我已经用谷歌搜索了好几天了,我在 google 上找不到一个 SINGLE 示例,其中 CIPHERTEXT 在解密期间比密钥短。
显然,我发现了他们正在加密的消息比所需消息短的示例,但这就是加密端的填充(对吗?)。这样当您收到填充消息时,您可以告诉算法使用什么填充模式使其长度正确,这样它就可以将填充与消息分开。但在所有这些情况下,解密期间收到的消息的长度都是正确的。
所以问题是——我们做错了什么?有没有办法用比密钥短的密文解密?还是他们通过生成太短的密码而在某个地方搞砸了?
谢谢你的帮助。