轻量级校验和算法的不错选择?

为了保持一致性,我发现自己需要为一串数据生成校验和。 广义的想法是客户端可以根据收到的有效负载重新生成校验和,从而检测传输过程中发生的任何损坏。 我隐约意识到这种事情背后有各种各样的数学原理,如果你试图自己滚动它,那么微妙的错误就很容易使整个算法失效。

所以我正在寻找有关散列/校验和算法的建议,其标准如下:

  • 它将由Javascript生成,因此需要相对较轻的计算。
  • validation将由Java完成(虽然我看不出这实际上是一个问题)。
  • 它将采用中等长度的文本输入(URL编码的Unicode,我相信是ASCII); 通常约200-300个字符,在所有情况下都低于2000。
  • 输出也应该是ASCII文本,越短越好。

我主要对轻量级的东西感兴趣,而不是让碰撞的绝对最小潜力成为可能。 我是否天真地想象一个八字符哈希适合这个? 我还应该澄清,如果在validation阶段没有发现腐败(并且我确实认为这不会100%可靠),那么它不是世界末日,尽管我的其余代码对每个代码的效率都显着降低滑倒的腐败入境。

编辑 – 感谢所有贡献。 我使用了Adler32选项并且认为它在Java中原生支持,在Javascript中非常容易实现,在两端快速计算并且具有8字节输出,这完全符合我的要求。

(请注意,我意识到网络传输不太可能对任何损坏错误负责,并且不会在此问题上折叠我的arm;但是添加校验和validation会消除一个故障点,这意味着我们可以专注于其他领域如果再次发生这种情况。)

CRC32在任何语言中都难以实现,它足以检测简单的数据损坏,并且在以良好的方式实现时,它非常快。 但是你也可以尝试Adler32,它几乎和CRC32一样好,但它更容易实现(并且速度相同)。

维基百科中的Adler32

CRC32 JavaScript实现示例

这两个(或者甚至两个)中的任何一个都可以用Java开箱即用。

是否知道TCP和UDP(以及IP,以太网和……)已经为传输中的数据提供校验和保护?

除非你做的事情非常奇怪,否则如果你看到腐败,那就是非常错误的。 我建议从内存测试器开始 。

此外,如果使用SSL / TLS,则会获得强大的数据完整性保护。

MD4,MD5和SHA1的Javascript实现 。 BSD许可证。

其他人已经提到过CRC32,但这里有一个链接到PNG的W3C CRC-32实现 ,作为少数知名的,具有参考CRC实现的信誉良好的站点之一。

(几年前,我试图找到一个着名的CRC算法网站或者至少有一个引用其算法来源的网站,并且在我找到PNG页面之前几乎撕掉了我的头发。)

[更新2013年5月30日:旧的JS CRC32实现的链接已经死亡,所以我现在已经链接到另一个。]

谷歌CRC32:速度快,重量轻于MD5等。 这里有一个Javascript实现。

在我寻找一个良好的校验和算法的JavaScript实现时,我遇到了这个问题。 Andrzej Doyle正确地选择了Adler32作为校验和,因为它确实易于实现并具有一些优秀的属性。 然后DroidOS在JavaScript中提供了一个实际的实现,它展示了简单性。

然而,该算法可以在维基百科页面中详细描述并且如下所述进一步改进。 诀窍是你不需要在每一步中确定模数。 相反,你可以推迟到最后。 这大大提高了实施速度,Chrome和Safari的速度提高了6倍。 此外,这种优化不会影响代码的可读性,使其成为双赢。 因此,它绝对符合原始问题,即具有计算轻量级的算法/实现。

function adler32(data) { var MOD_ADLER = 65521; var a = 1, b = 0; var len = data.length; for (var i = 0; i < len; i++) { a += data.charCodeAt(i); b += a; } a %= MOD_ADLER; b %= MOD_ADLER; return (b << 16) | a; } 

编辑: imaya创建了一个jsperf比较,然后显示运行简单版本时的速度差异,如DroidOS所详述,与推迟模运算的优化版本相比。 我已将名称为full-length的上述实现添加到jsperf页面,显示上述实现比imaya快了大约25%,比简单实现快了约570%(测试在Chrome 30上运行): http: //jsperf.com/adler-32-simple-vs-optimized/6

edit2:请不要忘记,在处理大型文件时,您最终会在a和b变量方面达到JavaScript实现的极限。 因此,在使用大型数据源时,应执行中间模运算,以确保不超过可以可靠存储的整数的最大值。

使用SHA-1 JS实现 。 它并不像你想象的那么慢(Core 3 Duo 2.4Ghz上的Firefox 3.0每秒哈希值超过100KB)。

这是一个我发明的相对简单的 – 它背后没有数学研究,但它非常快并且在实践中起作用。 我还包括测试算法的Java等价物,并显示10,000,000的失败几率不到1(运行需要一两分钟)。

JavaScript的

 function getCrc(s) { var result = 0; for(var i = 0; i < s.length; i++) { var c = s.charCodeAt(i); result = (result << 1) ^ c; } return result; } 

Java的

 package test; import java.util.*; public class SimpleCrc { public static void main(String[] args) { final Random randomGenerator = new Random(); int lastCrc = -1; int dupes = 0; for(int i = 0; i < 10000000; i++) { final StringBuilder sb = new StringBuilder(); for(int j = 0; j < 1000; j++) { final char c = (char)(randomGenerator.nextInt(128 - 32) + 32); sb.append(c); } final int crc = crc(sb.toString()); if(lastCrc == crc) { dupes++; } lastCrc = crc; } System.out.println("Dupes: " + dupes); } public static int crc(String string) { int result = 0; for(final char c : string.toCharArray()) { result = (result << 1) ^ c; } return result; } } 

这是一个相当古老的线程,但我怀疑它仍然经常被观看 – 如果您只需要一个简短但可靠的代码来生成校验和, Adler32位算法必须是您的选择。 这是JavaScript代码

 function adler32(data) { var MOD_ADLER = 65521; var a = 1, b = 0; for (var i = 0;i < data.length;i++) { a = (a + data.charCodeAt(i)) % MOD_ADLER; b = (b + a) % MOD_ADLER; } var adler = a | (b << 16); return adler; } 

这里有相应的小提琴使这个算法失效。