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