与Intel';兼容的Javascript CRC32C实现;s SSE4.2硬件实现
在我开始之前,有一个免责声明:虽然我可以研究C/C++代码,但我不是向导,也没有做过足够的编程来称自己是一个有能力的程序员 我正在尝试使用CRC32C来验证从浏览器进入服务器的数据。目前,两种实现都使用相同的代码(服务器上的nodeJS),但我们希望切换到硬件实现(,)(如果可用),为此,我需要在浏览器中提供一个功能正常的版本 我尝试使用正确的多项式(与Intel';兼容的Javascript CRC32C实现;s SSE4.2硬件实现,javascript,node.js,polynomial-math,crc32,Javascript,Node.js,Polynomial Math,Crc32,在我开始之前,有一个免责声明:虽然我可以研究C/C++代码,但我不是向导,也没有做过足够的编程来称自己是一个有能力的程序员 我正在尝试使用CRC32C来验证从浏览器进入服务器的数据。目前,两种实现都使用相同的代码(服务器上的nodeJS),但我们希望切换到硬件实现(,)(如果可用),为此,我需要在浏览器中提供一个功能正常的版本 我尝试使用正确的多项式(0x82F63B78,而不是0xEDB88320,以及0x1EDC6F41&0x8F6E37A0),但我使用的多项式不能产生正确的输出 继续我的研
0x82F63B78
,而不是0xEDB88320
,以及0x1EDC6F41
&0x8F6E37A0
),但我使用的多项式不能产生正确的输出
继续我的研究,我找到了一篇文章,其中包括一个软件实现,并决定尝试将其转换为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;
}
然后我想这一定是从Javascript字符串到C/C++数据的转换,我看到nodeJS实现使用UTF8(),而Javascript使用UCS-2编码
现在,我的问题是:
>>
,而不是算术右移>
。第二,您使用的是charCodeAt
,它返回字符的Unicode值,该值可能超过一个字节。CRC算法在字节序列上运行,而不是在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;
}
功能crc32c(crc,字节){
变量POLY=0x82f63b78;
var n;
crc^=0xFFFFFF;
对于(n=0;n>>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;
}
返回crc^0xFFFFFF;
}
node.js自带本机散列,即使不比crc更好,也能提供相同的实用程序:('sha1'、'md5'、'sha256'、'sha512')-此外,请仔细研究一下任何js编写的函数,它们有很多,但质量和性能差别很大。不幸的是,我们没有必要使用SHA,它将在2015/16年作为扩展引入,具有以下特点。我们已经有了一个令人满意的软件实现,但我们正试图通过使用硬件实现来加快速度,因此,CRC32C。这也是为什么我开始用我的C++知识免责我的问题-我必须把你的指针转换成索引,我不确定100%我把一切都搞定了。值得注意的是,但不是唯一的:for(var next=0;next<7;next++){//was:while(len&&(uintpttr)next&7)!=0{
;crc^=str.charCodeAt(next);//was:crc^=*(uint64_*)next;
crc=crc322c表[0][(crc^str charCodeAt(next++)&0xff]^(crc>>8);
ATM我怀疑编码有问题。非常抱歉,当时我没有接受这个答案(我的特定用例需要做更多的工作,后来我忘记了),但确实有效了。@Mark:再次,请接受我的道歉。
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;
}