我在lua写一个Wireshark协议剖析器它分析的协议包含一个crc16校验和解剖器应该检查crc是否正确。
我发现一个用C编写的crc16实现已经使用lua包装器代码here我已经成功编译并运行了它(例如crc16.compute("test")
)问题是它需要一个字符串作为输入从wireshark,我得到了一个lua类型的缓冲区所以当我这么做的时候
crc16.compute(buffer(5, 19))
Lua抱怨
userdata
。bad argument #1 to compute (string expected, got userdata)
在crc16 implementation中如下所示:static int compute(lua_State *L)
{
const char *data;
size_t len = 0;
unsigned short r, crc = 0;
data = luaL_checklstring(L, 1, &len);
for ( ; len > 0; len--)
{
r = (unsigned short)(crc >> 8);
crc <<= 8;
crc ^= crc_table[r ^ *data];
data ++;
}
lua_pushinteger(L, crc);
return 1;
}
似乎
compute()
失败了所以我想我要么需要将输入转换成lua字符串,我不确定它是否有效,因为不是所有输入字节都必须是可打印的字符或者我需要调整上面的代码,以便它接受userdata类型的输入我找到了luaL_checklstring
,但这好像返回了一个指针所以我需要一个关于长度的第二个论证,对吧?我不一定需要使用这个实现任何接受用户数据的用于lua的crc16实现都可以完美地解决这个问题。
最佳答案
从wireshark获得的缓冲区可以用作如下ByteArray:
byte_array = Buffer(5,19):bytes();
ByteArray有一个
_toString
函数,它将字节转换为十六进制字节的字符串表示形式所以可以这样调用crc函数:crc16.compute(tostring(byte_array))
“表示为十六进制的字节”意味着位
11111111
的输入字节将变成ASCII字符串FF
ASCII字符串FF
是01000110 01000110
位或46 46
十六进制这意味着你在C里得到的,不是原来的bytearray在计算crc之前,您需要将ascii表示解码回原始字节,否则我们显然会得到不同的crc。首先,此函数将包含一个ascii十六进制字符的单个字符
c
转换回它所表示的值:static char ascii2char(char c) {
c = tolower(c);
if(c >= '0' && c <= '9')
return c - '0';
else if(c >= 'a' && c <= 'f')
return c - 'a' + 10;
}
现在在compute函数中,我们循环遍历字符串表示,总是将两个字符组合成一个字节。
int compute(lua_State *L) {
size_t len;
const char * str = lua_tolstring(L, 1, &len);
uint8_t * data = (uint8_t *) malloc(len/2);
for(int n=0; n<len/2; n++) {
data[n] = ascii2char(str[2*n]) << 4;
data[n] |= ascii2char(str[2*n+1]);
}
crc16_t crc = crc16_init();
crc = crc16_update(crc, data, len/2);
crc = crc16_finalize(crc);
lua_pushinteger(L, crc);
free(data);
return 1;
}
在本例中,我使用了使用pycrc生成的crc函数
crc16_init
、crc16_update
和crc16_finalize
,而不是问题中链接的crc实现问题是在生成crc时需要使用相同的多项式等Pycrc允许您根据需要生成crc函数。我的包里还有一个crc32Pycrc还可以为crc32生成代码,因此它对crc32的工作方式完全相同。
关于c - 在lua中计算字节数组/用户数据的crc16,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43211281/