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.
7 // Tests include all the ShortMsgKATs provided by the Keccak team at
8 // https://github.com/gvanas/KeccakCodePackage
10 // They only include the zero-bit case of the bitwise testvectors
11 // published by NIST in the draft of FIPS-202.
26 testString = "brekeccakkeccak koax koax"
27 katFilename = "testdata/keccakKats.json.deflate"
30 // Internal-use instances of SHAKE used to test against KATs.
31 func newHashShake128() hash.Hash {
32 return &state{rate: 168, dsbyte: 0x1f, outputLen: 512}
34 func newHashShake256() hash.Hash {
35 return &state{rate: 136, dsbyte: 0x1f, outputLen: 512}
38 // testDigests contains functions returning hash.Hash instances
39 // with output-length equal to the KAT length for both SHA-3 and
41 var testDigests = map[string]func() hash.Hash{
46 "SHAKE128": newHashShake128,
47 "SHAKE256": newHashShake256,
50 // testShakes contains functions that return ShakeHash instances for
51 // testing the ShakeHash-specific interface.
52 var testShakes = map[string]func() ShakeHash{
53 "SHAKE128": NewShake128,
54 "SHAKE256": NewShake256,
57 // decodeHex converts a hex-encoded string into a raw byte string.
58 func decodeHex(s string) []byte {
59 b, err := hex.DecodeString(s)
66 // structs used to marshal JSON test-cases.
67 type KeccakKats struct {
68 Kats map[string][]struct {
69 Digest string `json:"digest"`
70 Length int64 `json:"length"`
71 Message string `json:"message"`
75 func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) {
76 xorInOrig, copyOutOrig := xorIn, copyOut
77 xorIn, copyOut = xorInGeneric, copyOutGeneric
79 if xorImplementationUnaligned != "generic" {
80 xorIn, copyOut = xorInUnaligned, copyOutUnaligned
83 xorIn, copyOut = xorInOrig, copyOutOrig
86 // TestKeccakKats tests the SHA-3 and Shake implementations against all the
87 // ShortMsgKATs from https://github.com/gvanas/KeccakCodePackage
88 // (The testvectors are stored in keccakKats.json.deflate due to their length.)
89 func TestKeccakKats(t *testing.T) {
90 testUnalignedAndGeneric(t, func(impl string) {
92 deflated, err := os.Open(katFilename)
94 t.Errorf("error opening %s: %s", katFilename, err)
96 file := flate.NewReader(deflated)
97 dec := json.NewDecoder(file)
99 err = dec.Decode(&katSet)
101 t.Errorf("error decoding KATs: %s", err)
105 for functionName, kats := range katSet.Kats {
106 d := testDigests[functionName]()
107 for _, kat := range kats {
109 in, err := hex.DecodeString(kat.Message)
111 t.Errorf("error decoding KAT: %s", err)
113 d.Write(in[:kat.Length/8])
114 got := strings.ToUpper(hex.EncodeToString(d.Sum(nil)))
115 if got != kat.Digest {
116 t.Errorf("function=%s, implementation=%s, length=%d\nmessage:\n %s\ngot:\n %s\nwanted:\n %s",
117 functionName, impl, kat.Length, kat.Message, got, kat.Digest)
118 t.Logf("wanted %+v", kat)
127 // TestUnalignedWrite tests that writing data in an arbitrary pattern with
128 // small input buffers.
129 func testUnalignedWrite(t *testing.T) {
130 testUnalignedAndGeneric(t, func(impl string) {
131 buf := sequentialBytes(0x10000)
132 for alg, df := range testDigests {
138 for i := 0; i < len(buf); {
139 // Cycle through offsets which make a 137 byte sequence.
140 // Because 137 is prime this sequence should exercise all corner cases.
141 offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
142 for _, j := range offsets {
143 if v := len(buf) - i; v < j {
146 d.Write(buf[i : i+j])
151 if !bytes.Equal(got, want) {
152 t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want)
158 // TestAppend checks that appending works when reallocation is necessary.
159 func TestAppend(t *testing.T) {
160 testUnalignedAndGeneric(t, func(impl string) {
163 for capacity := 2; capacity <= 66; capacity += 64 {
164 // The first time around the loop, Sum will have to reallocate.
165 // The second time, it will not.
166 buf := make([]byte, 2, capacity)
168 d.Write([]byte{0xcc})
170 expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
171 if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
172 t.Errorf("got %s, want %s", got, expected)
178 // TestAppendNoRealloc tests that appending works when no reallocation is necessary.
179 func TestAppendNoRealloc(t *testing.T) {
180 testUnalignedAndGeneric(t, func(impl string) {
181 buf := make([]byte, 1, 200)
183 d.Write([]byte{0xcc})
185 expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
186 if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
187 t.Errorf("%s: got %s, want %s", impl, got, expected)
192 // TestSqueezing checks that squeezing the full output a single time produces
193 // the same output as repeatedly squeezing the instance.
194 func TestSqueezing(t *testing.T) {
195 testUnalignedAndGeneric(t, func(impl string) {
196 for functionName, newShakeHash := range testShakes {
198 d0.Write([]byte(testString))
199 ref := make([]byte, 32)
203 d1.Write([]byte(testString))
206 one := make([]byte, 1)
208 multiple = append(multiple, one...)
210 if !bytes.Equal(ref, multiple) {
211 t.Errorf("%s (%s): squeezing %d bytes one at a time failed", functionName, impl, len(ref))
217 // sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing.
218 func sequentialBytes(size int) []byte {
219 result := make([]byte, size)
220 for i := range result {
226 // BenchmarkPermutationFunction measures the speed of the permutation function
227 // with no input data.
228 func BenchmarkPermutationFunction(b *testing.B) {
229 b.SetBytes(int64(200))
231 for i := 0; i < b.N; i++ {
236 // benchmarkHash tests the speed to hash num buffers of buflen each.
237 func benchmarkHash(b *testing.B, h hash.Hash, size, num int) {
240 data := sequentialBytes(size)
241 b.SetBytes(int64(size * num))
245 for i := 0; i < b.N; i++ {
246 for j := 0; j < num; j++ {
249 state = h.Sum(state[:0])
255 // benchmarkShake is specialized to the Shake instances, which don't
256 // require a copy on reading output.
257 func benchmarkShake(b *testing.B, h ShakeHash, size, num int) {
260 data := sequentialBytes(size)
261 d := make([]byte, 32)
263 b.SetBytes(int64(size * num))
266 for i := 0; i < b.N; i++ {
268 for j := 0; j < num; j++ {
275 func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) }
276 func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) }
277 func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) }
278 func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) }
280 func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 1350, 1) }
281 func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) }
282 func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) }
283 func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) }
285 func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) }
288 buf := []byte("some data to hash")
289 // A hash needs to be 64 bytes long to have 256-bit collision resistance.
290 h := make([]byte, 64)
291 // Compute a 64-byte hash of buf and put it in h.
293 fmt.Printf("%x\n", h)
294 // Output: 0f65fe41fc353e52c55667bb9e2b27bfcc8476f2c413e9437d272ee3194a4e3146d05ec04a25d16b8f577c19b82d16b1424c3e022e783d2b4da98de3658d363d
298 k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long")
299 buf := []byte("and this is some data to authenticate")
300 // A MAC with 32 bytes of output has 256-bit security strength -- if you use at least a 32-byte-long key.
301 h := make([]byte, 32)
303 // Write the key into the hash.
305 // Now write the data.
307 // Read 32 bytes of output from the hash into h.
309 fmt.Printf("%x\n", h)
310 // Output: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff