sha3_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  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. // testDigests contains functions returning hash.Hash instances
  26. // with output-length equal to the KAT length for SHA-3, Keccak
  27. // and SHAKE instances.
  28. var testDigests = map[string]func() hash.Hash{
  29. "SHA3-224": New224,
  30. "SHA3-256": New256,
  31. "SHA3-384": New384,
  32. "SHA3-512": New512,
  33. "Keccak-256": NewLegacyKeccak256,
  34. "Keccak-512": NewLegacyKeccak512,
  35. }
  36. // testShakes contains functions that return sha3.ShakeHash instances for
  37. // with output-length equal to the KAT length.
  38. var testShakes = map[string]struct {
  39. constructor func(N []byte, S []byte) ShakeHash
  40. defAlgoName string
  41. defCustomStr string
  42. }{
  43. // NewCShake without customization produces same result as SHAKE
  44. "SHAKE128": {NewCShake128, "", ""},
  45. "SHAKE256": {NewCShake256, "", ""},
  46. "cSHAKE128": {NewCShake128, "CSHAKE128", "CustomStrign"},
  47. "cSHAKE256": {NewCShake256, "CSHAKE256", "CustomStrign"},
  48. }
  49. // decodeHex converts a hex-encoded string into a raw byte string.
  50. func decodeHex(s string) []byte {
  51. b, err := hex.DecodeString(s)
  52. if err != nil {
  53. panic(err)
  54. }
  55. return b
  56. }
  57. // structs used to marshal JSON test-cases.
  58. type KeccakKats struct {
  59. Kats map[string][]struct {
  60. Digest string `json:"digest"`
  61. Length int64 `json:"length"`
  62. Message string `json:"message"`
  63. // Defined only for cSHAKE
  64. N string `json:"N"`
  65. S string `json:"S"`
  66. }
  67. }
  68. func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) {
  69. xorInOrig, copyOutOrig := xorIn, copyOut
  70. xorIn, copyOut = xorInGeneric, copyOutGeneric
  71. testf("generic")
  72. if xorImplementationUnaligned != "generic" {
  73. xorIn, copyOut = xorInUnaligned, copyOutUnaligned
  74. testf("unaligned")
  75. }
  76. xorIn, copyOut = xorInOrig, copyOutOrig
  77. }
  78. // TestKeccakKats tests the SHA-3 and Shake implementations against all the
  79. // ShortMsgKATs from https://github.com/gvanas/KeccakCodePackage
  80. // (The testvectors are stored in keccakKats.json.deflate due to their length.)
  81. func TestKeccakKats(t *testing.T) {
  82. testUnalignedAndGeneric(t, func(impl string) {
  83. // Read the KATs.
  84. deflated, err := os.Open(katFilename)
  85. if err != nil {
  86. t.Errorf("error opening %s: %s", katFilename, err)
  87. }
  88. file := flate.NewReader(deflated)
  89. dec := json.NewDecoder(file)
  90. var katSet KeccakKats
  91. err = dec.Decode(&katSet)
  92. if err != nil {
  93. t.Errorf("error decoding KATs: %s", err)
  94. }
  95. for algo, function := range testDigests {
  96. d := function()
  97. for _, kat := range katSet.Kats[algo] {
  98. d.Reset()
  99. in, err := hex.DecodeString(kat.Message)
  100. if err != nil {
  101. t.Errorf("error decoding KAT: %s", err)
  102. }
  103. d.Write(in[:kat.Length/8])
  104. got := strings.ToUpper(hex.EncodeToString(d.Sum(nil)))
  105. if got != kat.Digest {
  106. t.Errorf("function=%s, implementation=%s, length=%d\nmessage:\n %s\ngot:\n %s\nwanted:\n %s",
  107. algo, impl, kat.Length, kat.Message, got, kat.Digest)
  108. t.Logf("wanted %+v", kat)
  109. t.FailNow()
  110. }
  111. continue
  112. }
  113. }
  114. for algo, v := range testShakes {
  115. for _, kat := range katSet.Kats[algo] {
  116. N, err := hex.DecodeString(kat.N)
  117. if err != nil {
  118. t.Errorf("error decoding KAT: %s", err)
  119. }
  120. S, err := hex.DecodeString(kat.S)
  121. if err != nil {
  122. t.Errorf("error decoding KAT: %s", err)
  123. }
  124. d := v.constructor(N, S)
  125. in, err := hex.DecodeString(kat.Message)
  126. if err != nil {
  127. t.Errorf("error decoding KAT: %s", err)
  128. }
  129. d.Write(in[:kat.Length/8])
  130. out := make([]byte, len(kat.Digest)/2)
  131. d.Read(out)
  132. got := strings.ToUpper(hex.EncodeToString(out))
  133. if got != kat.Digest {
  134. t.Errorf("function=%s, implementation=%s, length=%d N:%s\n S:%s\nmessage:\n %s \ngot:\n %s\nwanted:\n %s",
  135. algo, impl, kat.Length, kat.N, kat.S, kat.Message, got, kat.Digest)
  136. t.Logf("wanted %+v", kat)
  137. t.FailNow()
  138. }
  139. continue
  140. }
  141. }
  142. })
  143. }
  144. // TestKeccak does a basic test of the non-standardized Keccak hash functions.
  145. func TestKeccak(t *testing.T) {
  146. tests := []struct {
  147. fn func() hash.Hash
  148. data []byte
  149. want string
  150. }{
  151. {
  152. NewLegacyKeccak256,
  153. []byte("abc"),
  154. "4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45",
  155. },
  156. {
  157. NewLegacyKeccak512,
  158. []byte("abc"),
  159. "18587dc2ea106b9a1563e32b3312421ca164c7f1f07bc922a9c83d77cea3a1e5d0c69910739025372dc14ac9642629379540c17e2a65b19d77aa511a9d00bb96",
  160. },
  161. }
  162. for _, u := range tests {
  163. h := u.fn()
  164. h.Write(u.data)
  165. got := h.Sum(nil)
  166. want := decodeHex(u.want)
  167. if !bytes.Equal(got, want) {
  168. t.Errorf("unexpected hash for size %d: got '%x' want '%s'", h.Size()*8, got, u.want)
  169. }
  170. }
  171. }
  172. // TestUnalignedWrite tests that writing data in an arbitrary pattern with
  173. // small input buffers.
  174. func TestUnalignedWrite(t *testing.T) {
  175. testUnalignedAndGeneric(t, func(impl string) {
  176. buf := sequentialBytes(0x10000)
  177. for alg, df := range testDigests {
  178. d := df()
  179. d.Reset()
  180. d.Write(buf)
  181. want := d.Sum(nil)
  182. d.Reset()
  183. for i := 0; i < len(buf); {
  184. // Cycle through offsets which make a 137 byte sequence.
  185. // Because 137 is prime this sequence should exercise all corner cases.
  186. offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
  187. for _, j := range offsets {
  188. if v := len(buf) - i; v < j {
  189. j = v
  190. }
  191. d.Write(buf[i : i+j])
  192. i += j
  193. }
  194. }
  195. got := d.Sum(nil)
  196. if !bytes.Equal(got, want) {
  197. t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want)
  198. }
  199. }
  200. // Same for SHAKE
  201. for alg, df := range testShakes {
  202. want := make([]byte, 16)
  203. got := make([]byte, 16)
  204. d := df.constructor([]byte(df.defAlgoName), []byte(df.defCustomStr))
  205. d.Reset()
  206. d.Write(buf)
  207. d.Read(want)
  208. d.Reset()
  209. for i := 0; i < len(buf); {
  210. // Cycle through offsets which make a 137 byte sequence.
  211. // Because 137 is prime this sequence should exercise all corner cases.
  212. offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
  213. for _, j := range offsets {
  214. if v := len(buf) - i; v < j {
  215. j = v
  216. }
  217. d.Write(buf[i : i+j])
  218. i += j
  219. }
  220. }
  221. d.Read(got)
  222. if !bytes.Equal(got, want) {
  223. t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want)
  224. }
  225. }
  226. })
  227. }
  228. // TestAppend checks that appending works when reallocation is necessary.
  229. func TestAppend(t *testing.T) {
  230. testUnalignedAndGeneric(t, func(impl string) {
  231. d := New224()
  232. for capacity := 2; capacity <= 66; capacity += 64 {
  233. // The first time around the loop, Sum will have to reallocate.
  234. // The second time, it will not.
  235. buf := make([]byte, 2, capacity)
  236. d.Reset()
  237. d.Write([]byte{0xcc})
  238. buf = d.Sum(buf)
  239. expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
  240. if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
  241. t.Errorf("got %s, want %s", got, expected)
  242. }
  243. }
  244. })
  245. }
  246. // TestAppendNoRealloc tests that appending works when no reallocation is necessary.
  247. func TestAppendNoRealloc(t *testing.T) {
  248. testUnalignedAndGeneric(t, func(impl string) {
  249. buf := make([]byte, 1, 200)
  250. d := New224()
  251. d.Write([]byte{0xcc})
  252. buf = d.Sum(buf)
  253. expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
  254. if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
  255. t.Errorf("%s: got %s, want %s", impl, got, expected)
  256. }
  257. })
  258. }
  259. // TestSqueezing checks that squeezing the full output a single time produces
  260. // the same output as repeatedly squeezing the instance.
  261. func TestSqueezing(t *testing.T) {
  262. testUnalignedAndGeneric(t, func(impl string) {
  263. for algo, v := range testShakes {
  264. d0 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr))
  265. d0.Write([]byte(testString))
  266. ref := make([]byte, 32)
  267. d0.Read(ref)
  268. d1 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr))
  269. d1.Write([]byte(testString))
  270. var multiple []byte
  271. for range ref {
  272. one := make([]byte, 1)
  273. d1.Read(one)
  274. multiple = append(multiple, one...)
  275. }
  276. if !bytes.Equal(ref, multiple) {
  277. t.Errorf("%s (%s): squeezing %d bytes one at a time failed", algo, impl, len(ref))
  278. }
  279. }
  280. })
  281. }
  282. // sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing.
  283. func sequentialBytes(size int) []byte {
  284. result := make([]byte, size)
  285. for i := range result {
  286. result[i] = byte(i)
  287. }
  288. return result
  289. }
  290. func TestReset(t *testing.T) {
  291. out1 := make([]byte, 32)
  292. out2 := make([]byte, 32)
  293. for _, v := range testShakes {
  294. // Calculate hash for the first time
  295. c := v.constructor(nil, []byte{0x99, 0x98})
  296. c.Write(sequentialBytes(0x100))
  297. c.Read(out1)
  298. // Calculate hash again
  299. c.Reset()
  300. c.Write(sequentialBytes(0x100))
  301. c.Read(out2)
  302. if !bytes.Equal(out1, out2) {
  303. t.Error("\nExpected:\n", out1, "\ngot:\n", out2)
  304. }
  305. }
  306. }
  307. func TestClone(t *testing.T) {
  308. out1 := make([]byte, 16)
  309. out2 := make([]byte, 16)
  310. // Test for sizes smaller and larger than block size.
  311. for _, size := range []int{0x1, 0x100} {
  312. in := sequentialBytes(size)
  313. for _, v := range testShakes {
  314. h1 := v.constructor(nil, []byte{0x01})
  315. h1.Write([]byte{0x01})
  316. h2 := h1.Clone()
  317. h1.Write(in)
  318. h1.Read(out1)
  319. h2.Write(in)
  320. h2.Read(out2)
  321. if !bytes.Equal(out1, out2) {
  322. t.Error("\nExpected:\n", hex.EncodeToString(out1), "\ngot:\n", hex.EncodeToString(out2))
  323. }
  324. }
  325. }
  326. }
  327. // BenchmarkPermutationFunction measures the speed of the permutation function
  328. // with no input data.
  329. func BenchmarkPermutationFunction(b *testing.B) {
  330. b.SetBytes(int64(200))
  331. var lanes [25]uint64
  332. for i := 0; i < b.N; i++ {
  333. keccakF1600(&lanes)
  334. }
  335. }
  336. // benchmarkHash tests the speed to hash num buffers of buflen each.
  337. func benchmarkHash(b *testing.B, h hash.Hash, size, num int) {
  338. b.StopTimer()
  339. h.Reset()
  340. data := sequentialBytes(size)
  341. b.SetBytes(int64(size * num))
  342. b.StartTimer()
  343. var state []byte
  344. for i := 0; i < b.N; i++ {
  345. for j := 0; j < num; j++ {
  346. h.Write(data)
  347. }
  348. state = h.Sum(state[:0])
  349. }
  350. b.StopTimer()
  351. h.Reset()
  352. }
  353. // benchmarkShake is specialized to the Shake instances, which don't
  354. // require a copy on reading output.
  355. func benchmarkShake(b *testing.B, h ShakeHash, size, num int) {
  356. b.StopTimer()
  357. h.Reset()
  358. data := sequentialBytes(size)
  359. d := make([]byte, 32)
  360. b.SetBytes(int64(size * num))
  361. b.StartTimer()
  362. for i := 0; i < b.N; i++ {
  363. h.Reset()
  364. for j := 0; j < num; j++ {
  365. h.Write(data)
  366. }
  367. h.Read(d)
  368. }
  369. }
  370. func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) }
  371. func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) }
  372. func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) }
  373. func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) }
  374. func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 1350, 1) }
  375. func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) }
  376. func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) }
  377. func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) }
  378. func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) }
  379. func Example_sum() {
  380. buf := []byte("some data to hash")
  381. // A hash needs to be 64 bytes long to have 256-bit collision resistance.
  382. h := make([]byte, 64)
  383. // Compute a 64-byte hash of buf and put it in h.
  384. ShakeSum256(h, buf)
  385. fmt.Printf("%x\n", h)
  386. // Output: 0f65fe41fc353e52c55667bb9e2b27bfcc8476f2c413e9437d272ee3194a4e3146d05ec04a25d16b8f577c19b82d16b1424c3e022e783d2b4da98de3658d363d
  387. }
  388. func Example_mac() {
  389. k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long")
  390. buf := []byte("and this is some data to authenticate")
  391. // A MAC with 32 bytes of output has 256-bit security strength -- if you use at least a 32-byte-long key.
  392. h := make([]byte, 32)
  393. d := NewShake256()
  394. // Write the key into the hash.
  395. d.Write(k)
  396. // Now write the data.
  397. d.Write(buf)
  398. // Read 32 bytes of output from the hash into h.
  399. d.Read(h)
  400. fmt.Printf("%x\n", h)
  401. // Output: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff
  402. }
  403. func ExampleNewCShake256() {
  404. out := make([]byte, 32)
  405. msg := []byte("The quick brown fox jumps over the lazy dog")
  406. // Example 1: Simple cshake
  407. c1 := NewCShake256([]byte("NAME"), []byte("Partition1"))
  408. c1.Write(msg)
  409. c1.Read(out)
  410. fmt.Println(hex.EncodeToString(out))
  411. // Example 2: Different customization string produces different digest
  412. c1 = NewCShake256([]byte("NAME"), []byte("Partition2"))
  413. c1.Write(msg)
  414. c1.Read(out)
  415. fmt.Println(hex.EncodeToString(out))
  416. // Example 3: Longer output length produces longer digest
  417. out = make([]byte, 64)
  418. c1 = NewCShake256([]byte("NAME"), []byte("Partition1"))
  419. c1.Write(msg)
  420. c1.Read(out)
  421. fmt.Println(hex.EncodeToString(out))
  422. // Example 4: Next read produces different result
  423. c1.Read(out)
  424. fmt.Println(hex.EncodeToString(out))
  425. // Output:
  426. //a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b
  427. //a8db03e71f3e4da5c4eee9d28333cdd355f51cef3c567e59be5beb4ecdbb28f0
  428. //a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b9dd98c6ee866ca7dc5a39d53e960f400bcd5a19c8a2d6ec6459f63696543a0d8
  429. //85e73a72228d08b46515553ca3a29d47df3047e5d84b12d6c2c63e579f4fd1105716b7838e92e981863907f434bfd4443c9e56ea09da998d2f9b47db71988109
  430. }