Javascript CRC32C实现与Intel的SSE4.2硬件实现兼容

在我开始之前,有一个免责声明:虽然我可以绕过C / C ++代码,但我并不是巫师,也没有做过足够的编程来称自己为一个有能力的程序员。

我正在尝试使用CRC32C来validation从浏览器进入我们服务器的数据。 目前这两个实现使用相同的代码(服务器上的nodeJS),但是我们希望切换到硬件实现( 博客文章 , github回购 )(如果可用),并且我需要在浏览器中正确运行的版本。

我试图去执行这个实现 (另一个,内部开发,但也没有工作),但使用正确的0xEDB883200x82F63B78而不是0xEDB88320 ,也0x1EDC6F410x8F6E37A0 ),但没有使用0x8F6E37A0产生正确的输出。

继续我的研究,我从马克·阿德勒 ( Mark Adler)那里find一篇文章,其中包括一个软件实现,并决定尝试将其转换为Javascript(以我对C的最佳理解)。

结果:

 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; } 

但是,没有运气。 不pipe用什么函数,我用什么表或什么多项式,结果都不一致:

 SSE4.2: 606105071 JS (example): 1249991249 

然后我回过头来想,它必须是从Javascriptstring转换为C / C ++数据的东西,我看到nodeJS实现使用UTF8( https://github.com/Voxer/sse4_crc32/blob/master/src/sse4_crc32.cpp #L56 )而Javascript使用UCS-2编码。

现在,我有这些问题:

  1. 这些function是否有效? 第一个看起来如此,对于我发布的一个我不确定是否我正确地翻译了所有的按位操作
  2. 如何解决编码问题? 这是甚至是一个编码问题,我怀疑? 有没有人有任何其他的想法如何确保nodeJS硬件实现和客户端实现返回相同的输出?

感谢您的任何想法!

使用硬件指令查看兼容软件实现和快速实现的答案 。

那里有几个问题。 一个是在JavaScript中,您需要使用逻辑右移>>>而不是算术右移>> 。 其次,你使用的是charCodeAt ,它返回一个字符的Unicode值,可能是多个字节。 CRCalgorithm按字节序列操作,而不是Unicode字符序列。 第三,你每次计算同一个表 – 这个表只能计算一次。 最后是你直接跳到一个复杂的实现。

作为一个简单的例子,这将在Javascript中计算CRC-32C的数值,这个值的范围应该是0到255之间的整数,即字节数:

 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; }