package crypto import ( "bytes" "testing" ) func TestHamadryadHashDeterministic(t *testing.T) { msg := []byte("hello world") h1 := Hash(msg) h2 := Hash(msg) if h1 != h2 { t.Error("same input produced different hashes") } } func TestHamadryadHashDistinct(t *testing.T) { h1 := Hash([]byte("hello")) h2 := Hash([]byte("world")) if h1 == h2 { t.Error("different inputs produced same hash") } } func TestHamadryadHashEmpty(t *testing.T) { h := Hash([]byte{}) if h.IsZero() { t.Error("hash of empty input should not be zero") } } func TestHamadryadHashLong(t *testing.T) { // Test with input longer than one block (128 bytes). msg := bytes.Repeat([]byte("a"), 500) h := Hash(msg) if h.IsZero() { t.Error("hash of long input should not be zero") } // Changing one byte should change the hash. msg2 := make([]byte, len(msg)) copy(msg2, msg) msg2[250] = 'b' h2 := Hash(msg2) if h == h2 { t.Error("changing one byte did not change hash") } } func TestHamadryadDisperse(t *testing.T) { h := Hash([]byte("test shard extraction")) s := h.Disperse() // Shard should be the first 6 bytes of the Hamadryad. if !bytes.Equal(s[:], h[:ShardBytes]) { t.Error("Disperse did not extract first 6 bytes") } } func TestHamPackUnpack(t *testing.T) { // Create known coefficients, pack, unpack, verify round-trip. var coeffs [HamN]uint16 for i := range HamN { coeffs[i] = uint16(i) % HamR } packed := packCoeffs(coeffs) unpacked := unpackCoeffs(packed) for i := range HamN { if unpacked[i] != coeffs[i] { t.Errorf("round-trip failed at [%d]: got %d, want %d", i, unpacked[i], coeffs[i]) } } } func TestHamPackMaxValues(t *testing.T) { // All coefficients at max value (127). var coeffs [HamN]uint16 for i := range HamN { coeffs[i] = HamR - 1 } packed := packCoeffs(coeffs) unpacked := unpackCoeffs(packed) for i := range HamN { if unpacked[i] != HamR-1 { t.Errorf("[%d]: got %d, want %d", i, unpacked[i], HamR-1) } } } func TestHamadryadSum(t *testing.T) { h1 := Hash([]byte("alpha")) h2 := Hash([]byte("beta")) sum := h1.Sum(h2) // Sum should be different from both inputs. if sum == h1 || sum == h2 { t.Error("sum should differ from both inputs") } // Sum should be deterministic. sum2 := h1.Sum(h2) if sum != sum2 { t.Error("sum not deterministic") } } func TestHamadryadHashValue(t *testing.T) { // HashValue should produce consistent results for same input. h1 := HashValue(42) h2 := HashValue(42) if h1 != h2 { t.Error("HashValue not deterministic") } // Different values should produce different hashes. h3 := HashValue(43) if h1 == h3 { t.Error("different values produced same hash") } } func TestHamadryadCompress(t *testing.T) { // Verify that hamCompress produces values in Z_257. var block [hamInputBytes]byte for i := range block { block[i] = byte(i) } result := hamCompress(&block) for i, v := range result { if v >= HamP { t.Errorf("coefficient [%d] = %d, exceeds p=%d", i, v, HamP) } } } func TestHamadryadLengthExtension(t *testing.T) { // "abc" and "abc\x00" should produce different hashes. h1 := Hash([]byte("abc")) h2 := Hash([]byte("abc\x00")) if h1 == h2 { t.Error("length extension: different-length inputs produced same hash") } } func BenchmarkHamadryadHash128(b *testing.B) { msg := make([]byte, 128) for i := range msg { msg[i] = byte(i) } b.ResetTimer() for range b.N { Hash(msg) } } func BenchmarkHamadryadHash1K(b *testing.B) { msg := make([]byte, 1024) for i := range msg { msg[i] = byte(i) } b.ResetTimer() for range b.N { Hash(msg) } }