为了保持一致性,我发现自己需要为一串数据生成校验和。广义的想法是客户端可以根据收到的有效负载重新生成校验和,从而检测传输过程中发生的任何损坏。我隐约意识到这种事情背后有各种各样的数学原理,如果你试图自己滚动,那么微妙的错误就很容易使整个算法失效。
所以我正在寻找有关哈希/校验和算法的建议,其中包括以下标准:
我主要对轻量级的东西感兴趣,而不是让碰撞的绝对最小潜力成为可能。我是否天真地想象一个八字符哈希适合这个?我还应该澄清,如果在验证阶段没有发现腐败,那么这不是世界末日(而且我确实认识到这不会100%可靠),尽管我的其余代码对每个代码的效率都显着降低通过的腐败入境。
编辑 - 感谢所有贡献。我使用了Adler32选项并且认为它在Java中原生支持,在Javascript中非常容易实现,在两端快速计算并且具有8字节输出,它完全符合我的要求。
(请注意,我意识到网络传输不太可能对任何损坏错误负责,并且不会在这个问题上折叠我的手臂;但是添加校验和验证会消除一个故障点,这意味着我们可以关注在其他领域应该再次发生。)
答案 0 :(得分:14)
CRC32在任何语言中都难以实现,它足以检测简单的数据损坏,并且在以良好的方式实现时,它非常快。不过你也可以尝试Adler32,它几乎和CRC32一样好,但它实现起来更容易(并且速度相同)。
CRC32 JavaScript implementation sample
这两个中的任何一个(或者甚至两个)都可以在Java中使用。
答案 1 :(得分:6)
是否知道TCP和UDP(以及IP,以太网和......)已经为传输中的数据提供校验和保护?
除非你做的事情非常奇怪,否则如果你看到腐败,那就是非常错误的。我建议从memory tester开始。
此外,如果您使用SSL / TLS,则会获得强大的数据完整性保护。
答案 2 :(得分:2)
[更新2013年3月30日:旧JS CRC32实施的链接已经过时,所以我现在已经链接到另一个。]
Google CRC32:速度快,重量轻于MD5等。有一个Javascript实现here。
答案 3 :(得分:2)
答案 4 :(得分:2)
其他人已经提到过CRC32,但是这里是W3C implementation of CRC-32 for PNG的链接,作为少数知名的,有信誉的网站之一,参考CRC实现。
(几年前,我试图找到一个着名的CRC算法网站或者至少有一个引用其算法来源的网站,并且在我找到PNG页面之前几乎撕掉了我的头发。)< / p>
答案 5 :(得分:2)
在我搜索良好校验和算法的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 ,与推迟模运算的优化版本相比。我已将名称 全长 的上述实现添加到jsperf page,表明上述实现比中的实现速度快25% imaya 比简单实现(在Chrome 30上运行测试)快约570%:http://jsperf.com/adler-32-simple-vs-optimized/6
edit2:请不要忘记,在处理大型文件时,您最终会在a和b变量方面达到JavaScript实现的极限。因此,在使用大型数据源时,应执行中间模运算,以确保不超过可以可靠存储的整数的最大值。
答案 6 :(得分:1)
使用SHA-1 JS implementation。它并不像你想象的那么慢(Core 2 Duo 2.4Ghz上的Firefox 3.0每秒哈希值超过100KB)。
答案 7 :(得分:1)
这是一个我发明的相对简单的一个 - 它背后没有数学研究,但它非常快,并且在实践中有效。我还包括测试算法的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;
}
爪哇
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;
}
}
答案 8 :(得分:0)
这是一个相当古老的线程,但我怀疑它仍然经常被观看 - 如果您只需要一段简短但可靠的代码来生成校验和,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;
}
使用该算法的相应小提琴是here。