keccak/sponge.go

100 lines
2.0 KiB
Go
Raw Permalink Normal View History

2014-12-31 22:59:00 +00:00
package keccak
import "hash"
2014-12-31 23:19:23 +00:00
const Size = 256 / 8
2014-12-31 22:59:00 +00:00
const BlockSize = 1600/8 - Size*2
2024-10-06 02:22:41 +00:00
func round(a *[25]uint64) { roundGo(a) }
2015-01-01 00:40:56 +00:00
2014-12-31 22:59:00 +00:00
// digest implements hash.Hash
type digest struct {
a [25]uint64 // a[y][x][z]
2015-01-01 07:59:40 +00:00
buf [200]byte
2015-01-01 07:19:05 +00:00
dsbyte byte
2015-01-01 07:59:40 +00:00
len int
size int
2014-12-31 22:59:00 +00:00
}
2015-01-01 07:59:40 +00:00
func New256() hash.Hash { return &digest{size: 256 / 8, dsbyte: 0x06} }
func New512() hash.Hash { return &digest{size: 512 / 8, dsbyte: 0x06} }
2015-01-01 07:19:05 +00:00
2015-01-01 07:59:40 +00:00
func newKeccak256() hash.Hash { return &digest{size: 256 / 8, dsbyte: 0x01} }
func newKeccak512() hash.Hash { return &digest{size: 512 / 8, dsbyte: 0x01} }
2014-12-31 22:59:00 +00:00
2015-01-01 07:19:05 +00:00
func (d *digest) Size() int { return d.size }
func (d *digest) BlockSize() int { return 200 - d.size*2 }
2014-12-31 22:59:00 +00:00
func (d *digest) Reset() {
2015-01-01 07:19:05 +00:00
//fmt.Println("resetting")
d.a = [25]uint64{}
2015-01-01 07:19:05 +00:00
d.buf = [200]byte{}
d.len = 0
2014-12-31 22:59:00 +00:00
}
func (d *digest) Write(b []byte) (int, error) {
written := len(b)
2015-01-01 07:19:05 +00:00
bs := d.BlockSize()
2014-12-31 22:59:00 +00:00
for len(b) > 0 {
2015-01-01 07:19:05 +00:00
n := copy(d.buf[d.len:bs], b)
2014-12-31 22:59:00 +00:00
d.len += n
b = b[n:]
2015-01-01 07:59:40 +00:00
if d.len == bs {
2014-12-31 22:59:00 +00:00
d.flush()
}
}
return written, nil
}
func (d *digest) flush() {
2015-01-01 07:19:05 +00:00
//fmt.Printf("Flushing with %d bytes\n", d.len)
b := d.buf[:d.len]
for i := range d.a {
2015-01-01 11:10:11 +00:00
if len(b) == 0 {
2024-10-05 06:46:16 +00:00
break
2015-01-01 11:10:11 +00:00
}
d.a[i] ^= le64dec(b)
b = b[8:]
2014-12-31 22:59:00 +00:00
}
2014-12-31 23:17:55 +00:00
keccakf(&d.a)
2014-12-31 22:59:00 +00:00
d.len = 0
}
func keccakf(a *[25]uint64) {
2014-12-31 22:59:00 +00:00
for i := 0; i < 24; i++ {
2015-01-01 00:40:56 +00:00
round(a)
a[0] ^= roundc[i]
2014-12-31 22:59:00 +00:00
}
}
func (d *digest) clone() *digest {
d0 := *d
return &d0
}
func (d *digest) Sum(b []byte) []byte {
d = d.clone()
2015-01-01 07:19:05 +00:00
d.buf[d.len] = d.dsbyte
bs := d.BlockSize()
for i := d.len + 1; i < bs; i++ {
2014-12-31 22:59:00 +00:00
d.buf[i] = 0
}
2015-01-01 07:19:05 +00:00
d.buf[bs-1] |= 0x80
d.len = bs
2014-12-31 22:59:00 +00:00
d.flush()
2015-01-01 07:19:05 +00:00
for i := 0; i < d.size/8; i++ {
b = le64enc(b, d.a[i])
2015-01-01 07:19:05 +00:00
}
2014-12-31 22:59:00 +00:00
return b
}
2014-12-31 23:11:40 +00:00
func le64dec(b []byte) uint64 {
2014-12-31 23:19:23 +00:00
return uint64(b[0])<<0 | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
2014-12-31 23:11:40 +00:00
}
2014-12-31 22:59:00 +00:00
func le64enc(b []byte, x uint64) []byte {
return append(b, byte(x), byte(x>>8), byte(x>>16), byte(x>>24), byte(x>>32), byte(x>>40), byte(x>>48), byte(x>>56))
}