diff --git a/gen.go b/gen.go new file mode 100644 index 0000000..9dcd0e5 --- /dev/null +++ b/gen.go @@ -0,0 +1,122 @@ +// +build ignore + +package main + +import ( + "fmt" + "os" + "text/template" +) + +var roundc [24]uint64 +var rotc [5][5]int + +func main() { + // Round constants + rc := uint8(1) + for i := 0; i < 24; i++ { + for j := 0; j <= 6; j++ { + roundc[i] |= uint64(rc&1) << (1<>7) + } + } + + // Rotation constants + x, y := 1, 0 + for i := 1; i < 25; i++ { + rotc[x][y] = (i*(i+1)/2) % 64 + x, y = y, (2*x+3*y)%5 + } + + var ctx = struct { + Rotc [5][5]int + } { + rotc, + } + err := tmpl.Execute(os.Stdout, &ctx) + if err != nil { + fmt.Println(err) + } +} + +func count(n int) []int { + var out = make([]int, n) + for i := 0; i < n; i ++ { + out[i] = i + } + return out +} + +func add(a, b, m int) int { + return (a+b) % m +} + +func sub(a, b int) int { + return a - b +} + +func mul(a, b int) int { + return a*b +} + +var funcs = template.FuncMap{ + "count": count, + "add": add, + "sub": sub, + "mul": mul, +} + +var tmpl = template.Must(template.New("keccak").Funcs(funcs).Parse(` +// Generated from go run gen.go +// DO NOT EDIT + +package keccak + +// roundGeneric implements one round of the keccak-f[1600] permutation. +func roundGeneric(a *[5][5]uint64) { + {{ range $x := count 5 }} + {{ range $y := count 5 }} + var a{{$x}}{{$y}} = a[{{$y}}][{{$x}}] + {{ end }} + {{ end }} + + // Theta + var c0, c1, c2, c3, c4 uint64 + {{ range $x := count 5 }} + c{{$x}} = a{{$x}}0 ^ a{{$x}}1 ^ a{{$x}}2 ^ a{{$x}}3 ^ a{{$x}}4 + {{ end }} + {{ range $x := count 5 }} + {{ $x0 := add $x 4 5 }} + {{ $x1 := add $x 1 5 }} + a{{$x}}0 ^= c{{$x0}} ^ (c{{$x1}}<<1 | c{{$x1}}>>63) + a{{$x}}1 ^= c{{$x0}} ^ (c{{$x1}}<<1 | c{{$x1}}>>63) + a{{$x}}2 ^= c{{$x0}} ^ (c{{$x1}}<<1 | c{{$x1}}>>63) + a{{$x}}3 ^= c{{$x0}} ^ (c{{$x1}}<<1 | c{{$x1}}>>63) + a{{$x}}4 ^= c{{$x0}} ^ (c{{$x1}}<<1 | c{{$x1}}>>63) + {{ end }} + + // Rho and pi + {{ range $y := count 5 }} + {{ range $x := count 5 }} + {{ $x0 := $y }} + {{ $y0 := add (mul $x 2) (mul $y 3) 5 }} + {{ $r := index $.Rotc $x $y }} + var b{{$x0}}{{$y0}} = a{{$x}}{{$y}}<<{{$r}} | a{{$x}}{{$y}}>>{{sub 64 $r}} + {{ end }} + {{ end }} + + // Chi + {{ range $y := count 5 }} + {{ range $x := count 5 }} + a{{$x}}{{$y}} = b{{$x}}{{$y}} ^ (b{{add $x 2 5}}{{$y}} &^ b{{add $x 1 5}}{{$y}}) + {{ end }} + {{ end }} + + // Output + {{ range $y := count 5 }} + {{ range $x := count 5 }} + a[{{$y}}][{{$x}}] = a{{$x}}{{$y}} + {{ end }} + {{ end }} +} +`)) diff --git a/genconst.go b/genconst.go deleted file mode 100644 index 3187d90..0000000 --- a/genconst.go +++ /dev/null @@ -1,27 +0,0 @@ -// +build ignore - -package main - -import "fmt" - -func main() { - //Round constants - var RC [24]uint64 - rc := uint8(1) - for i := 0; i < 24; i++ { - for j := 0; j <= 6; j++ { - RC[i] |= uint64(rc&1) << (1<>7) - } - } - fmt.Println("package keccak") - fmt.Printf("var RC = %#016v\n", RC) - - var rot [5][5]uint - x, y := 1, 0 - for i := 0; i < 24; i++ { - rot[y][x] = uint((i+1)*(i+2)/2) % 64 - x, y = y, (2*x+3*y)%5 - } - fmt.Printf("var rotc = %#v\n", rot) -} diff --git a/keccak.go b/keccak.go index 45604ad..ee18b14 100644 --- a/keccak.go +++ b/keccak.go @@ -28,15 +28,14 @@ func roundGeneric(a *[5][5]uint64) { // Chi for y := range a[0] { - c := [5]uint64{b[y][0], b[y][1], b[y][2], b[y][3], b[y][4]} - a[y][0] = b[y][0] ^ ^c[1]&c[2] - a[y][1] = b[y][1] ^ ^c[2]&c[3] - a[y][2] = b[y][2] ^ ^c[3]&c[4] - a[y][3] = b[y][3] ^ ^c[4]&c[0] - a[y][4] = b[y][4] ^ ^c[0]&c[1] + a[y][0] = b[y][0] ^ ^b[y][1]&b[y][2] + a[y][1] = b[y][1] ^ ^b[y][2]&b[y][3] + a[y][2] = b[y][2] ^ ^b[y][3]&b[y][4] + a[y][3] = b[y][3] ^ ^b[y][4]&b[y][0] + a[y][4] = b[y][4] ^ ^b[y][0]&b[y][1] } } func rotl(a uint64, r uint) uint64 { - return a<>(64-r) + return a<<(r%64) | a>>(64-(r%64)) } diff --git a/keccak_gen.go b/keccak_gen.go new file mode 100644 index 0000000..91a46ee --- /dev/null +++ b/keccak_gen.go @@ -0,0 +1,258 @@ +// Generated from go run gen.go +// DO NOT EDIT + +package keccak + +// roundGeneric implements one round of the keccak-f[1600] permutation. +func roundGen(a *[5][5]uint64) { + + var a00 = a[0][0] + + var a01 = a[1][0] + + var a02 = a[2][0] + + var a03 = a[3][0] + + var a04 = a[4][0] + + var a10 = a[0][1] + + var a11 = a[1][1] + + var a12 = a[2][1] + + var a13 = a[3][1] + + var a14 = a[4][1] + + var a20 = a[0][2] + + var a21 = a[1][2] + + var a22 = a[2][2] + + var a23 = a[3][2] + + var a24 = a[4][2] + + var a30 = a[0][3] + + var a31 = a[1][3] + + var a32 = a[2][3] + + var a33 = a[3][3] + + var a34 = a[4][3] + + var a40 = a[0][4] + + var a41 = a[1][4] + + var a42 = a[2][4] + + var a43 = a[3][4] + + var a44 = a[4][4] + + // Theta + var c0, c1, c2, c3, c4 uint64 + + c0 = a00 ^ a01 ^ a02 ^ a03 ^ a04 + + c1 = a10 ^ a11 ^ a12 ^ a13 ^ a14 + + c2 = a20 ^ a21 ^ a22 ^ a23 ^ a24 + + c3 = a30 ^ a31 ^ a32 ^ a33 ^ a34 + + c4 = a40 ^ a41 ^ a42 ^ a43 ^ a44 + + a00 ^= c4 ^ (c1<<1 | c1>>63) + a01 ^= c4 ^ (c1<<1 | c1>>63) + a02 ^= c4 ^ (c1<<1 | c1>>63) + a03 ^= c4 ^ (c1<<1 | c1>>63) + a04 ^= c4 ^ (c1<<1 | c1>>63) + + a10 ^= c0 ^ (c2<<1 | c2>>63) + a11 ^= c0 ^ (c2<<1 | c2>>63) + a12 ^= c0 ^ (c2<<1 | c2>>63) + a13 ^= c0 ^ (c2<<1 | c2>>63) + a14 ^= c0 ^ (c2<<1 | c2>>63) + + a20 ^= c1 ^ (c3<<1 | c3>>63) + a21 ^= c1 ^ (c3<<1 | c3>>63) + a22 ^= c1 ^ (c3<<1 | c3>>63) + a23 ^= c1 ^ (c3<<1 | c3>>63) + a24 ^= c1 ^ (c3<<1 | c3>>63) + + a30 ^= c2 ^ (c4<<1 | c4>>63) + a31 ^= c2 ^ (c4<<1 | c4>>63) + a32 ^= c2 ^ (c4<<1 | c4>>63) + a33 ^= c2 ^ (c4<<1 | c4>>63) + a34 ^= c2 ^ (c4<<1 | c4>>63) + + a40 ^= c3 ^ (c0<<1 | c0>>63) + a41 ^= c3 ^ (c0<<1 | c0>>63) + a42 ^= c3 ^ (c0<<1 | c0>>63) + a43 ^= c3 ^ (c0<<1 | c0>>63) + a44 ^= c3 ^ (c0<<1 | c0>>63) + + // Rho and pi + + var b00 = a00<<0 | a00>>64 + + var b02 = a10<<1 | a10>>63 + + var b04 = a20<<62 | a20>>2 + + var b01 = a30<<28 | a30>>36 + + var b03 = a40<<27 | a40>>37 + + var b13 = a01<<36 | a01>>28 + + var b10 = a11<<44 | a11>>20 + + var b12 = a21<<6 | a21>>58 + + var b14 = a31<<55 | a31>>9 + + var b11 = a41<<20 | a41>>44 + + var b21 = a02<<3 | a02>>61 + + var b23 = a12<<10 | a12>>54 + + var b20 = a22<<43 | a22>>21 + + var b22 = a32<<25 | a32>>39 + + var b24 = a42<<39 | a42>>25 + + var b34 = a03<<41 | a03>>23 + + var b31 = a13<<45 | a13>>19 + + var b33 = a23<<15 | a23>>49 + + var b30 = a33<<21 | a33>>43 + + var b32 = a43<<8 | a43>>56 + + var b42 = a04<<18 | a04>>46 + + var b44 = a14<<2 | a14>>62 + + var b41 = a24<<61 | a24>>3 + + var b43 = a34<<56 | a34>>8 + + var b40 = a44<<14 | a44>>50 + + // Chi + + a00 = b00 ^ (b20 &^ b10) + + a10 = b10 ^ (b30 &^ b20) + + a20 = b20 ^ (b40 &^ b30) + + a30 = b30 ^ (b00 &^ b40) + + a40 = b40 ^ (b10 &^ b00) + + a01 = b01 ^ (b21 &^ b11) + + a11 = b11 ^ (b31 &^ b21) + + a21 = b21 ^ (b41 &^ b31) + + a31 = b31 ^ (b01 &^ b41) + + a41 = b41 ^ (b11 &^ b01) + + a02 = b02 ^ (b22 &^ b12) + + a12 = b12 ^ (b32 &^ b22) + + a22 = b22 ^ (b42 &^ b32) + + a32 = b32 ^ (b02 &^ b42) + + a42 = b42 ^ (b12 &^ b02) + + a03 = b03 ^ (b23 &^ b13) + + a13 = b13 ^ (b33 &^ b23) + + a23 = b23 ^ (b43 &^ b33) + + a33 = b33 ^ (b03 &^ b43) + + a43 = b43 ^ (b13 &^ b03) + + a04 = b04 ^ (b24 &^ b14) + + a14 = b14 ^ (b34 &^ b24) + + a24 = b24 ^ (b44 &^ b34) + + a34 = b34 ^ (b04 &^ b44) + + a44 = b44 ^ (b14 &^ b04) + + // Output + + a[0][0] = a00 + + a[0][1] = a10 + + a[0][2] = a20 + + a[0][3] = a30 + + a[0][4] = a40 + + a[1][0] = a01 + + a[1][1] = a11 + + a[1][2] = a21 + + a[1][3] = a31 + + a[1][4] = a41 + + a[2][0] = a02 + + a[2][1] = a12 + + a[2][2] = a22 + + a[2][3] = a32 + + a[2][4] = a42 + + a[3][0] = a03 + + a[3][1] = a13 + + a[3][2] = a23 + + a[3][3] = a33 + + a[3][4] = a43 + + a[4][0] = a04 + + a[4][1] = a14 + + a[4][2] = a24 + + a[4][3] = a34 + + a[4][4] = a44 + +} diff --git a/keccak_test.go b/keccak_test.go index 4606d74..a582e6d 100644 --- a/keccak_test.go +++ b/keccak_test.go @@ -5,7 +5,8 @@ import ( "testing" ) -var vector = []byte{0xc5, 0xd2, 0x46, 0x01, 0x86, 0xf7, 0x23, 0x3c, +var vector = []byte{ + 0xc5, 0xd2, 0x46, 0x01, 0x86, 0xf7, 0x23, 0x3c, 0x92, 0x7e, 0x7d, 0xb2, 0xdc, 0xc7, 0x03, 0xc0, 0xe5, 0x00, 0xb6, 0x53, 0xca, 0x82, 0x27, 0x3b, 0x7b, 0xfa, 0xd8, 0x04, 0x5d, 0x85, 0xa4, 0x70, diff --git a/sponge.go b/sponge.go index 47cbc8a..70ff593 100644 --- a/sponge.go +++ b/sponge.go @@ -6,6 +6,8 @@ const Size = 256 / 8 const BlockSize = 1600/8 - Size*2 +var round = roundGen + // digest implements hash.Hash type digest struct { a [5][5]uint64 // a[y][x][z] @@ -55,7 +57,7 @@ loop: func keccakf(a *[5][5]uint64) { for i := 0; i < 24; i++ { - roundGeneric(a) + round(a) a[0][0] ^= RC[i] } }