arnaucube
arnaucube/keccak256-circomPublic Self-hosted repository
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}
41
42func pad(b []bool) []bool {
43	padded := make([]bool, blockSize*8)
44	copy(padded, b)
45	copy(padded[len(b):len(b)+8], byteToBits(domain))
46	copy(padded[(len(padded)-8):],
47		or(padded[(len(padded)-8):], byteToBits(0x80)))
48	return padded
49}
50
51func absorb(s [25 * 64]bool, block []bool) [25 * 64]bool {
52	if len(block) != blockSize*8 {
53		panic(fmt.Errorf("absorb: invalid block size: %d, expected: %d",
54			len(block), blockSize*8))
55	}
56
57	for i := 0; i < blockSize/8; i++ {
58		copy(s[i*64:i*64+64], xor(s[i*64:i*64+64], block[i*64:i*64+64]))
59	}
60	newS := keccakf(s)
61	return newS
62}
63
64func squeeze(s [25 * 64]bool) []bool {
65	// option1
66	// b := make([]bool, 8*8*len(s))
67	// for i := 0; i < 25; i++ {
68	//         copy(b[i*64:i*64+64], s[i*64:i*64+64])
69	// }
70	// return b[:size*8]
71
72	// option2
73	// out := make([]bool, size*8)
74	// for i := 0; i < 25; i++ {
75	//         for j := 0; j < 64; j++ {
76	//                 if i*64+j < size*8 {
77	//                         out[i*64+j] = s[i*64+j]
78	//                 }
79	//         }
80	// }
81	// return out
82
83	// option3
84	return s[:size*8]
85}
86
87func keccakfRound(s [25 * 64]bool, r int) [25 * 64]bool {
88	s = theta(s)
89	s = rhopi(s)
90	s = chi(s)
91	s = iot(s, r)
92	return s
93}
94func keccakf(s [25 * 64]bool) [25 * 64]bool {
95	for r := 0; r < rounds; r++ {
96		s = keccakfRound(s, r)
97	}
98	return s
99}