sha3_test.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. // Copyright 2014 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package sha3
  5. // Tests include all the ShortMsgKATs provided by the Keccak team at
  6. // https://github.com/gvanas/KeccakCodePackage
  7. //
  8. // They only include the zero-bit case of the utterly useless bitwise
  9. // testvectors published by NIST in the draft of FIPS-202.
  10. import (
  11. "bytes"
  12. "compress/flate"
  13. "encoding/hex"
  14. "encoding/json"
  15. "hash"
  16. "os"
  17. "strings"
  18. "testing"
  19. )
  20. const (
  21. testString = "brekeccakkeccak koax koax"
  22. katFilename = "keccakKats.json.deflate"
  23. )
  24. // Internal-use instances of SHAKE used to test against KATs.
  25. func newHashShake128() hash.Hash {
  26. return &state{rate: 168, dsbyte: 0x1f, outputLen: 512}
  27. }
  28. func newHashShake256() hash.Hash {
  29. return &state{rate: 136, dsbyte: 0x1f, outputLen: 512}
  30. }
  31. // testDigests contains functions returning hash.Hash instances
  32. // with output-length equal to the KAT length for both SHA-3 and
  33. // SHAKE instances.
  34. var testDigests = map[string]func() hash.Hash{
  35. "SHA3-224": New224,
  36. "SHA3-256": New256,
  37. "SHA3-384": New384,
  38. "SHA3-512": New512,
  39. "SHAKE128": newHashShake128,
  40. "SHAKE256": newHashShake256,
  41. }
  42. // testShakes contains functions returning ShakeHash instances for
  43. // testing the ShakeHash-specific interface.
  44. var testShakes = map[string]func() ShakeHash{
  45. "SHAKE128": NewShake128,
  46. "SHAKE256": NewShake256,
  47. }
  48. // decodeHex converts an hex-encoded string into a raw byte string.
  49. func decodeHex(s string) []byte {
  50. b, err := hex.DecodeString(s)
  51. if err != nil {
  52. panic(err)
  53. }
  54. return b
  55. }
  56. // structs used to marshal JSON test-cases.
  57. type KeccakKats struct {
  58. Kats map[string][]struct {
  59. Digest string `json:"digest"`
  60. Length int64 `json:"length"`
  61. Message string `json:"message"`
  62. }
  63. }
  64. // TestKeccakKats tests the SHA-3 and Shake implementations against all the
  65. // ShortMsgKATs from https://github.com/gvanas/KeccakCodePackage
  66. // (The testvectors are stored in keccakKats.json.deflate due to their length.)
  67. func TestKeccakKats(t *testing.T) {
  68. // Read the KATs.
  69. deflated, err := os.Open(katFilename)
  70. if err != nil {
  71. t.Errorf("Error opening %s: %s", katFilename, err)
  72. }
  73. file := flate.NewReader(deflated)
  74. dec := json.NewDecoder(file)
  75. var katSet KeccakKats
  76. err = dec.Decode(&katSet)
  77. if err != nil {
  78. t.Errorf("%s", err)
  79. }
  80. // Do the KATs.
  81. for functionName, kats := range katSet.Kats {
  82. d := testDigests[functionName]()
  83. t.Logf("%s", functionName)
  84. for _, kat := range kats {
  85. d.Reset()
  86. in, err := hex.DecodeString(kat.Message)
  87. if err != nil {
  88. t.Errorf("%s", err)
  89. }
  90. d.Write(in[:kat.Length/8])
  91. got := strings.ToUpper(hex.EncodeToString(d.Sum(nil)))
  92. want := kat.Digest
  93. if got != want {
  94. t.Errorf("function=%s, length=%d\nmessage:\n %s\ngot:\n %s\nwanted:\n %s",
  95. functionName, kat.Length, kat.Message, got, want)
  96. t.Logf("wanted %+v", kat)
  97. t.FailNow()
  98. }
  99. }
  100. }
  101. }
  102. // TestUnalignedWrite tests that writing data in an arbitrary pattern with
  103. // small input buffers.
  104. func TestUnalignedWrite(t *testing.T) {
  105. buf := sequentialBytes(0x10000)
  106. for alg, df := range testDigests {
  107. d := df()
  108. d.Reset()
  109. d.Write(buf)
  110. want := d.Sum(nil)
  111. d.Reset()
  112. for i := 0; i < len(buf); {
  113. // Cycle through offsets which make a 137 byte sequence.
  114. // Because 137 is prime this sequence should exercise all corner cases.
  115. offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
  116. for _, j := range offsets {
  117. if v := len(buf) - i; v < j {
  118. j = v
  119. }
  120. d.Write(buf[i : i+j])
  121. i += j
  122. }
  123. }
  124. got := d.Sum(nil)
  125. if !bytes.Equal(got, want) {
  126. t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want)
  127. }
  128. }
  129. }
  130. // Test that appending works when reallocation is necessary.
  131. func TestAppend(t *testing.T) {
  132. d := New224()
  133. for capacity := 2; capacity < 64; capacity += 64 {
  134. // The first time around the loop, Sum will have to reallocate.
  135. // The second time, it will not.
  136. buf := make([]byte, 2, capacity)
  137. d.Reset()
  138. d.Write([]byte{0xcc})
  139. buf = d.Sum(buf)
  140. expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
  141. if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
  142. t.Errorf("got %s, want %s", got, expected)
  143. }
  144. }
  145. }
  146. // Test that appending works when no reallocation is necessary.
  147. func TestAppendNoRealloc(t *testing.T) {
  148. buf := make([]byte, 1, 200)
  149. d := New224()
  150. d.Write([]byte{0xcc})
  151. buf = d.Sum(buf)
  152. expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
  153. if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
  154. t.Errorf("got %s, want %s", got, expected)
  155. }
  156. }
  157. // TestSqueezing checks that squeezing the full output a single time produces
  158. // the same output as repeatedly squeezing the instance.
  159. func TestSqueezing(t *testing.T) {
  160. for functionName, newShakeHash := range testShakes {
  161. t.Logf("%s", functionName)
  162. d0 := newShakeHash()
  163. d0.Write([]byte(testString))
  164. ref := make([]byte, 32)
  165. d0.Read(ref)
  166. d1 := newShakeHash()
  167. d1.Write([]byte(testString))
  168. var multiple []byte
  169. for _ = range ref {
  170. one := make([]byte, 1)
  171. d1.Read(one)
  172. multiple = append(multiple, one...)
  173. }
  174. if !bytes.Equal(ref, multiple) {
  175. t.Errorf("squeezing %d bytes one at a time failed", len(ref))
  176. }
  177. }
  178. }
  179. func TestReadSimulation(t *testing.T) {
  180. d := NewShake256()
  181. d.Write(nil)
  182. dwr := make([]byte, 32)
  183. d.Read(dwr)
  184. }
  185. // sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing.
  186. func sequentialBytes(size int) []byte {
  187. result := make([]byte, size)
  188. for i := range result {
  189. result[i] = byte(i)
  190. }
  191. return result
  192. }
  193. // BenchmarkPermutationFunction measures the speed of the permutation function
  194. // with no input data.
  195. func BenchmarkPermutationFunction(b *testing.B) {
  196. b.SetBytes(int64(200))
  197. var lanes [25]uint64
  198. for i := 0; i < b.N; i++ {
  199. keccakF1600(&lanes)
  200. }
  201. }
  202. // benchmarkBulkHash tests the speed to hash a buffer of buflen.
  203. func benchmarkBulkHash(b *testing.B, h hash.Hash, size int) {
  204. b.StopTimer()
  205. h.Reset()
  206. data := sequentialBytes(size)
  207. b.SetBytes(int64(size))
  208. b.StartTimer()
  209. var state []byte
  210. for i := 0; i < b.N; i++ {
  211. h.Write(data)
  212. state = h.Sum(state[:0])
  213. }
  214. b.StopTimer()
  215. h.Reset()
  216. }
  217. func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkBulkHash(b, New512(), 1350) }
  218. func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkBulkHash(b, New384(), 1350) }
  219. func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkBulkHash(b, New256(), 1350) }
  220. func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkBulkHash(b, New224(), 1350) }
  221. func BenchmarkShake256_MTU(b *testing.B) { benchmarkBulkHash(b, newHashShake256(), 1350) }
  222. func BenchmarkShake128_MTU(b *testing.B) { benchmarkBulkHash(b, newHashShake128(), 1350) }
  223. func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkBulkHash(b, New512(), 1<<20) }
  224. func BenchmarkShake256_1MiB(b *testing.B) { benchmarkBulkHash(b, newHashShake256(), 1<<20) }