- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我需要计算消息的 CRC 并将其放在该消息的开头,以便带有“前置”补丁字节的消息的最终 CRC 等于 0。我能够做到这在几篇文章的帮助下非常容易,但不适用于我的特定参数。问题是我必须使用给定的 CRC32 算法来计算内存块的 CRC,但我没有计算那 4 个补丁字节/“CRC 类型”的“反向”算法。给定的 CRC32 算法的参数是:
计算CRC的代码(半字节,表驱动,希望数据类型定义不言自明):
uint32 crc32tab(uint16* data, uint32 len, uint32 crc)
{
uint8 nibble;
int i;
while(len--)
{
for(i = 3; i >= 0; i--)
{
nibble = (*data >> i*4) & 0x0F;
crc = ((crc << 4) | nibble) ^ tab[crc >> 28];
}
data++;
}
return crc;
}
所需的表是(我认为短 [16] 表应该包含大 [256] 表中的每第 16 个元素,但该表实际上包含前 16 个元素,但事实就是这样提供给我):
static const uint32 tab[16]=
{
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
};
我修改了代码,使其不那么长,但功能保持不变。问题是这个正向 CRC 计算看起来更像反向/反向 CRC 计算。
我花了将近一周的时间试图找出正确的多项式/算法/表格组合,但没有成功。如果有帮助,我想出了与上面的表驱动代码相对应的按位算法,尽管这毕竟不是那么难:
uint32 crc32(uint16* data, uint32 len, uint32 crc)
{
uint32 i;
while(len--)
{
for(i = 0; i < 16; i++)
{
// #define POLY 0x04C11DB7
crc = (crc << 1) ^ (((crc ^ *data) & 0x80000000) ? POLY : 0);
}
crc ^= *data++;
}
return crc;
}
这是预期的结果 - 前 2 个 16 位字构成所需的未知 CRC,其余是已知数据本身(通过将这些示例提供给提供的算法,结果为 0)。
{0x3288, 0xD244, 0xCDEF, 0x89AB, 0x4567, 0x0123}
{0xC704, 0xDD7B, 0x0000} - append as many zeros as you like, the result is the same
{0xCEBD, 0x1ADD, 0xFFFF}
{0x81AB, 0xB932, 0xFFFF, 0xFFFF}
{0x0857, 0x0465, 0x0000, 0x0123}
{0x1583, 0xD959, 0x0123}
^ ^
| |
unknown bytes that I need to calculate
我认为在 0xFFFF 或 0x0000 字上测试这个很方便,因为计算的方向和字节顺序并不重要(我希望 :D)。所以要小心使用其他测试字节,因为计算的方向很曲折:D。您还可以看到,通过仅向算法(向前和向后)提供零,结果是所谓的残差 (0xC704DD7B),这可能会有所帮助。
所以...我写了至少 10 个不同的函数(逐位函数、表格、多项式组合等)试图解决这个问题,但没有成功。我在这里给你我寄予希望的功能。它是上面表驱动算法的“反向”算法,当然有不同的表。问题是我从中得到的唯一正确的 CRC 是全 0 消息,这并不意外。我还编写了按位算法的反向实现(反向移位等),但该算法仅正确返回第一个字节。
这是表驱动的,指向 data 的指针应该指向消息的最后一个元素,crc 输入应该是请求的 crc(整个消息的 0s 或者你也许可以采取另一种方法 - 消息的最后 4 个字节是您正在寻找的 CRC:Calculating CRC initial value instead of appending the CRC to payload):
uint32 crc32tabrev(uint16* data, uint32 len, uint32 crc)
{
uint8 nibble;
int i;
while(len--)
{
for(i = 0; i < 4; i++)
{
nibble = (*data >> i*4) & 0x0F;
crc = (crc >> 4) ^ revtab[((crc ^ nibble) & 0x0F)];
}
data--;
}
return reverse(crc); //reverse() flips all bits around center (MSB <-> LSB ...)
}
这张 table ,我希望它是“被选中的那个”:
static const uint32 revtab[16]=
{
0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC,
0x76DC4190, 0x6B6B51F4, 0x4DB26158, 0x5005713C,
0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C,
0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C
};
如您所见,此算法有一些好处,让我原地踏步,我想我可能走在正确的轨道上,但我遗漏了一些东西。我希望多一双眼睛能看到我看不到的东西。很抱歉发了这么长的帖子(没有土 bean :D),但我认为所有这些解释都是必要的。提前感谢您的见解或建议。
最佳答案
我将回答您的 CRC 规范,即 CRC-32/MPEG-2 的规范。我将不得不忽略您计算该 CRC 的尝试,因为它们不正确。
无论如何,为了回答你的问题,我碰巧写了一个解决这个问题的程序。它被称为 spoof.c
。它可以非常快速地计算出要更改消息中的哪些位以获得所需的 CRC。它按照 log(n) 时间的顺序执行此操作,其中 n 是消息的长度。这是一个例子:
让我们以九字节消息 123456789
(这些数字以 ASCII 表示)为例。我们将在它前面加上四个零字节,我们将对其进行更改以在最后获得所需的 CRC。十六进制的消息是:00 00 00 00 31 32 33 34 35 36 37 38 39
。现在我们计算该消息的 CRC-32/MPEG-2。我们得到 373c5870
。
现在我们用这个输入运行spoof
,它是以位为单位的CRC长度,它没有反射(reflect)出来的事实,多项式,我们刚刚计算的CRC,以字节为单位的消息长度,以及前四个字节中的所有 32 位位置(这是我们允许 spoof
更改的内容):
32 0 04C11DB7
373c5870 13
0 0 1 2 3 4 5 6 7
1 0 1 2 3 4 5 6 7
2 0 1 2 3 4 5 6 7
3 0 1 2 3 4 5 6 7
它为这个输出提供了前四个字节中要设置的位:
invert these bits in the sequence:
offset bit
0 1
0 2
0 4
0 5
0 6
1 0
1 2
1 5
1 7
2 0
2 2
2 5
2 6
2 7
3 0
3 1
3 2
3 4
3 5
3 7
然后我们将前四个字节设置为:76 a5 e5 b7
。然后,我们通过计算消息 76 a5 e5 b7 31 32 33 34 35 36 37 38 39
的 CRC-32/MPEG-2 进行测试,我们得到 00000000
,即所需的结果。
您可以使 spoof.c
适应您的应用程序。
下面是一个使用按位算法正确计算字节流的 CRC-32/MPEG-2 的示例:
uint32_t crc32m(uint32_t crc, const unsigned char *buf, size_t len)
{
int k;
while (len--) {
crc ^= (uint32_t)(*buf++) << 24;
for (k = 0; k < 8; k++)
crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
}
return crc;
}
并使用问题中的表格进行 nybble-wise 算法(这是正确的):
uint32_t crc_table[] = {
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
};
uint32_t crc32m_nyb(uint32_t crc, const unsigned char *buf, size_t len)
{
while (len--) {
crc ^= (uint32_t)(*buf++) << 24;
crc = (crc << 4) ^ crc_table[crc >> 28];
crc = (crc << 4) ^ crc_table[crc >> 28];
}
return crc;
}
在这两种情况下,初始 CRC 必须是 0xffffffff
。
关于CRC32 计算 CRC 消息开头的 CRC 散列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31585116/
我一直在读到,如果一个集合“被释放”,它也会释放它的所有对象。另一方面,我还读到,一旦集合被释放,集合就会释放它的对象。 但最后一件事可能并不总是发生,正如苹果所说。系统决定是否取消分配。在大多数情况
我有一个客户端-服务器应用程序,它使用 WCF 进行通信,并使用 NetDataContractSerializer 序列化对象图。 由于服务器和客户端之间传输了大量数据,因此我尝试通过微调数据成员的
我需要有关 JMS 队列和消息处理的帮助。 我有一个场景,需要针对特定属性组同步处理消息,但可以在不同属性组之间同时处理消息。 我了解了特定于每个属性的消息组和队列的一些知识。我的想法是,我想针对
我最近开始使用 C++,并且有一种强烈的冲动 #define print(msg) std::cout void print(T const& msg) { std::cout void
我已经为使用 JGroups 编写了简单的测试。有两个像这样的简单应用程序 import org.jgroups.*; import org.jgroups.conf.ConfiguratorFact
这个问题在这里已经有了答案: Firebase messaging is not supported in your browser how to solve this? (3 个回答) 7 个月前关
在我的 C# 控制台应用程序中,我正在尝试更新 CRM 2016 中的帐户。IsFaulted 不断返回 true。当我向下钻取时它返回的错误消息如下: EntityState must be set
我正在尝试通过 tcp 将以下 json 写入 graylog 服务器: {"facility":"GELF","file":"","full_message":"Test Message Tcp",
我正在使用 Django 的消息框架来指示成功的操作和失败的操作。 如何排除帐户登录和注销消息?目前,登录后登陆页面显示 已成功登录为“用户名”。我不希望显示此消息,但应显示所有其他成功消息。我的尝试
我通过编写禁用qDebug()消息 CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT 在.pro文件中。这很好。我想知道是否可以
我正在使用 ThrottleRequest 来限制登录尝试。 在 Kendler.php 我有 'throttle' => \Illuminate\Routing\Middleware\Throttl
我有一个脚本,它通过die引发异常。捕获异常时,我想输出不附加位置信息的消息。 该脚本: #! /usr/bin/perl -w use strict; eval { die "My erro
允许的消息类型有哪些(字符串、字节、整数等)? 消息的最大大小是多少? 队列和交换器的最大数量是多少? 最佳答案 理论上任何东西都可以作为消息存储/发送。实际上您不想在队列上存储任何内容。如果队列大部
基本上,我正在尝试创建一个简单的 GUI 来与 Robocopy 一起使用。我正在使用进程打开 Robocopy 并将输出重定向到文本框,如下所示: With MyProcess.StartI
我想将进入 MQ 队列的消息记录到数据库/文件或其他日志队列,并且我无法修改现有代码。是否有任何方法可以实现某种类似于 HTTP 嗅探器的消息记录实用程序?或者也许 MQ 有一些内置的功能来记录消息?
我得到了一个带有 single_selection 数据表和一个命令按钮的页面。命令按钮调用一个 bean 方法来验证是否进行了选择。如果不是,它应该显示一条消息警告用户。如果进行了选择,它将导航到另
我知道 MSVC 可以通过 pragma 消息做到这一点 -> http://support.microsoft.com/kb/155196 gcc 是否有办法打印用户创建的警告或消息? (我找不到谷
当存在大量节点或二进制数据时, native Erlang 消息能否提供合理的性能? 情况 1:有一个大约 50-200 台机器的动态池(erlang 节点)。它在不断变化,每 10 分钟大约添加或删
我想知道如何在用户登录后显示“欢迎用户,您已登录”的问候消息,并且该消息应在 5 秒内消失。 该消息将在用户成功登录后显示一次,但在同一 session 期间连续访问主页时不会再次显示。因为我在 ho
如果我仅使用Welcome消息,我的代码可以正常工作,但是当打印p->client_name指针时,消息不居中。 所以我的问题是如何将消息和客户端名称居中,就像它是一条消息一样。为什么它目前仅将消
我是一名优秀的程序员,十分优秀!