From bfdd4767cf90c943ee66b7ad4bcb822dec1c1935 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sun, 31 Oct 2021 01:58:47 +0200 Subject: [PATCH] Add Theta go impl --- go-keccak256-bits-impl/ref.go | 51 +++++++++++++++++++++ go-keccak256-bits-impl/stepmappings.go | 48 +++++++++++++++++++ go-keccak256-bits-impl/stepmappings_test.go | 43 +++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 go-keccak256-bits-impl/ref.go create mode 100644 go-keccak256-bits-impl/stepmappings.go create mode 100644 go-keccak256-bits-impl/stepmappings_test.go diff --git a/go-keccak256-bits-impl/ref.go b/go-keccak256-bits-impl/ref.go new file mode 100644 index 0000000..cac71c1 --- /dev/null +++ b/go-keccak256-bits-impl/ref.go @@ -0,0 +1,51 @@ +/* +This file contains the byte & uint64 implementations that are used to test the +bits implementations. +*/ +package keccak + +func thetaU64Version(a [25]uint64) [25]uint64 { + var c0, c1, c2, c3, c4, d uint64 + var r [25]uint64 + c0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + c1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + c2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + c3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + c4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + + d = c4 ^ (c1<<1 | c1>>(64-1)) + r[0] = a[0] ^ d + r[5] = a[5] ^ d + r[10] = a[10] ^ d + r[15] = a[15] ^ d + r[20] = a[20] ^ d + + d = c0 ^ (c2<<1 | c2>>(64-1)) + r[1] = a[1] ^ d + r[6] = a[6] ^ d + r[11] = a[11] ^ d + r[16] = a[16] ^ d + r[21] = a[21] ^ d + + d = c1 ^ (c3<<1 | c3>>(64-1)) + r[2] = a[2] ^ d + r[7] = a[7] ^ d + r[12] = a[12] ^ d + r[17] = a[17] ^ d + r[22] = a[22] ^ d + + d = c2 ^ (c4<<1 | c4>>(64-1)) + r[3] = a[3] ^ d + r[8] = a[8] ^ d + r[13] = a[13] ^ d + r[18] = a[18] ^ d + r[23] = a[23] ^ d + + d = c3 ^ (c0<<1 | c0>>(64-1)) + r[4] = a[4] ^ d + r[9] = a[9] ^ d + r[14] = a[14] ^ d + r[19] = a[19] ^ d + r[24] = a[24] ^ d + return r +} diff --git a/go-keccak256-bits-impl/stepmappings.go b/go-keccak256-bits-impl/stepmappings.go new file mode 100644 index 0000000..dd98b68 --- /dev/null +++ b/go-keccak256-bits-impl/stepmappings.go @@ -0,0 +1,48 @@ +package keccak + +func theta(a [25 * 64]bool) [25 * 64]bool { + var c0, c1, c2, c3, c4, d [64]bool + var r [25 * 64]bool + + copy(c0[:], xor(xor(xor(xor(a[0:1*64], a[5*64:6*64]), a[10*64:11*64]), a[15*64:16*64]), a[20*64:21*64])) + copy(c1[:], xor(xor(xor(xor(a[1*64:2*64], a[6*64:7*64]), a[11*64:12*64]), a[16*64:17*64]), a[21*64:22*64])) + copy(c2[:], xor(xor(xor(xor(a[2*64:3*64], a[7*64:8*64]), a[12*64:13*64]), a[17*64:18*64]), a[22*64:23*64])) + copy(c3[:], xor(xor(xor(xor(a[3*64:4*64], a[8*64:9*64]), a[13*64:14*64]), a[18*64:19*64]), a[23*64:24*64])) + copy(c4[:], xor(xor(xor(xor(a[4*64:5*64], a[9*64:10*64]), a[14*64:15*64]), a[19*64:20*64]), a[24*64:25*64])) + + copy(d[:], xor(c4[:], or(leftShift(c1[:], 1), rightShift(c1[:], (64-1))))) + copy(r[0:1*64], xor(a[0:1*64], d[:])) + copy(r[5*64:6*64], xor(a[5*64:6*64], d[:])) + copy(r[10*64:11*64], xor(a[10*64:11*64], d[:])) + copy(r[15*64:16*64], xor(a[15*64:16*64], d[:])) + copy(r[20*64:21*64], xor(a[20*64:21*64], d[:])) + + copy(d[:], xor(c0[:], or(leftShift(c2[:], 1), rightShift(c2[:], (64-1))))) + copy(r[1*64:2*64], xor(a[1*64:2*64], d[:])) + copy(r[6*64:7*64], xor(a[6*64:7*64], d[:])) + copy(r[11*64:12*64], xor(a[11*64:12*64], d[:])) + copy(r[16*64:17*64], xor(a[16*64:17*64], d[:])) + copy(r[21*64:22*64], xor(a[21*64:22*64], d[:])) + + copy(d[:], xor(c1[:], or(leftShift(c3[:], 1), rightShift(c3[:], (64-1))))) + copy(r[2*64:3*64], xor(a[2*64:3*64], d[:])) + copy(r[7*64:8*64], xor(a[7*64:8*64], d[:])) + copy(r[12*64:13*64], xor(a[12*64:13*64], d[:])) + copy(r[17*64:18*64], xor(a[17*64:18*64], d[:])) + copy(r[22*64:23*64], xor(a[22*64:23*64], d[:])) + + copy(d[:], xor(c2[:], or(leftShift(c4[:], 1), rightShift(c4[:], (64-1))))) + copy(r[3*64:4*64], xor(a[3*64:4*64], d[:])) + copy(r[8*64:9*64], xor(a[8*64:9*64], d[:])) + copy(r[13*64:14*64], xor(a[13*64:14*64], d[:])) + copy(r[18*64:19*64], xor(a[18*64:19*64], d[:])) + copy(r[23*64:24*64], xor(a[23*64:24*64], d[:])) + + copy(d[:], xor(c3[:], or(leftShift(c0[:], 1), rightShift(c0[:], (64-1))))) + copy(r[4*64:5*64], xor(a[4*64:5*64], d[:])) + copy(r[9*64:10*64], xor(a[9*64:10*64], d[:])) + copy(r[14*64:15*64], xor(a[14*64:15*64], d[:])) + copy(r[19*64:20*64], xor(a[19*64:20*64], d[:])) + copy(r[24*64:25*64], xor(a[24*64:25*64], d[:])) + return r +} diff --git a/go-keccak256-bits-impl/stepmappings_test.go b/go-keccak256-bits-impl/stepmappings_test.go new file mode 100644 index 0000000..04701f7 --- /dev/null +++ b/go-keccak256-bits-impl/stepmappings_test.go @@ -0,0 +1,43 @@ +package keccak + +import ( + "encoding/json" + "fmt" + "testing" + + qt "github.com/frankban/quicktest" +) + +func printS(n string, s []uint64) { + jS, err := json.Marshal(s) + if err != nil { + panic(err) + } + fmt.Printf("%s: %s\n", n, string(jS)) +} +func newS() ([25 * 64]bool, [25]uint64) { + var s [25 * 64]bool + var sU64 [25]uint64 + for i := 0; i < len(s)/64; i++ { + copy(s[i*64:i*64+64], u64ToBits(uint64(i))) + sU64[i] = uint64(i) + } + return s, sU64 +} + +func TestTheta(t *testing.T) { + s, sU64 := newS() + + s = theta(s) + sU64 = thetaU64Version(sU64) + + qt.Assert(t, bitsToU64Array(s[:]), qt.DeepEquals, sU64[:]) + qt.Assert(t, bitsToU64Array(s[:]), qt.DeepEquals, + []uint64{26, 9, 13, 29, 47, 31, 14, 8, 22, 34, 16, 3, 3, + 19, 37, 21, 24, 30, 12, 56, 14, 29, 25, 9, 51}) + + // compute again theta on the current state + s = theta(s) + sU64 = thetaU64Version(sU64) + qt.Assert(t, bitsToU64Array(s[:]), qt.DeepEquals, sU64[:]) +}