You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

338 line
9.5 KiB

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