Skip to content

Commit a3f1816

Browse files
committed
Add TurboShake{128,256}
1 parent 7955403 commit a3f1816

File tree

23 files changed

+273
-78
lines changed

23 files changed

+273
-78
lines changed

internal/sha3/keccakf.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,21 @@ package sha3
66

77
// KeccakF1600 applies the Keccak permutation to a 1600b-wide
88
// state represented as a slice of 25 uint64s.
9+
// If turbo is true, applies the 12-round variant instead of the
10+
// regular 24-round variant.
911
// nolint:funlen
10-
func KeccakF1600(a *[25]uint64) {
12+
func KeccakF1600(a *[25]uint64, turbo bool) {
1113
// Implementation translated from Keccak-inplace.c
1214
// in the keccak reference code.
1315
var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64
1416

15-
for i := 0; i < 24; i += 4 {
17+
i := 0
18+
19+
if turbo {
20+
i = 12
21+
}
22+
23+
for ; i < 24; i += 4 {
1624
// Combines the 5 steps in each round into 2 steps.
1725
// Unrolls 4 rounds per loop and spreads some steps across rounds.
1826

internal/sha3/sha3.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type State struct {
5151
// Specific to SHA-3 and SHAKE.
5252
outputLen int // the default output size in bytes
5353
state spongeDirection // whether the sponge is absorbing or squeezing
54+
turbo bool // Whether we're using 12 rounds instead of 24
5455
}
5556

5657
// BlockSize returns the rate of sponge underlying this hash function.
@@ -86,11 +87,11 @@ func (d *State) permute() {
8687
xorIn(d, d.buf())
8788
d.bufe = 0
8889
d.bufo = 0
89-
KeccakF1600(&d.a)
90+
KeccakF1600(&d.a, d.turbo)
9091
case spongeSqueezing:
9192
// If we're squeezing, we need to apply the permutation before
9293
// copying more output.
93-
KeccakF1600(&d.a)
94+
KeccakF1600(&d.a, d.turbo)
9495
d.bufe = d.rate
9596
d.bufo = 0
9697
copyOut(d, d.buf())
@@ -136,7 +137,7 @@ func (d *State) Write(p []byte) (written int, err error) {
136137
// The fast path; absorb a full "rate" bytes of input and apply the permutation.
137138
xorIn(d, p[:d.rate])
138139
p = p[d.rate:]
139-
KeccakF1600(&d.a)
140+
KeccakF1600(&d.a, d.turbo)
140141
} else {
141142
// The slow path; buffer the input until we can fill the sponge, and then xor it in.
142143
todo := d.rate - bufl

internal/sha3/sha3_test.go

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,23 @@ func sequentialBytes(size int) []byte {
161161
return result
162162
}
163163

164+
// BenchmarkPermutationFunction measures the speed of the permutation function
165+
// with no input data.
166+
func BenchmarkPermutationFunctionTurbo(b *testing.B) {
167+
b.SetBytes(int64(200))
168+
var lanes [25]uint64
169+
for i := 0; i < b.N; i++ {
170+
KeccakF1600(&lanes, true)
171+
}
172+
}
173+
164174
// BenchmarkPermutationFunction measures the speed of the permutation function
165175
// with no input data.
166176
func BenchmarkPermutationFunction(b *testing.B) {
167177
b.SetBytes(int64(200))
168178
var lanes [25]uint64
169179
for i := 0; i < b.N; i++ {
170-
KeccakF1600(&lanes)
180+
KeccakF1600(&lanes, false)
171181
}
172182
}
173183

@@ -220,6 +230,9 @@ func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 135
220230
func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) }
221231
func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) }
222232

233+
func BenchmarkTurboShake128_1MiB(b *testing.B) { benchmarkShake(b, NewTurboShake128(0x37), 1024, 1024) }
234+
func BenchmarkTurboShake256_1MiB(b *testing.B) { benchmarkShake(b, NewTurboShake256(0x37), 1024, 1024) }
235+
223236
func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) }
224237

