hamadryad_test.go raw

   1  package crypto
   2  
   3  import (
   4  	"bytes"
   5  	"testing"
   6  )
   7  
   8  func TestHamadryadHashDeterministic(t *testing.T) {
   9  	msg := []byte("hello world")
  10  	h1 := Hash(msg)
  11  	h2 := Hash(msg)
  12  	if h1 != h2 {
  13  		t.Error("same input produced different hashes")
  14  	}
  15  }
  16  
  17  func TestHamadryadHashDistinct(t *testing.T) {
  18  	h1 := Hash([]byte("hello"))
  19  	h2 := Hash([]byte("world"))
  20  	if h1 == h2 {
  21  		t.Error("different inputs produced same hash")
  22  	}
  23  }
  24  
  25  func TestHamadryadHashEmpty(t *testing.T) {
  26  	h := Hash([]byte{})
  27  	if h.IsZero() {
  28  		t.Error("hash of empty input should not be zero")
  29  	}
  30  }
  31  
  32  func TestHamadryadHashLong(t *testing.T) {
  33  	// Test with input longer than one block (128 bytes).
  34  	msg := bytes.Repeat([]byte("a"), 500)
  35  	h := Hash(msg)
  36  	if h.IsZero() {
  37  		t.Error("hash of long input should not be zero")
  38  	}
  39  
  40  	// Changing one byte should change the hash.
  41  	msg2 := make([]byte, len(msg))
  42  	copy(msg2, msg)
  43  	msg2[250] = 'b'
  44  	h2 := Hash(msg2)
  45  	if h == h2 {
  46  		t.Error("changing one byte did not change hash")
  47  	}
  48  }
  49  
  50  func TestHamadryadDisperse(t *testing.T) {
  51  	h := Hash([]byte("test shard extraction"))
  52  	s := h.Disperse()
  53  
  54  	// Shard should be the first 6 bytes of the Hamadryad.
  55  	if !bytes.Equal(s[:], h[:ShardBytes]) {
  56  		t.Error("Disperse did not extract first 6 bytes")
  57  	}
  58  }
  59  
  60  func TestHamPackUnpack(t *testing.T) {
  61  	// Create known coefficients, pack, unpack, verify round-trip.
  62  	var coeffs [HamN]uint16
  63  	for i := range HamN {
  64  		coeffs[i] = uint16(i) % HamR
  65  	}
  66  
  67  	packed := packCoeffs(coeffs)
  68  	unpacked := unpackCoeffs(packed)
  69  
  70  	for i := range HamN {
  71  		if unpacked[i] != coeffs[i] {
  72  			t.Errorf("round-trip failed at [%d]: got %d, want %d", i, unpacked[i], coeffs[i])
  73  		}
  74  	}
  75  }
  76  
  77  func TestHamPackMaxValues(t *testing.T) {
  78  	// All coefficients at max value (127).
  79  	var coeffs [HamN]uint16
  80  	for i := range HamN {
  81  		coeffs[i] = HamR - 1
  82  	}
  83  
  84  	packed := packCoeffs(coeffs)
  85  	unpacked := unpackCoeffs(packed)
  86  
  87  	for i := range HamN {
  88  		if unpacked[i] != HamR-1 {
  89  			t.Errorf("[%d]: got %d, want %d", i, unpacked[i], HamR-1)
  90  		}
  91  	}
  92  }
  93  
  94  func TestHamadryadSum(t *testing.T) {
  95  	h1 := Hash([]byte("alpha"))
  96  	h2 := Hash([]byte("beta"))
  97  	sum := h1.Sum(h2)
  98  
  99  	// Sum should be different from both inputs.
 100  	if sum == h1 || sum == h2 {
 101  		t.Error("sum should differ from both inputs")
 102  	}
 103  
 104  	// Sum should be deterministic.
 105  	sum2 := h1.Sum(h2)
 106  	if sum != sum2 {
 107  		t.Error("sum not deterministic")
 108  	}
 109  }
 110  
 111  func TestHamadryadHashValue(t *testing.T) {
 112  	// HashValue should produce consistent results for same input.
 113  	h1 := HashValue(42)
 114  	h2 := HashValue(42)
 115  	if h1 != h2 {
 116  		t.Error("HashValue not deterministic")
 117  	}
 118  
 119  	// Different values should produce different hashes.
 120  	h3 := HashValue(43)
 121  	if h1 == h3 {
 122  		t.Error("different values produced same hash")
 123  	}
 124  }
 125  
 126  func TestHamadryadCompress(t *testing.T) {
 127  	// Verify that hamCompress produces values in Z_257.
 128  	var block [hamInputBytes]byte
 129  	for i := range block {
 130  		block[i] = byte(i)
 131  	}
 132  
 133  	result := hamCompress(&block)
 134  	for i, v := range result {
 135  		if v >= HamP {
 136  			t.Errorf("coefficient [%d] = %d, exceeds p=%d", i, v, HamP)
 137  		}
 138  	}
 139  }
 140  
 141  func TestHamadryadLengthExtension(t *testing.T) {
 142  	// "abc" and "abc\x00" should produce different hashes.
 143  	h1 := Hash([]byte("abc"))
 144  	h2 := Hash([]byte("abc\x00"))
 145  	if h1 == h2 {
 146  		t.Error("length extension: different-length inputs produced same hash")
 147  	}
 148  }
 149  
 150  func BenchmarkHamadryadHash128(b *testing.B) {
 151  	msg := make([]byte, 128)
 152  	for i := range msg {
 153  		msg[i] = byte(i)
 154  	}
 155  	b.ResetTimer()
 156  	for range b.N {
 157  		Hash(msg)
 158  	}
 159  }
 160  
 161  func BenchmarkHamadryadHash1K(b *testing.B) {
 162  	msg := make([]byte, 1024)
 163  	for i := range msg {
 164  		msg[i] = byte(i)
 165  	}
 166  	b.ResetTimer()
 167  	for range b.N {
 168  		Hash(msg)
 169  	}
 170  }
 171