我正在尝试使用CRC32C验证从浏览器进入我们服务器的数据。目前这两个实现都使用相同的代码(服务器上的nodeJS),但我们希望切换到硬件实现(blog post,github repo)(如果可用),为此我需要一个正确运行的版本浏览器。
我尝试使用this implementation(和另一个,内部开发,但也没有工作),但使用正确的多项式(0x82F63B78
代替0xEDB88320
,以及{{1} }& 0x1EDC6F41
)但我没有使用多项生成正确的输出。
继续我的研究,我发现了Mark Adler的帖子,其中包含一个软件实现,并决定尝试将其转换为Javascript(据我所知C)。
结果:
0x8F6E37A0
仍然没有运气。无论我使用什么函数,什么表或什么多项式,结果都不匹配:
function crc32c_table_intel() {
var POLY = 0x82f63b78;
var n, crc, k;
var crc32c_table = gen2darr(8, 256, 0);
for (n = 0; n < 256; n++) {
crc = n;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
crc32c_table[0][n] = crc;
}
for (n = 0; n < 256; n++) {
crc = crc32c_table[0][n];
for (k = 1; k < 8; k++) {
crc = crc32c_table[0][crc & 0xff] ^ (crc >> 8);
crc32c_table[k][n] = crc;
_crc_tmptable.push(crc32c_table[k][n]);
}
}
return crc32c_table;
}
function crc32c_sw(crci, str) {
var len = str.length;
var crc;
var crc32c_table = crc32c_table_intel();
crc = crci ^ 0xffffffff;
for(var next = 0; next < 7; next++) { // was: while (len && ((uintptr_t)next & 7) != 0) {
crc = crc32c_table[0][(crc ^ str.charCodeAt(next++)) & 0xff] ^ (crc >> 8);
len--;
}
while (len >= 8) {
// was: crc ^= *(uint64_t *)next;
crc ^= str.charCodeAt(next);
crc = crc32c_table[7][crc & 0xff] ^
crc32c_table[6][(crc >> 8) & 0xff] ^
crc32c_table[5][(crc >> 16) & 0xff] ^
crc32c_table[4][(crc >> 24) & 0xff] ^
crc32c_table[3][(crc >> 32) & 0xff] ^
crc32c_table[2][(crc >> 40) & 0xff] ^
crc32c_table[1][(crc >> 48) & 0xff] ^
crc32c_table[0][crc >> 56];
next += 1;
len -= 1;
}
while (len) {
// was: crc = crc32c_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
crc = crc32c_table[0][(crc ^ str.charCodeAt(next++)) & 0xff] ^ (crc >> 8);
len--;
}
return crc ^ 0xffffffff;
}
// a helper function
function gen2darr( rows, cols, defaultValue){
var arr = [];
for(var i=0; i < rows; i++){
arr.push([]);
arr[i].push( new Array(cols));
for(var j=0; j < cols; j++){
arr[i][j] = defaultValue;
}
}
return arr;
}
然后我认为它必须是从Javascript字符串转换为C / C ++数据的东西,我看到nodeJS实现使用UTF8(https://github.com/Voxer/sse4_crc32/blob/master/src/sse4_crc32.cpp#L56),而Javascript使用UCS-2编码。
现在,我的问题是:
感谢您的任何想法!
答案 0 :(得分:2)
有关兼容的软件实现和使用硬件指令的快速实现,请参阅this answer。
你有一些问题。一个是在Javascript中你需要使用逻辑右移>>>
而不是算术右移>>
。其次是您正在使用charCodeAt
,它返回一个字符的Unicode值,该值可能超过一个字节。 CRC算法对字节序列进行操作,而不是Unicode字符序列。第三,你每次都在计算相同的表 - 表只应计算一次。最后,你正在直接进入一个复杂的实现。
作为一个简单的例子,这将在Javascript中计算一个值为0..255的整数值的数组中的CRC-32C,即字节:
function crc32c(crc, bytes) {
var POLY = 0x82f63b78;
var n;
crc ^= 0xffffffff;
for (n = 0; n < bytes.length; n++) {
crc ^= bytes[n];
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
crc = crc & 1 ? (crc >>> 1) ^ POLY : crc >>> 1;
}
return crc ^ 0xffffffff;
}