225238
func Example_sum() {
@@ -247,3 +260,26 @@ func Example_mac() {
247260
fmt.Printf("%x\n", h)
248261
// Output: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff
249262
}
263+
264+
func TestTurboShake128(t *testing.T) {
265+
out := make([]byte, 64)
266+
TurboShakeSum128(out, []byte{}, 0x07)
267+
if hex.EncodeToString(out) != "5a223ad30b3b8c66a243048cfced430f54e7529287d15150b973133adfac6a2ffe2708e73061e09a4000168ba9c8ca1813198f7bbed4984b4185f2c2580ee623" {
268+
t.Fatal()
269+
}
270+
271+
h := NewTurboShake128(0x07)
272+
out = make([]byte, 10032)
273+
_, _ = h.Read(out)
274+
if hex.EncodeToString(out[len(out)-32:]) != "7593a28020a3c4ae0d605fd61f5eb56eccd27cc3d12ff09f78369772a460c55d" {
275+
t.Fatal()
276+
}
277+
278+
out = make([]byte, 32)
279+
TurboShakeSum128(out, []byte{0xff}, 0x06)
280+
if hex.EncodeToString(out) != "8ec9c66465ed0d4a6c35d13506718d687a25cb05c74cca1e42501abd83874a67" {
281+
t.Fatal()
282+
}
283+
284+
// TODO all tests
285+
}

internal/sha3/shake.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,35 @@ func NewShake128() State {
5757
return State{rate: rate128, dsbyte: dsbyteShake}
5858
}
5959

60+
// NewTurboShake128 creates a new TurboSHAKE128 variable-output-length ShakeHash.
61+
// Its generic security strength is 128 bits against all attacks if at
62+
// least 32 bytes of its output are used.
63+
// D is the seperationByte and must be between 0x01 and 0x7f inclusive.
64+
func NewTurboShake128(D byte) State {
65+
if D == 0 || D > 0x7f {
66+
panic("turboshake: D out of range")
67+
}
68+
return State{rate: rate128, dsbyte: D, turbo: true}
69+
}
70+
6071
// NewShake256 creates a new SHAKE256 variable-output-length ShakeHash.
6172
// Its generic security strength is 256 bits against all attacks if
6273
// at least 64 bytes of its output are used.
6374
func NewShake256() State {
6475
return State{rate: rate256, dsbyte: dsbyteShake}
6576
}
6677

78+
// NewTurboShake256 creates a new TurboSHAKE256 variable-output-length ShakeHash.
79+
// Its generic security strength is 256 bits against all attacks if
80+
// at least 64 bytes of its output are used.
81+
// D is the seperationByte and must be between 0x01 and 0x7f inclusive.
82+
func NewTurboShake256(D byte) State {
83+
if D == 0 || D > 0x7f {
84+
panic("turboshake: D out of range")
85+
}
86+
return State{rate: rate256, dsbyte: D, turbo: true}
87+
}
88+
6789
// ShakeSum128 writes an arbitrary-length digest of data into hash.
6890
func ShakeSum128(hash, data []byte) {
6991
h := NewShake128()
@@ -77,3 +99,17 @@ func ShakeSum256(hash, data []byte) {
7799
_, _ = h.Write(data)
78100
_, _ = h.Read(hash)
79101
}
102+
103+
// TurboShakeSum128 writes an arbitrary-length digest of data into hash.
104+
func TurboShakeSum128(hash, data []byte, D byte) {
105+
h := NewTurboShake128(D)
106+
_, _ = h.Write(data)
107+
_, _ = h.Read(hash)
108+
}
109+
110+
// TurboShakeSum256 writes an arbitrary-length digest of data into hash.
111+
func TurboShakeSum256(hash, data []byte, D byte) {
112+
h := NewTurboShake256(D)
113+
_, _ = h.Write(data)
114+
_, _ = h.Read(hash)
115+
}

pke/kyber/internal/common/sample.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func (p *Poly) DeriveNoise2(seed []byte, nonce uint8) {
100100
// Can only be called when DeriveX4Available is true.
101101
func PolyDeriveUniformX4(ps [4]*Poly, seed *[32]byte, xs, ys [4]uint8) {
102102
var perm keccakf1600.StateX4
103-
state := perm.Initialize()
103+
state := perm.Initialize(false)
104104

105105
// Absorb the seed in the four states
106106
for i := 0; i < 4; i++ {

sign/dilithium/mode2/internal/sample.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sign/dilithium/mode2aes/internal/sample.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sign/dilithium/mode3/internal/sample.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ var DeriveX4Available = keccakf1600.IsEnabledX4() && !UseAES
1818
// Can only be called when DeriveX4Available is true.
1919
func PolyDeriveUniformX4(ps [4]*common.Poly, seed *[32]byte, nonces [4]uint16) {
2020
var perm keccakf1600.StateX4
21-
state := perm.Initialize()
21+
state := perm.Initialize(false)
2222

2323
// Absorb the seed in the four states
2424
for i := 0; i < 4; i++ {
@@ -246,7 +246,7 @@ func PolyDeriveUniformLeGamma1(p *common.Poly, seed *[64]byte, nonce uint16) {
246246
// This function is currently not used (yet).
247247
func PolyDeriveUniformBallX4(ps [4]*common.Poly, seed *[32]byte) {
248248
var perm keccakf1600.StateX4
249-
state := perm.Initialize()
249+
state := perm.Initialize(false)
250250

251251
// Absorb the seed in the four states
252252
for i := 0; i < 4; i++ {

sign/dilithium/mode3aes/internal/sample.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sign/dilithium/mode5/internal/sample.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)