sha3_test.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. // Copyright 2013 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. // These tests are a subset of those provided by the Keccak web site(http://keccak.noekeon.org/).
  6. import (
  7. "bytes"
  8. "encoding/hex"
  9. "fmt"
  10. "hash"
  11. "strings"
  12. "testing"
  13. )
  14. // testDigests maintains a digest state of each standard type.
  15. var testDigests = map[string]*digest{
  16. "Keccak224": {outputSize: 224 / 8, capacity: 2 * 224 / 8},
  17. "Keccak256": {outputSize: 256 / 8, capacity: 2 * 256 / 8},
  18. "Keccak384": {outputSize: 384 / 8, capacity: 2 * 384 / 8},
  19. "Keccak512": {outputSize: 512 / 8, capacity: 2 * 512 / 8},
  20. }
  21. // testVector represents a test input and expected outputs from multiple algorithm variants.
  22. type testVector struct {
  23. desc string
  24. input []byte
  25. repeat int // input will be concatenated the input this many times.
  26. want map[string]string
  27. }
  28. // decodeHex converts an hex-encoded string into a raw byte string.
  29. func decodeHex(s string) []byte {
  30. b, err := hex.DecodeString(s)
  31. if err != nil {
  32. panic(err)
  33. }
  34. return b
  35. }
  36. // shortTestVectors stores a series of short testVectors.
  37. // Inputs of 8, 248, and 264 bits from http://keccak.noekeon.org/ are included below.
  38. // The standard defines additional test inputs of all sizes between 0 and 2047 bits.
  39. // Because the current implementation can only handle an integral number of bytes,
  40. // most of the standard test inputs can't be used.
  41. var shortKeccakTestVectors = []testVector{
  42. {
  43. desc: "short-8b",
  44. input: decodeHex("CC"),
  45. repeat: 1,
  46. want: map[string]string{
  47. "Keccak224": "A9CAB59EB40A10B246290F2D6086E32E3689FAF1D26B470C899F2802",
  48. "Keccak256": "EEAD6DBFC7340A56CAEDC044696A168870549A6A7F6F56961E84A54BD9970B8A",
  49. "Keccak384": "1B84E62A46E5A201861754AF5DC95C4A1A69CAF4A796AE405680161E29572641F5FA1E8641D7958336EE7B11C58F73E9",
  50. "Keccak512": "8630C13CBD066EA74BBE7FE468FEC1DEE10EDC1254FB4C1B7C5FD69B646E44160B8CE01D05A0908CA790DFB080F4B513BC3B6225ECE7A810371441A5AC666EB9",
  51. },
  52. },
  53. {
  54. desc: "short-248b",
  55. input: decodeHex("84FB51B517DF6C5ACCB5D022F8F28DA09B10232D42320FFC32DBECC3835B29"),
  56. repeat: 1,
  57. want: map[string]string{
  58. "Keccak224": "81AF3A7A5BD4C1F948D6AF4B96F93C3B0CF9C0E7A6DA6FCD71EEC7F6",
  59. "Keccak256": "D477FB02CAAA95B3280EC8EE882C29D9E8A654B21EF178E0F97571BF9D4D3C1C",
  60. "Keccak384": "503DCAA4ADDA5A9420B2E436DD62D9AB2E0254295C2982EF67FCE40F117A2400AB492F7BD5D133C6EC2232268BC27B42",
  61. "Keccak512": "9D8098D8D6EDBBAA2BCFC6FB2F89C3EAC67FEC25CDFE75AA7BD570A648E8C8945FF2EC280F6DCF73386109155C5BBC444C707BB42EAB873F5F7476657B1BC1A8",
  62. },
  63. },
  64. {
  65. desc: "short-264b",
  66. input: decodeHex("DE8F1B3FAA4B7040ED4563C3B8E598253178E87E4D0DF75E4FF2F2DEDD5A0BE046"),
  67. repeat: 1,
  68. want: map[string]string{
  69. "Keccak224": "F217812E362EC64D4DC5EACFABC165184BFA456E5C32C2C7900253D0",
  70. "Keccak256": "E78C421E6213AFF8DE1F025759A4F2C943DB62BBDE359C8737E19B3776ED2DD2",
  71. "Keccak384": "CF38764973F1EC1C34B5433AE75A3AAD1AAEF6AB197850C56C8617BCD6A882F6666883AC17B2DCCDBAA647075D0972B5",
  72. "Keccak512": "9A7688E31AAF40C15575FC58C6B39267AAD3722E696E518A9945CF7F7C0FEA84CB3CB2E9F0384A6B5DC671ADE7FB4D2B27011173F3EEEAF17CB451CF26542031",
  73. },
  74. },
  75. }
  76. // longTestVectors stores longer testVectors (currently only one).
  77. // The computed test vector is 64 MiB long and is a truncated version of the
  78. // ExtremelyLongMsgKAT taken from http://keccak.noekeon.org/.
  79. var longKeccakTestVectors = []testVector{
  80. {
  81. desc: "long-64MiB",
  82. input: []byte("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"),
  83. repeat: 1024 * 1024,
  84. want: map[string]string{
  85. "Keccak224": "50E35E40980FEEFF1EA490957B0E970257F75EA0D410EE0F0B8A7A58",
  86. "Keccak256": "5015A4935F0B51E091C6550A94DCD262C08998232CCAA22E7F0756DEAC0DC0D0",
  87. "Keccak384": "7907A8D0FAA7BC6A90FE14C6C958C956A0877E751455D8F13ACDB96F144B5896E716C06EC0CB56557A94EF5C3355F6F3",
  88. "Keccak512": "3EC327D6759F769DEB74E80CA70C831BC29CAB048A4BF4190E4A1DD5C6507CF2B4B58937FDE81D36014E7DFE1B1DD8B0F27CB7614F9A645FEC114F1DAAEFC056",
  89. },
  90. },
  91. }
  92. // TestKeccakVectors checks that correct output is produced for a set of known testVectors.
  93. func TestKeccakVectors(t *testing.T) {
  94. testCases := append([]testVector{}, shortKeccakTestVectors...)
  95. if !testing.Short() {
  96. testCases = append(testCases, longKeccakTestVectors...)
  97. }
  98. for _, tc := range testCases {
  99. for alg, want := range tc.want {
  100. d := testDigests[alg]
  101. d.Reset()
  102. for i := 0; i < tc.repeat; i++ {
  103. d.Write(tc.input)
  104. }
  105. got := strings.ToUpper(hex.EncodeToString(d.Sum(nil)))
  106. if got != want {
  107. t.Errorf("%s, alg=%s\ngot %q, want %q", tc.desc, alg, got, want)
  108. }
  109. }
  110. }
  111. }
  112. // dumpState is a debugging function to pretty-print the internal state of the hash.
  113. func (d *digest) dumpState() {
  114. fmt.Printf("SHA3 hash, %d B output, %d B capacity (%d B rate)\n", d.outputSize, d.capacity, d.rate())
  115. fmt.Printf("Internal state after absorbing %d B:\n", d.absorbed)
  116. for x := 0; x < sliceSize; x++ {
  117. for y := 0; y < sliceSize; y++ {
  118. fmt.Printf("%v, ", d.a[x*sliceSize+y])
  119. }
  120. fmt.Println("")
  121. }
  122. }
  123. // TestUnalignedWrite tests that writing data in an arbitrary pattern with small input buffers.
  124. func TestUnalignedWrite(t *testing.T) {
  125. buf := sequentialBytes(0x10000)
  126. for alg, d := range testDigests {
  127. d.Reset()
  128. d.Write(buf)
  129. want := d.Sum(nil)
  130. d.Reset()
  131. for i := 0; i < len(buf); {
  132. // Cycle through offsets which make a 137 byte sequence.
  133. // Because 137 is prime this sequence should exercise all corner cases.
  134. offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
  135. for _, j := range offsets {
  136. j = minInt(j, len(buf)-i)
  137. d.Write(buf[i : i+j])
  138. i += j
  139. }
  140. }
  141. got := d.Sum(nil)
  142. if !bytes.Equal(got, want) {
  143. t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want)
  144. }
  145. }
  146. }
  147. func TestAppend(t *testing.T) {
  148. d := NewKeccak224()
  149. for capacity := 2; capacity < 64; capacity += 64 {
  150. // The first time around the loop, Sum will have to reallocate.
  151. // The second time, it will not.
  152. buf := make([]byte, 2, capacity)
  153. d.Reset()
  154. d.Write([]byte{0xcc})
  155. buf = d.Sum(buf)
  156. expected := "0000A9CAB59EB40A10B246290F2D6086E32E3689FAF1D26B470C899F2802"
  157. if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
  158. t.Errorf("got %s, want %s", got, expected)
  159. }
  160. }
  161. }
  162. func TestAppendNoRealloc(t *testing.T) {
  163. buf := make([]byte, 1, 200)
  164. d := NewKeccak224()
  165. d.Write([]byte{0xcc})
  166. buf = d.Sum(buf)
  167. expected := "00A9CAB59EB40A10B246290F2D6086E32E3689FAF1D26B470C899F2802"
  168. if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
  169. t.Errorf("got %s, want %s", got, expected)
  170. }
  171. }
  172. // sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing.
  173. func sequentialBytes(size int) []byte {
  174. result := make([]byte, size)
  175. for i := range result {
  176. result[i] = byte(i)
  177. }
  178. return result
  179. }
  180. // benchmarkBlockWrite tests the speed of writing data and never calling the permutation function.
  181. func benchmarkBlockWrite(b *testing.B, d *digest) {
  182. b.StopTimer()
  183. d.Reset()
  184. // Write all but the last byte of a block, to ensure that the permutation is not called.
  185. data := sequentialBytes(d.rate() - 1)
  186. b.SetBytes(int64(len(data)))
  187. b.StartTimer()
  188. for i := 0; i < b.N; i++ {
  189. d.absorbed = 0 // Reset absorbed to avoid ever calling the permutation function
  190. d.Write(data)
  191. }
  192. b.StopTimer()
  193. d.Reset()
  194. }
  195. // BenchmarkPermutationFunction measures the speed of the permutation function with no input data.
  196. func BenchmarkPermutationFunction(b *testing.B) {
  197. b.StopTimer()
  198. d := testDigests["Keccak512"]
  199. d.Reset()
  200. b.SetBytes(int64(stateSize))
  201. b.StartTimer()
  202. for i := 0; i < b.N; i++ {
  203. d.keccakF()
  204. }
  205. b.StopTimer()
  206. d.Reset()
  207. }
  208. // BenchmarkSingleByteWrite tests the latency from writing a single byte
  209. func BenchmarkSingleByteWrite(b *testing.B) {
  210. b.StopTimer()
  211. d := testDigests["Keccak512"]
  212. d.Reset()
  213. data := sequentialBytes(1) //1 byte buffer
  214. b.SetBytes(int64(d.rate()) - 1)
  215. b.StartTimer()
  216. for i := 0; i < b.N; i++ {
  217. d.absorbed = 0 // Reset absorbed to avoid ever calling the permutation function
  218. // Write all but the last byte of a block, one byte at a time.
  219. for j := 0; j < d.rate()-1; j++ {
  220. d.Write(data)
  221. }
  222. }
  223. b.StopTimer()
  224. d.Reset()
  225. }
  226. // BenchmarkSingleByteX measures the block write speed for each size of the digest.
  227. func BenchmarkBlockWrite512(b *testing.B) { benchmarkBlockWrite(b, testDigests["Keccak512"]) }
  228. func BenchmarkBlockWrite384(b *testing.B) { benchmarkBlockWrite(b, testDigests["Keccak384"]) }
  229. func BenchmarkBlockWrite256(b *testing.B) { benchmarkBlockWrite(b, testDigests["Keccak256"]) }
  230. func BenchmarkBlockWrite224(b *testing.B) { benchmarkBlockWrite(b, testDigests["Keccak224"]) }
  231. // benchmarkBulkHash tests the speed to hash a 16 KiB buffer.
  232. func benchmarkBulkHash(b *testing.B, h hash.Hash) {
  233. b.StopTimer()
  234. h.Reset()
  235. size := 1 << 14
  236. data := sequentialBytes(size)
  237. b.SetBytes(int64(size))
  238. b.StartTimer()
  239. var digest []byte
  240. for i := 0; i < b.N; i++ {
  241. h.Write(data)
  242. digest = h.Sum(digest[:0])
  243. }
  244. b.StopTimer()
  245. h.Reset()
  246. }
  247. // benchmarkBulkKeccakX test the speed to hash a 16 KiB buffer by calling benchmarkBulkHash.
  248. func BenchmarkBulkKeccak512(b *testing.B) { benchmarkBulkHash(b, NewKeccak512()) }
  249. func BenchmarkBulkKeccak384(b *testing.B) { benchmarkBulkHash(b, NewKeccak384()) }
  250. func BenchmarkBulkKeccak256(b *testing.B) { benchmarkBulkHash(b, NewKeccak256()) }
  251. func BenchmarkBulkKeccak224(b *testing.B) { benchmarkBulkHash(b, NewKeccak224()) }