sha3_test.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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 bitwise testvectors
  9. // 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 = "testdata/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 that return ShakeHash instances for
  43. // testing the ShakeHash-specific interface.
  44. var testShakes = map[string]func() ShakeHash{
  45. "SHAKE128": NewShake128,
  46. "SHAKE256": NewShake256,
  47. }
  48. // structs used to marshal JSON test-cases.
  49. type KeccakKats struct {
  50. Kats map[string][]struct {
  51. Digest string `json:"digest"`
  52. Length int64 `json:"length"`
  53. Message string `json:"message"`
  54. }
  55. }
  56. func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) {
  57. xorInOrig, copyOutOrig := xorIn, copyOut
  58. xorIn, copyOut = xorInGeneric, copyOutGeneric
  59. testf("generic")
  60. if xorImplementationUnaligned != "generic" {
  61. xorIn, copyOut = xorInUnaligned, copyOutUnaligned
  62. testf("unaligned")
  63. }
  64. xorIn, copyOut = xorInOrig, copyOutOrig
  65. }
  66. // TestKeccakKats tests the SHA-3 and Shake implementations against all the
  67. // ShortMsgKATs from https://github.com/gvanas/KeccakCodePackage
  68. // (The testvectors are stored in keccakKats.json.deflate due to their length.)
  69. func TestKeccakKats(t *testing.T) {
  70. testUnalignedAndGeneric(t, func(impl string) {
  71. // Read the KATs.
  72. deflated, err := os.Open(katFilename)
  73. if err != nil {
  74. t.Errorf("error opening %s: %s", katFilename, err)
  75. }
  76. file := flate.NewReader(deflated)
  77. dec := json.NewDecoder(file)
  78. var katSet KeccakKats
  79. err = dec.Decode(&katSet)
  80. if err != nil {
  81. t.Errorf("error decoding KATs: %s", err)
  82. }
  83. // Do the KATs.
  84. for functionName, kats := range katSet.Kats {
  85. d := testDigests[functionName]()
  86. for _, kat := range kats {
  87. d.Reset()
  88. in, err := hex.DecodeString(kat.Message)
  89. if err != nil {
  90. t.Errorf("error decoding KAT: %s", err)
  91. }
  92. d.Write(in[:kat.Length/8])
  93. got := strings.ToUpper(hex.EncodeToString(d.Sum(nil)))
  94. if got != kat.Digest {
  95. t.Errorf("function=%s, implementation=%s, length=%d\nmessage:\n %s\ngot:\n %s\nwanted:\n %s",
  96. functionName, impl, kat.Length, kat.Message, got, kat.Digest)
  97. t.Logf("wanted %+v", kat)
  98. t.FailNow()
  99. }
  100. continue
  101. }
  102. }
  103. })
  104. }
  105. // TestUnalignedWrite tests that writing data in an arbitrary pattern with
  106. // small input buffers.
  107. func TestUnalignedWrite(t *testing.T) {
  108. testUnalignedAndGeneric(t, func(impl string) {
  109. buf := sequentialBytes(0x10000)
  110. for alg, df := range testDigests {
  111. d := df()
  112. d.Reset()
  113. d.Write(buf)
  114. want := d.Sum(nil)
  115. d.Reset()
  116. for i := 0; i < len(buf); {
  117. // Cycle through offsets which make a 137 byte sequence.
  118. // Because 137 is prime this sequence should exercise all corner cases.
  119. offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
  120. for _, j := range offsets {
  121. if v := len(buf) - i; v < j {
  122. j = v
  123. }
  124. d.Write(buf[i : i+j])
  125. i += j
  126. }
  127. }
  128. got := d.Sum(nil)
  129. if !bytes.Equal(got, want) {
  130. t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want)
  131. }
  132. }
  133. })
  134. }
  135. // TestAppend checks that appending works when reallocation is necessary.
  136. func TestAppend(t *testing.T) {
  137. testUnalignedAndGeneric(t, func(impl string) {
  138. d := New224()
  139. for capacity := 2; capacity <= 66; capacity += 64 {
  140. // The first time around the loop, Sum will have to reallocate.
  141. // The second time, it will not.
  142. buf := make([]byte, 2, capacity)
  143. d.Reset()
  144. d.Write([]byte{0xcc})
  145. buf = d.Sum(buf)
  146. expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
  147. if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
  148. t.Errorf("got %s, want %s", got, expected)
  149. }
  150. }
  151. })
  152. }
  153. // TestAppendNoRealloc tests that appending works when no reallocation is necessary.
  154. func TestAppendNoRealloc(t *testing.T) {
  155. testUnalignedAndGeneric(t, func(impl string) {
  156. buf := make([]byte, 1, 200)
  157. d := New224()
  158. d.Write([]byte{0xcc})
  159. buf = d.Sum(buf)
  160. expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
  161. if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
  162. t.Errorf("%s: got %s, want %s", impl, got, expected)
  163. }
  164. })
  165. }
  166. // TestSqueezing checks that squeezing the full output a single time produces
  167. // the same output as repeatedly squeezing the instance.
  168. func TestSqueezing(t *testing.T) {
  169. testUnalignedAndGeneric(t, func(impl string) {
  170. for functionName, newShakeHash := range testShakes {
  171. d0 := newShakeHash()
  172. d0.Write([]byte(testString))
  173. ref := make([]byte, 32)
  174. d0.Read(ref)
  175. d1 := newShakeHash()
  176. d1.Write([]byte(testString))
  177. var multiple []byte
  178. for range ref {
  179. one := make([]byte, 1)
  180. d1.Read(one)
  181. multiple = append(multiple, one...)
  182. }
  183. if !bytes.Equal(ref, multiple) {
  184. t.Errorf("%s (%s): squeezing %d bytes one at a time failed", functionName, impl, len(ref))
  185. }
  186. }
  187. })
  188. }
  189. // sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing.
  190. func sequentialBytes(size int) []byte {
  191. result := make([]byte, size)
  192. for i := range result {
  193. result[i] = byte(i)
  194. }
  195. return result
  196. }
  197. // BenchmarkPermutationFunction measures the speed of the permutation function
  198. // with no input data.
  199. func BenchmarkPermutationFunction(b *testing.B) {
  200. b.SetBytes(int64(200))
  201. var lanes [25]uint64
  202. for i := 0; i < b.N; i++ {
  203. keccakF1600(&lanes)
  204. }
  205. }
  206. // benchmarkHash tests the speed to hash num buffers of buflen each.
  207. func benchmarkHash(b *testing.B, h hash.Hash, size, num int) {
  208. b.StopTimer()
  209. h.Reset()
  210. data := sequentialBytes(size)
  211. b.SetBytes(int64(size * num))
  212. b.StartTimer()
  213. var state []byte
  214. for i := 0; i < b.N; i++ {
  215. for j := 0; j < num; j++ {
  216. h.Write(data)
  217. }
  218. state = h.Sum(state[:0])
  219. }
  220. b.StopTimer()
  221. h.Reset()
  222. }
  223. // benchmarkShake is specialized to the Shake instances, which don't
  224. // require a copy on reading output.
  225. func benchmarkShake(b *testing.B, h ShakeHash, size, num int) {
  226. b.StopTimer()
  227. h.Reset()
  228. data := sequentialBytes(size)
  229. d := make([]byte, 32)
  230. b.SetBytes(int64(size * num))
  231. b.StartTimer()
  232. for i := 0; i < b.N; i++ {
  233. h.Reset()
  234. for j := 0; j < num; j++ {
  235. h.Write(data)
  236. }
  237. h.Read(d)
  238. }
  239. }
  240. func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) }
  241. func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) }
  242. func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) }
  243. func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) }
  244. func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 1350, 1) }
  245. func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) }
  246. func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) }
  247. func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) }
  248. func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) }
  249. func Example_sum() {
  250. buf := []byte("some data to hash")
  251. // A hash needs to be 64 bytes long to have 256-bit collision resistance.
  252. h := make([]byte, 64)
  253. // Compute a 64-byte hash of buf and put it in h.
  254. ShakeSum256(h, buf)
  255. }
  256. func Example_mac() {
  257. k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long")
  258. buf := []byte("and this is some data to authenticate")
  259. // A MAC with 32 bytes of output has 256-bit security strength -- if you use at least a 32-byte-long key.
  260. h := make([]byte, 32)
  261. d := NewShake256()
  262. // Write the key into the hash.
  263. d.Write(k)
  264. // Now write the data.
  265. d.Write(buf)
  266. // Read 32 bytes of output from the hash into h.
  267. d.Read(h)
  268. }