OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / crypto / sha3 / sha3_test.go
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
5 package sha3
6
7 // Tests include all the ShortMsgKATs provided by the Keccak team at
8 // https://github.com/gvanas/KeccakCodePackage
9 //
10 // They only include the zero-bit case of the bitwise testvectors
11 // published by NIST in the draft of FIPS-202.
12
13 import (
14         "bytes"
15         "compress/flate"
16         "encoding/hex"
17         "encoding/json"
18         "fmt"
19         "hash"
20         "os"
21         "strings"
22         "testing"
23 )
24
25 const (
26         testString  = "brekeccakkeccak koax koax"
27         katFilename = "testdata/keccakKats.json.deflate"
28 )
29
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}
33 }
34 func newHashShake256() hash.Hash {
35         return &state{rate: 136, dsbyte: 0x1f, outputLen: 512}
36 }
37
38 // testDigests contains functions returning hash.Hash instances
39 // with output-length equal to the KAT length for both SHA-3 and
40 // SHAKE instances.
41 var testDigests = map[string]func() hash.Hash{
42         "SHA3-224": New224,
43         "SHA3-256": New256,
44         "SHA3-384": New384,
45         "SHA3-512": New512,
46         "SHAKE128": newHashShake128,
47         "SHAKE256": newHashShake256,
48 }
49
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,
55 }
56
57 // decodeHex converts a hex-encoded string into a raw byte string.
58 func decodeHex(s string) []byte {
59         b, err := hex.DecodeString(s)
60         if err != nil {
61                 panic(err)
62         }
63         return b
64 }
65
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"`
72         }
73 }
74
75 func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) {
76         xorInOrig, copyOutOrig := xorIn, copyOut
77         xorIn, copyOut = xorInGeneric, copyOutGeneric
78         testf("generic")
79         if xorImplementationUnaligned != "generic" {
80                 xorIn, copyOut = xorInUnaligned, copyOutUnaligned
81                 testf("unaligned")
82         }
83         xorIn, copyOut = xorInOrig, copyOutOrig
84 }
85
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) {
91                 // Read the KATs.
92                 deflated, err := os.Open(katFilename)
93                 if err != nil {
94                         t.Errorf("error opening %s: %s", katFilename, err)
95                 }
96                 file := flate.NewReader(deflated)
97                 dec := json.NewDecoder(file)
98                 var katSet KeccakKats
99                 err = dec.Decode(&katSet)
100                 if err != nil {
101                         t.Errorf("error decoding KATs: %s", err)
102                 }
103
104                 // Do the KATs.
105                 for functionName, kats := range katSet.Kats {
106                         d := testDigests[functionName]()
107                         for _, kat := range kats {
108                                 d.Reset()
109                                 in, err := hex.DecodeString(kat.Message)
110                                 if err != nil {
111                                         t.Errorf("error decoding KAT: %s", err)
112                                 }
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)
119                                         t.FailNow()
120                                 }
121                                 continue
122                         }
123                 }
124         })
125 }
126
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 {
133                         d := df()
134                         d.Reset()
135                         d.Write(buf)
136                         want := d.Sum(nil)
137                         d.Reset()
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 {
144                                                 j = v
145                                         }
146                                         d.Write(buf[i : i+j])
147                                         i += j
148                                 }
149                         }
150                         got := d.Sum(nil)
151                         if !bytes.Equal(got, want) {
152                                 t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want)
153                         }
154                 }
155         })
156 }
157
158 // TestAppend checks that appending works when reallocation is necessary.
159 func TestAppend(t *testing.T) {
160         testUnalignedAndGeneric(t, func(impl string) {
161                 d := New224()
162
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)
167                         d.Reset()
168                         d.Write([]byte{0xcc})
169                         buf = d.Sum(buf)
170                         expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
171                         if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
172                                 t.Errorf("got %s, want %s", got, expected)
173                         }
174                 }
175         })
176 }
177
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)
182                 d := New224()
183                 d.Write([]byte{0xcc})
184                 buf = d.Sum(buf)
185                 expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
186                 if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
187                         t.Errorf("%s: got %s, want %s", impl, got, expected)
188                 }
189         })
190 }
191
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 {
197                         d0 := newShakeHash()
198                         d0.Write([]byte(testString))
199                         ref := make([]byte, 32)
200                         d0.Read(ref)
201
202                         d1 := newShakeHash()
203                         d1.Write([]byte(testString))
204                         var multiple []byte
205                         for _ = range ref {
206                                 one := make([]byte, 1)
207                                 d1.Read(one)
208                                 multiple = append(multiple, one...)
209                         }
210                         if !bytes.Equal(ref, multiple) {
211                                 t.Errorf("%s (%s): squeezing %d bytes one at a time failed", functionName, impl, len(ref))
212                         }
213                 }
214         })
215 }
216
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 {
221                 result[i] = byte(i)
222         }
223         return result
224 }
225
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))
230         var lanes [25]uint64
231         for i := 0; i < b.N; i++ {
232                 keccakF1600(&lanes)
233         }
234 }
235
236 // benchmarkHash tests the speed to hash num buffers of buflen each.
237 func benchmarkHash(b *testing.B, h hash.Hash, size, num int) {
238         b.StopTimer()
239         h.Reset()
240         data := sequentialBytes(size)
241         b.SetBytes(int64(size * num))
242         b.StartTimer()
243
244         var state []byte
245         for i := 0; i < b.N; i++ {
246                 for j := 0; j < num; j++ {
247                         h.Write(data)
248                 }
249                 state = h.Sum(state[:0])
250         }
251         b.StopTimer()
252         h.Reset()
253 }
254
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) {
258         b.StopTimer()
259         h.Reset()
260         data := sequentialBytes(size)
261         d := make([]byte, 32)
262
263         b.SetBytes(int64(size * num))
264         b.StartTimer()
265
266         for i := 0; i < b.N; i++ {
267                 h.Reset()
268                 for j := 0; j < num; j++ {
269                         h.Write(data)
270                 }
271                 h.Read(d)
272         }
273 }
274
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) }
279
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) }
284
285 func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) }
286
287 func Example_sum() {
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.
292         ShakeSum256(h, buf)
293         fmt.Printf("%x\n", h)
294         // Output: 0f65fe41fc353e52c55667bb9e2b27bfcc8476f2c413e9437d272ee3194a4e3146d05ec04a25d16b8f577c19b82d16b1424c3e022e783d2b4da98de3658d363d
295 }
296
297 func Example_mac() {
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)
302         d := NewShake256()
303         // Write the key into the hash.
304         d.Write(k)
305         // Now write the data.
306         d.Write(buf)
307         // Read 32 bytes of output from the hash into h.
308         d.Read(h)
309         fmt.Printf("%x\n", h)
310         // Output: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff
311 }