github.com/onflow/flow-go/crypto@v0.24.8/hash/hash_test.go (about) 1 package hash 2 3 import ( 4 "crypto/rand" 5 "crypto/sha256" 6 "crypto/sha512" 7 "encoding/hex" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 "golang.org/x/crypto/sha3" 13 ) 14 15 // Sanity check of SHA3_256 16 func TestSanitySHA3_256(t *testing.T) { 17 input := []byte("test") 18 expected, _ := hex.DecodeString("36f028580bb02cc8272a9a020f4200e346e276ae664e45ee80745574e2f5ab80") 19 20 alg := NewSHA3_256() 21 hash := alg.ComputeHash(input) 22 assert.Equal(t, Hash(expected), hash) 23 } 24 25 // Sanity check of SHA3_384 26 func TestSanitySHA3_384(t *testing.T) { 27 input := []byte("test") 28 expected, _ := hex.DecodeString("e516dabb23b6e30026863543282780a3ae0dccf05551cf0295178d7ff0f1b41eecb9db3ff219007c4e097260d58621bd") 29 30 alg := NewSHA3_384() 31 hash := alg.ComputeHash(input) 32 assert.Equal(t, Hash(expected), hash) 33 } 34 35 // Sanity check of SHA2_256 36 func TestSanitySHA2_256(t *testing.T) { 37 input := []byte("test") 38 expected, _ := hex.DecodeString("9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08") 39 40 alg := NewSHA2_256() 41 hash := alg.ComputeHash(input) 42 assert.Equal(t, Hash(expected), hash) 43 } 44 45 // Sanity check of SHA2_384 46 func TestSanitySHA2_384(t *testing.T) { 47 input := []byte("test") 48 expected, _ := hex.DecodeString("768412320f7b0aa5812fce428dc4706b3cae50e02a64caa16a782249bfe8efc4b7ef1ccb126255d196047dfedf17a0a9") 49 50 alg := NewSHA2_384() 51 hash := alg.ComputeHash(input) 52 assert.Equal(t, Hash(expected), hash) 53 } 54 55 // Sanity check of Keccak_256 56 func TestSanityKeccak_256(t *testing.T) { 57 input := []byte("test") 58 expected, _ := hex.DecodeString("9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658") 59 60 alg := NewKeccak_256() 61 hash := alg.ComputeHash(input) 62 assert.Equal(t, Hash(expected), hash) 63 } 64 65 // Sanity checks of KMAC128 66 // the test vector is taken from the NIST document 67 // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/Kmac_samples.pdf 68 func TestSanityKmac128(t *testing.T) { 69 70 input := []byte{0x00, 0x01, 0x02, 0x03} 71 expected := []Hash{ 72 {0xE5, 0x78, 0x0B, 0x0D, 0x3E, 0xA6, 0xF7, 0xD3, 0xA4, 0x29, 0xC5, 0x70, 0x6A, 0xA4, 0x3A, 0x00, 73 0xFA, 0xDB, 0xD7, 0xD4, 0x96, 0x28, 0x83, 0x9E, 0x31, 0x87, 0x24, 0x3F, 0x45, 0x6E, 0xE1, 0x4E}, 74 {0x3B, 0x1F, 0xBA, 0x96, 0x3C, 0xD8, 0xB0, 0xB5, 0x9E, 0x8C, 0x1A, 0x6D, 0x71, 0x88, 0x8B, 0x71, 75 0x43, 0x65, 0x1A, 0xF8, 0xBA, 0x0A, 0x70, 0x70, 0xC0, 0x97, 0x9E, 0x28, 0x11, 0x32, 0x4A, 0xA5}, 76 } 77 key := []byte{0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 78 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F} 79 customizers := [][]byte{ 80 []byte(""), 81 []byte("My Tagged Application"), 82 } 83 outputSize := 32 84 85 alg, err := NewKMAC_128(key, customizers[0], outputSize) 86 require.Nil(t, err) 87 _, _ = alg.Write(input[0:2]) 88 _, _ = alg.Write(input[2:]) 89 hash := alg.SumHash() 90 assert.Equal(t, expected[0], hash) 91 92 for i := 0; i < len(customizers); i++ { 93 alg, err = NewKMAC_128(key, customizers[i], outputSize) 94 require.Nil(t, err) 95 hash = alg.ComputeHash(input) 96 assert.Equal(t, expected[i], hash) 97 } 98 99 // test short key length 100 _, err = NewKMAC_128(key[:15], customizers[0], outputSize) 101 assert.Error(t, err) 102 } 103 104 // TestHashersAPI tests the expected definition of the hashers APIs 105 func TestHashersAPI(t *testing.T) { 106 107 newKmac128 := func() Hasher { 108 kmac, err := NewKMAC_128([]byte("test_key________"), []byte("test_custommizer"), 32) 109 if err != nil { 110 panic("new kmac hasher failed") 111 } 112 return kmac 113 } 114 115 newHasherFunctions := [](func() Hasher){ 116 NewSHA2_256, 117 NewSHA2_384, 118 NewSHA3_256, 119 NewSHA3_384, 120 newKmac128, 121 NewKeccak_256, 122 } 123 124 data := make([]byte, 1801) 125 _, err := rand.Read(data) 126 require.NoError(t, err) 127 128 for _, newFunction := range newHasherFunctions { 129 // Reset should empty the state 130 h := newFunction() 131 expectedEmptyHash := h.SumHash() 132 _, _ = h.Write(data) 133 h.Reset() 134 emptyHash := h.SumHash() 135 assert.Equal(t, expectedEmptyHash, emptyHash) 136 137 // SumHash on an empty state is equal to compute hash with empty data 138 emptyHash = h.ComputeHash(nil) 139 assert.Equal(t, expectedEmptyHash, emptyHash) 140 141 // successive writes of data are equivalent to compute hash 142 // of the concatenated data 143 h = newFunction() 144 hash1 := h.ComputeHash(data) 145 146 h.Reset() 147 _, _ = h.Write(data[:355]) 148 _, _ = h.Write(data[355:902]) 149 _, _ = h.Write(data[902:]) 150 hash2 := h.SumHash() 151 assert.Equal(t, hash1, hash2) 152 153 // ComputeHash output does not depend on the hasher state 154 h = newFunction() 155 156 _, _ = h.Write([]byte("dummy data")) 157 hash1 = h.ComputeHash(data) 158 assert.Equal(t, hash1, hash2) 159 } 160 } 161 162 // TestSHA2 is a specific test of SHA2-256 and SHA2-384. 163 // It compares the hashes of random data of different lengths to 164 // the output of standard Go sha2. 165 func TestSHA2(t *testing.T) { 166 167 t.Run("SHA2_256", func(t *testing.T) { 168 for i := 0; i < 5000; i++ { 169 value := make([]byte, i) 170 _, err := rand.Read(value) 171 require.NoError(t, err) 172 expected := sha256.Sum256(value) 173 174 // test hash computation using the hasher 175 hasher := NewSHA2_256() 176 h := hasher.ComputeHash(value) 177 assert.Equal(t, expected[:], []byte(h)) 178 179 // test hash computation using the light api 180 var res [HashLenSHA2_256]byte 181 ComputeSHA2_256(&res, value) 182 assert.Equal(t, expected[:], res[:]) 183 } 184 }) 185 186 t.Run("SHA2_384", func(t *testing.T) { 187 for i := 0; i < 5000; i++ { 188 value := make([]byte, i) 189 _, err := rand.Read(value) 190 require.NoError(t, err) 191 expected := sha512.Sum384(value) 192 193 hasher := NewSHA2_384() 194 h := hasher.ComputeHash(value) 195 assert.Equal(t, expected[:], []byte(h)) 196 } 197 }) 198 } 199 200 // TestSHA3 is a specific test of SHA3-256 and SHA3-384. 201 // It compares the hashes of random data of different lengths to 202 // the output of standard Go sha3. 203 func TestSHA3(t *testing.T) { 204 t.Run("SHA3_256", func(t *testing.T) { 205 for i := 0; i < 5000; i++ { 206 value := make([]byte, i) 207 _, err := rand.Read(value) 208 require.NoError(t, err) 209 expected := sha3.Sum256(value) 210 211 // test hash computation using the hasher 212 hasher := NewSHA3_256() 213 h := hasher.ComputeHash(value) 214 assert.Equal(t, expected[:], []byte(h)) 215 216 // test hash computation using the light api 217 var res [HashLenSHA3_256]byte 218 ComputeSHA3_256(&res, value) 219 assert.Equal(t, expected[:], res[:]) 220 } 221 }) 222 223 t.Run("SHA3_384", func(t *testing.T) { 224 for i := 0; i < 5000; i++ { 225 value := make([]byte, i) 226 _, err := rand.Read(value) 227 require.NoError(t, err) 228 expected := sha3.Sum384(value) 229 230 hasher := NewSHA3_384() 231 h := hasher.ComputeHash(value) 232 assert.Equal(t, expected[:], []byte(h)) 233 } 234 }) 235 } 236 237 // TestKeccak is a specific test of Keccak-256. 238 // It compares the hashes of random data of different lengths to 239 // the output of Go LegacyKeccak. 240 func TestKeccak(t *testing.T) { 241 for i := 0; i < 5000; i++ { 242 value := make([]byte, i) 243 _, err := rand.Read(value) 244 require.NoError(t, err) 245 k := sha3.NewLegacyKeccak256() 246 k.Write(value) 247 expected := k.Sum(nil) 248 249 // test hash computation using the hasher 250 hasher := NewKeccak_256() 251 h := hasher.ComputeHash(value) 252 assert.Equal(t, expected[:], []byte(h)) 253 } 254 } 255 256 // Benchmark of all hashers' ComputeHash function 257 func BenchmarkComputeHash(b *testing.B) { 258 259 m := make([]byte, 32) 260 _, err := rand.Read(m) 261 require.NoError(b, err) 262 263 b.Run("SHA2_256", func(b *testing.B) { 264 b.ResetTimer() 265 for i := 0; i < b.N; i++ { 266 alg := NewSHA2_256() 267 _ = alg.ComputeHash(m) 268 } 269 b.StopTimer() 270 }) 271 272 b.Run("SHA2_256_light", func(b *testing.B) { 273 var h [HashLenSHA2_256]byte 274 b.ResetTimer() 275 for i := 0; i < b.N; i++ { 276 ComputeSHA2_256(&h, m) 277 } 278 b.StopTimer() 279 }) 280 281 b.Run("SHA2_384", func(b *testing.B) { 282 b.ResetTimer() 283 for i := 0; i < b.N; i++ { 284 alg := NewSHA2_384() 285 _ = alg.ComputeHash(m) 286 } 287 b.StopTimer() 288 }) 289 290 b.Run("SHA3_256", func(b *testing.B) { 291 b.ResetTimer() 292 for i := 0; i < b.N; i++ { 293 alg := NewSHA3_256() 294 alg.ComputeHash(m) 295 } 296 b.StopTimer() 297 }) 298 299 b.Run("SHA3_256_light", func(b *testing.B) { 300 var h [HashLenSHA3_256]byte 301 b.ResetTimer() 302 for i := 0; i < b.N; i++ { 303 ComputeSHA3_256(&h, m) 304 } 305 b.StopTimer() 306 }) 307 308 b.Run("SHA3_384", func(b *testing.B) { 309 b.ResetTimer() 310 for i := 0; i < b.N; i++ { 311 alg := NewSHA3_384() 312 _ = alg.ComputeHash(m) 313 } 314 b.StopTimer() 315 }) 316 317 b.Run("Keccak_256", func(b *testing.B) { 318 b.ResetTimer() 319 for i := 0; i < b.N; i++ { 320 alg := NewKeccak_256() 321 alg.ComputeHash(m) 322 } 323 b.StopTimer() 324 }) 325 326 // KMAC128 with 128 bytes output 327 b.Run("KMAC128_128", func(b *testing.B) { 328 alg, _ := NewKMAC_128([]byte("bench_key________"), []byte("bench_custommizer"), 128) 329 b.ResetTimer() 330 for i := 0; i < b.N; i++ { 331 _ = alg.ComputeHash(m) 332 } 333 b.StopTimer() 334 }) 335 }