Search Apps Documentation Source Content File Folder Download Copy Actions Download

sha3_test.gno

9.80 Kb ยท 304 lines
  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
  5package keccak256
  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
 13import (
 14	"bytes"
 15	"encoding/hex"
 16	"hash"
 17	"math/rand"
 18	"testing"
 19)
 20
 21const (
 22	testString  = "brekeccakkeccak koax koax"
 23	katFilename = "testdata/keccakKats.json.deflate"
 24)
 25
 26// testDigests contains functions returning hash.Hash instances
 27// with output-length equal to the KAT length for SHA-3, Keccak
 28// and SHAKE instances.
 29var testDigests = map[string]func() hash.Hash{
 30	"Keccak-256": NewLegacyKeccak256,
 31}
 32
 33// decodeHex converts a hex-encoded string into a raw byte string.
 34func decodeHex(s string) []byte {
 35	b, err := hex.DecodeString(s)
 36	if err != nil {
 37		panic(err)
 38	}
 39	return b
 40}
 41
 42// structs used to marshal JSON test-cases.
 43type KeccakKats struct {
 44	Kats map[string][]struct {
 45		Digest  string `json:"digest"`
 46		Length  int64  `json:"length"`
 47		Message string `json:"message"`
 48
 49		// Defined only for cSHAKE
 50		N string `json:"N"`
 51		S string `json:"S"`
 52	}
 53}
 54
 55// TestKeccakKats tests the SHA-3 and Shake implementations against all the
 56// ShortMsgKATs from https://github.com/gvanas/KeccakCodePackage
 57// (The testvectors are stored in keccakKats.json.deflate due to their length.)
 58//XXX Do not use "compress/flate"
 59/*func TestKeccakKats(t *testing.T) {
 60	// Read the KATs.
 61	deflated, err := os.Open(katFilename)
 62	if err != nil {
 63		t.Errorf("error opening %s: %s", katFilename, err)
 64	}
 65	file := flate.NewReader(deflated)
 66	dec := json.NewDecoder(file)
 67	var katSet KeccakKats
 68	err = dec.Decode(&katSet)
 69	if err != nil {
 70		t.Errorf("error decoding KATs: %s", err)
 71	}
 72
 73	for algo, function := range testDigests {
 74		d := function()
 75		for _, kat := range katSet.Kats[algo] {
 76			d.Reset()
 77			in, err := hex.DecodeString(kat.Message)
 78			if err != nil {
 79				t.Errorf("error decoding KAT: %s", err)
 80			}
 81			d.Write(in[:kat.Length/8])
 82			got := strings.ToUpper(hex.EncodeToString(d.Sum(nil)))
 83			if got != kat.Digest {
 84				t.Errorf("function=%s, length=%d\nmessage:\n %s\ngot:\n  %s\nwanted:\n %s",
 85					algo, kat.Length, kat.Message, got, kat.Digest)
 86				t.Logf("wanted %+v", kat)
 87				t.FailNow()
 88			}
 89			continue
 90		}
 91	}
 92
 93	for algo, v := range testShakes {
 94		for _, kat := range katSet.Kats[algo] {
 95			N, err := hex.DecodeString(kat.N)
 96			if err != nil {
 97				t.Errorf("error decoding KAT: %s", err)
 98			}
 99
100			S, err := hex.DecodeString(kat.S)
101			if err != nil {
102				t.Errorf("error decoding KAT: %s", err)
103			}
104			d := v.constructor(N, S)
105			in, err := hex.DecodeString(kat.Message)
106			if err != nil {
107				t.Errorf("error decoding KAT: %s", err)
108			}
109
110			d.Write(in[:kat.Length/8])
111			out := make([]byte, len(kat.Digest)/2)
112			d.Read(out)
113			got := strings.ToUpper(hex.EncodeToString(out))
114			if got != kat.Digest {
115				t.Errorf("function=%s, length=%d N:%s\n S:%s\nmessage:\n %s \ngot:\n  %s\nwanted:\n %s",
116					algo, kat.Length, kat.N, kat.S, kat.Message, got, kat.Digest)
117				t.Logf("wanted %+v", kat)
118				t.FailNow()
119			}
120			continue
121		}
122	}
123}*/
124
125// TestKeccak does a basic test of the non-standardized Keccak hash functions.
126func TestKeccak(t *testing.T) {
127	tests := []struct {
128		fn   func() hash.Hash
129		data []byte
130		want string
131	}{
132
133		{
134			NewLegacyKeccak256,
135			[]byte("There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text"),
136			"39670cbdfbfc25519e9834899e13569e5f5802b77df3d8259961f713ad09745d",
137		},
138		{
139			NewLegacyKeccak256,
140			[]byte("abc"),
141			"4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45",
142		},
143		{
144			NewLegacyKeccak256,
145			[]byte("916889520661998333947422699691"),
146			"c5b223cc231dd56389ca19435758fba38e79f3c461d989d818ceb96595d310d1",
147		},
148		{
149			NewLegacyKeccak256,
150			[]byte("6R1Q2KvQNGxI4OtUGDS1rSCbJXkp1H"),
151			"8e94c6d49ca23597ee1d4a317b17a85ae38f6f3241e11c3ace4abe756287839a",
152		},
153		{
154			NewLegacyKeccak256,
155			[]byte("SOMERANDOMSTRING"),
156			"59f47b8dc1ffdfb716d2fcb313c070040f6049bd23c321c6cb8adb3f79eb720f",
157		},
158		{
159			NewLegacyKeccak256,
160			[]byte("Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC"),
161			"da5293ad50619d7fdac8b4c8dc2f80e0cd40b6571be14740229d0a1d6e2fc232",
162		},
163		{
164			NewLegacyKeccak256,
165			[]byte("There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc."),
166			"a84506d23b7246dc18805c8bf60316fb6f677934a546ee8d8650495929f21eef",
167		},
168	}
169
170	for _, u := range tests {
171		h := u.fn()
172		h.Write(u.data)
173		got := h.Sum(nil)
174		want := decodeHex(u.want)
175		if !bytes.Equal(got, want) {
176			t.Errorf("unexpected hash for size %d: got '%x' want '%s'", h.Size()*8, got, u.want)
177		}
178	}
179}
180
181func TestHash(t *testing.T) {
182	tests := []struct {
183		data []byte
184		want string
185	}{
186
187		{
188
189			[]byte("There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text"),
190			"39670cbdfbfc25519e9834899e13569e5f5802b77df3d8259961f713ad09745d",
191		},
192		{
193
194			[]byte("abc"),
195			"4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45",
196		},
197		{
198
199			[]byte("916889520661998333947422699691"),
200			"c5b223cc231dd56389ca19435758fba38e79f3c461d989d818ceb96595d310d1",
201		},
202		{
203
204			[]byte("6R1Q2KvQNGxI4OtUGDS1rSCbJXkp1H"),
205			"8e94c6d49ca23597ee1d4a317b17a85ae38f6f3241e11c3ace4abe756287839a",
206		},
207		{
208
209			[]byte("SOMERANDOMSTRING"),
210			"59f47b8dc1ffdfb716d2fcb313c070040f6049bd23c321c6cb8adb3f79eb720f",
211		},
212		{
213
214			[]byte("Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC"),
215			"da5293ad50619d7fdac8b4c8dc2f80e0cd40b6571be14740229d0a1d6e2fc232",
216		},
217		{
218
219			[]byte("There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc."),
220			"a84506d23b7246dc18805c8bf60316fb6f677934a546ee8d8650495929f21eef",
221		},
222	}
223
224	for _, u := range tests {
225		got := Hash(u.data)
226		want := decodeHex(u.want)
227		if !bytes.Equal(got[:], want) {
228			t.Errorf("unexpected hash: got '%x' want '%s'", got, u.want)
229		}
230	}
231}
232
233// sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing.
234//
235// The alignment of each slice is intentionally randomized to detect alignment
236// issues in the implementation. See https://golang.org/issue/37644.
237// Ideally, the compiler should fuzz the alignment itself.
238// (See https://golang.org/issue/35128.)
239func sequentialBytes(size int) []byte {
240	alignmentOffset := rand.IntN(8)
241	result := make([]byte, size+alignmentOffset)[alignmentOffset:]
242	for i := range result {
243		result[i] = byte(i)
244	}
245	return result
246}
247
248/*func TestMarshalUnmarshal(t *testing.T) {
249	t.Run("Keccak-256", func(t *testing.T) { testMarshalUnmarshal(t, NewLegacyKeccak256()) })
250}*/
251
252// TODO(filippo): move this to crypto/internal/cryptotest.
253//XX: remove rand.Read
254/*func testMarshalUnmarshal(t *testing.T, h hash.Hash) {
255	buf := make([]byte, 200)
256	rand.Read(buf)
257	n := rand.IntN(200)
258	h.Write(buf)
259	want := h.Sum(nil)
260	h.Reset()
261	h.Write(buf[:n])
262	b, err := h.(encoding.BinaryMarshaler).MarshalBinary()
263	if err != nil {
264		t.Errorf("MarshalBinary: %v", err)
265	}
266	h.Write(bytes.Repeat([]byte{0}, 200))
267	if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary(b); err != nil {
268		t.Errorf("UnmarshalBinary: %v", err)
269	}
270	h.Write(buf[n:])
271	got := h.Sum(nil)
272	if !bytes.Equal(got, want) {
273		t.Errorf("got %x, want %x", got, want)
274	}
275}*/
276
277// BenchmarkPermutationFunction measures the speed of the permutation function
278// with no input data.
279func BenchmarkPermutationFunction(b *testing.B) {
280	b.SetBytes(int64(200))
281	var lanes [25]uint64
282	for i := 0; i < b.N; i++ {
283		keccakF1600(&lanes)
284	}
285}
286
287// benchmarkHash tests the speed to hash num buffers of buflen each.
288func benchmarkHash(b *testing.B, h hash.Hash, size, num int) {
289	b.StopTimer()
290	h.Reset()
291	data := sequentialBytes(size)
292	b.SetBytes(int64(size * num))
293	b.StartTimer()
294
295	var state []byte
296	for i := 0; i < b.N; i++ {
297		for j := 0; j < num; j++ {
298			h.Write(data)
299		}
300		state = h.Sum(state[:0])
301	}
302	b.StopTimer()
303	h.Reset()
304}