package keccak
|
|
|
|
import "fmt"
|
|
|
|
var roundConstantsU64 = []uint64{
|
|
0x0000000000000001, 0x0000000000008082, 0x800000000000808A,
|
|
0x8000000080008000, 0x000000000000808B, 0x0000000080000001,
|
|
0x8000000080008081, 0x8000000000008009, 0x000000000000008A,
|
|
0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
|
|
0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
|
|
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
|
|
0x000000000000800A, 0x800000008000000A, 0x8000000080008081,
|
|
0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
|
|
}
|
|
|
|
var roundConstants = u64ArrayToBits(roundConstantsU64)
|
|
|
|
const (
|
|
rounds = 24
|
|
size = 32
|
|
blockSize = 136
|
|
domain = 0x01
|
|
)
|
|
|
|
func ComputeKeccak(b []bool) []bool {
|
|
if len(b) >= blockSize*8 {
|
|
// TODO absorb
|
|
}
|
|
s := final(b)
|
|
b = squeeze(s)
|
|
|
|
return b
|
|
}
|
|
|
|
func final(b []bool) [25 * 64]bool {
|
|
last := pad(b)
|
|
var s [25 * 64]bool
|
|
s = absorb(s, last)
|
|
return s
|
|
}
|
|
|
|
func pad(b []bool) []bool {
|
|
padded := make([]bool, blockSize*8)
|
|
copy(padded, b)
|
|
copy(padded[len(b):len(b)+8], byteToBits(domain))
|
|
copy(padded[(len(padded)-8):],
|
|
or(padded[(len(padded)-8):], byteToBits(0x80)))
|
|
return padded
|
|
}
|
|
|
|
func absorb(s [25 * 64]bool, block []bool) [25 * 64]bool {
|
|
if len(block) != blockSize*8 {
|
|
panic(fmt.Errorf("absorb: invalid block size: %d, expected: %d",
|
|
len(block), blockSize*8))
|
|
}
|
|
|
|
for i := 0; i < blockSize/8; i++ {
|
|
copy(s[i*64:i*64+64], xor(s[i*64:i*64+64], block[i*64:i*64+64]))
|
|
}
|
|
newS := keccakf(s)
|
|
return newS
|
|
}
|
|
|
|
func squeeze(s [25 * 64]bool) []bool {
|
|
// option1
|
|
// b := make([]bool, 8*8*len(s))
|
|
// for i := 0; i < 25; i++ {
|
|
// copy(b[i*64:i*64+64], s[i*64:i*64+64])
|
|
// }
|
|
// return b[:size*8]
|
|
|
|
// option2
|
|
// out := make([]bool, size*8)
|
|
// for i := 0; i < 25; i++ {
|
|
// for j := 0; j < 64; j++ {
|
|
// if i*64+j < size*8 {
|
|
// out[i*64+j] = s[i*64+j]
|
|
// }
|
|
// }
|
|
// }
|
|
// return out
|
|
|
|
// option3
|
|
return s[:size*8]
|
|
}
|
|
|
|
func keccakfRound(s [25 * 64]bool, r int) [25 * 64]bool {
|
|
s = theta(s)
|
|
s = rhopi(s)
|
|
s = chi(s)
|
|
s = iot(s, r)
|
|
return s
|
|
}
|
|
func keccakf(s [25 * 64]bool) [25 * 64]bool {
|
|
for r := 0; r < rounds; r++ {
|
|
s = keccakfRound(s, r)
|
|
}
|
|
return s
|
|
}
|