keccak256-circom/go-keccak256-bits-impl/keccak.go
go-keccak256-bits-impl/keccak.goRaw
1package keccak
2
3import "fmt"
4
5var roundConstantsU64 = []uint64{
6 0x0000000000000001, 0x0000000000008082, 0x800000000000808A,
7 0x8000000080008000, 0x000000000000808B, 0x0000000080000001,
8 0x8000000080008081, 0x8000000000008009, 0x000000000000008A,
9 0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
10 0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
11 0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
12 0x000000000000800A, 0x800000008000000A, 0x8000000080008081,
13 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
14}
15
16var roundConstants = u64ArrayToBits(roundConstantsU64)
17
18const (
19 rounds = 24
20 size = 32
21 blockSize = 136
22 domain = 0x01
23)
24
25func ComputeKeccak(b []bool) []bool {
26 if len(b) >= blockSize*8 {
27 // TODO absorb
28 }
29 s := final(b)
30 b = squeeze(s)
31
32 return b
33}
34
35func final(b []bool) [25 * 64]bool {
36 last := pad(b)
37 var s [25 * 64]bool
38 s = absorb(s, last)
39 return s
40}
41func pad(b []bool) []bool {
42 padded := make([]bool, blockSize*8)
43 copy(padded, b)
44 copy(padded[len(b):len(b)+8], byteToBits(domain))
45 copy(padded[(len(padded)-8):],
46 or(padded[(len(padded)-8):], byteToBits(0x80)))
47 return padded
48}
49func absorb(s [25 * 64]bool, block []bool) [25 * 64]bool {
50 if len(block) != blockSize*8 {
51 panic(fmt.Errorf("absorb: invalid block size: %d, expected: %d",
52 len(block), blockSize*8))
53 }
54
55 for i := 0; i < blockSize/8; i++ {
56 copy(s[i*64:i*64+64], xor(s[i*64:i*64+64], block[i*64:i*64+64]))
57 }
58 newS := keccakf(s)
59 return newS
60}
61
62func squeeze(s [25 * 64]bool) []bool {
63 // option1
64 // b := make([]bool, 8*8*len(s))
65 // for i := 0; i < 25; i++ {
66 // copy(b[i*64:i*64+64], s[i*64:i*64+64])
67 // }
68 // return b[:size*8]
69
70 // option2
71 // out := make([]bool, size*8)
72 // for i := 0; i < 25; i++ {
73 // for j := 0; j < 64; j++ {
74 // if i*64+j < size*8 {
75 // out[i*64+j] = s[i*64+j]
76 // }
77 // }
78 // }
79 // return out
80
81 // option3
82 return s[:size*8]
83}
84
85func keccakfRound(s [25 * 64]bool, r int) [25 * 64]bool {
86 s = theta(s)
87 s = rhopi(s)
88 s = chi(s)
89 s = iot(s, r)
90 return s
91}
92func keccakf(s [25 * 64]bool) [25 * 64]bool {
93 for r := 0; r < rounds; r++ {
94 s = keccakfRound(s, r)
95 }
96 return s
97}