/// <summary> /// Measures the predictablity of hashes generated using a given algorithm and reference data. /// </summary> /// <returns>The distance the observed entropy is from perfect. Lower is better.</returns> public double Predictability() { int total = 0; for (int i = 0; i < this.toggleBits; i++) { this.Toggle(i); int delta = this.hash.GetHashCode(this.target); int diff = Avalanche.HammingDistance(this.reference, delta); total += diff; } this.grandTotal += total; return(Avalanche.Predictability(total, this.limit)); }
public void AffineHash_Hash_Measure_Avalanche() { Random random = new Random(); var cases = new[] { new { name = "zeroes", source = Enumerable.Repeat((byte)0x00, 100).ToArray() }, new { name = "ones", source = Enumerable.Repeat((byte)0xFF, 100).ToArray() }, new { name = "alternating-right", source = Enumerable.Repeat((byte)0x55, 100).ToArray() }, new { name = "alternating-left", source = Enumerable.Repeat((byte)0xAA, 100).ToArray() }, new { name = "random", source = Enumerable.Repeat(default(byte), 100).Select(b => (byte)random.Next()).ToArray() }, }; Avalanche avalanche = new Avalanche(); this.TestContext.WriteLine("power,predictability,scale,shift"); for (int trial = 0; trial < 10000; trial++) { AffineHash target = new AffineHash(random); avalanche.Reset(target); bool strong = true; bool weak = false; foreach (var c in cases) { avalanche.Next(c.source); double predictability = avalanche.Predictability(); if (predictability > 0.1) { strong = false; } if (predictability > 0.2) { weak = true; } } if (strong) { double predictability = avalanche.Finish(); this.TestContext.WriteLine("strong,{0},{1},{2}", predictability, target.Scale, target.Shift); } if (weak) { double predictability = avalanche.Finish(); this.TestContext.WriteLine("weak,{0},{1},{2}", predictability, target.Scale, target.Shift); } } }
/// <summary> /// Finishes the avalanche series for a given algorithm. /// </summary> /// <returns>The distance the observed entropy is from perfect. Lower is better.</returns> public double Finish() { return(Avalanche.Predictability(this.grandTotal, this.grandLimit)); }