Encryption 使用比密钥短的密文进行AES 128解密

Encryption 使用比密钥短的密文进行AES 128解密,encryption,aes,block-cipher,key,Encryption,Aes,Block Cipher,Key,我们正在开发一个应用程序,该应用程序必须处理由LoraWan()提取的数据 我们已经找到了他们如何加密数据的文档,并且在过去几天里一直在阅读这些文档(),但目前仍然无法解决我们的问题 我们必须使用带零填充的AES 128位ECB解密来解密消息,但问题是它不起作用,因为我们接收的加密消息的长度不够AES 128,因此算法在最后一行返回“数据不是完整块”异常 我们收到的示例密钥如下:D6740C0B8417FF1295D878B130784BC5(不是真正的密钥)。它的长度是32个字符,所以是32个

我们正在开发一个应用程序,该应用程序必须处理由LoraWan()提取的数据

我们已经找到了他们如何加密数据的文档,并且在过去几天里一直在阅读这些文档(),但目前仍然无法解决我们的问题

我们必须使用带零填充的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等))

我们收到的一个示例消息是:D3734C,我们假设它也是十六进制的。这只有6个字节,如果我们将其从hexa转换为normal,则为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-密文)将文本“填充”到正确的大小,在这种情况下,算法运行良好,但它返回的是完全乱码,而不是原始文本

我们已经试过了所有的操作模式,也弄乱了填充模式。他们只给我们提供了密文和该文本的密钥。也没有初始化向量,所以我们假设每次都要生成它(但对于ECB,甚至不需要iirc)

更重要的是,他们能够很好地加密和解密他们的消息。最令人费解的是,我已经在谷歌上搜索了好几天了,我在谷歌上找不到一个例子,在解密过程中,密文比密钥短

显然,我发现了一些示例,其中他们正在加密的消息比需要的短,但这就是加密端填充的作用(对吗?)。因此,当您收到填充消息时,您可以告诉算法使用了什么填充模式使其长度正确,这样它就可以将填充与消息分开。但在所有这些情况下,解密过程中接收到的消息长度都是正确的

所以问题是——我们做错了什么?有没有办法用比密钥短的密文解密?或者他们是不是因为密码太短而把事情搞砸了


谢谢您的帮助。

在AES-ECB中,只有小于16字节的有效密文是空的。16字节的限制是AES的块(不是键)大小,它恰好与AES-128的键大小匹配

因此,问题是

我们收到的一个示例消息是:D373 4c

不显示ECB加密的消息(因为a告诉它来自JSON,所以不能是碰巧显示为十六进制的字节)。这太短了,不能作为联接接受的FRMPayload(根据此),因为后者说:

1625
消息的长度为16或32字节

是否JSON消息包含的内容不是完整的FRMPayload,而是数据包的一个片段,用空格分隔符编码为十六进制对?只要不知道如何构建FRMPayload,就没有必要破译它

更新:如果神秘消息始终为3个字节,并且对于给定的密钥始终相同(或每个密钥可用一次),则根据Maarten Bodewes的,它可能是一个密钥检查值。KCV通常是使用原始分组密码的密钥对所有零值进行加密的前3个字节(相当于:每个ECB)。可以完全脱机工作(这是不公开密钥所必需的),并可用于手动验证假设。它告诉我们,对于问题中给出的16字节密钥,KCV将是
cd15e1
(或
c076fc
,根据下一节中的变量)


另外:它还用于
CreateDecryptor
制作一个负责ECB解密的gizmo。这在LoraWan有效载荷解密的情况下可能是不正确的,这需要ECB加密来解密某些字段:

1626
注意:ECB模式下的AES解密操作用于加密加入接受消息,以便终端设备可以使用AES加密操作解密消息。这样,终端设备只需实现AES加密,而不必实现AES解密


在LoraWan数据包解密的上下文中,您希望使用字节数组而不是字符串与AES引擎通信。当LoraWan密文和相应的明文没有编码时,字符串有编码。似乎已经成功地迫使nice.netdo-it-all-crypto API完成了底层工作


HextoString
代码中,我模模糊糊地了解到,
hex
作为字节数组成为最初的十六进制输入(完全消除十六进制和其他编码错误;在这种情况下,变量
hex
应该重命名为
纯字节
的某个部分)。但是我对
System.Text.Encoding.ASCII.GetString(hex)
一无所知。如果真是这样,我会很惊讶的