diff --git a/const.go b/const.go index 836ad7d..45b1bfd 100644 --- a/const.go +++ b/const.go @@ -1,4 +1,34 @@ package keccak -var RC = [24]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 rotc = [5][5]uint{[5]uint{0x0, 0x1, 0x3e, 0x1c, 0x1b}, [5]uint{0x24, 0x2c, 0x6, 0x37, 0x14}, [5]uint{0x3, 0xa, 0x2b, 0x19, 0x27}, [5]uint{0x29, 0x2d, 0xf, 0x15, 0x8}, [5]uint{0x12, 0x2, 0x3d, 0x38, 0xe}} +var roundc = [24]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 rotc = [5][5]uint{[5]uint{0x0, 0x1, 0x3e, 0x1c, 0x1b}, + [5]uint{0x24, 0x2c, 0x6, 0x37, 0x14}, + [5]uint{0x3, 0xa, 0x2b, 0x19, 0x27}, + [5]uint{0x29, 0x2d, 0xf, 0x15, 0x8}, + [5]uint{0x12, 0x2, 0x3d, 0x38, 0xe}, +} diff --git a/keccak_test.go b/keccak_test.go index a582e6d..cfbb022 100644 --- a/keccak_test.go +++ b/keccak_test.go @@ -5,24 +5,47 @@ import ( "testing" ) -var vector = []byte{ +var vector256 = []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, } -func TestKeccak(t *testing.T) { - h := New() +var vector512 = []byte{ + 0x0e, 0xab, 0x42, 0xde, 0x4c, 0x3c, 0xeb, 0x92, + 0x35, 0xfc, 0x91, 0xac, 0xff, 0xe7, 0x46, 0xb2, + 0x9c, 0x29, 0xa8, 0xc3, 0x66, 0xb7, 0xc6, 0x0e, + 0x4e, 0x67, 0xc4, 0x66, 0xf3, 0x6a, 0x43, 0x04, + 0xc0, 0x0f, 0xa9, 0xca, 0xf9, 0xd8, 0x79, 0x76, + 0xba, 0x46, 0x9b, 0xcb, 0xe0, 0x67, 0x13, 0xb4, + 0x35, 0xf0, 0x91, 0xef, 0x27, 0x69, 0xfb, 0x16, + 0x0c, 0xda, 0xb3, 0x3d, 0x36, 0x70, 0x68, 0x0e, +} + +func TestKeccak256(t *testing.T) { + h := newKeccak256() sum := h.Sum(nil) - if !reflect.DeepEqual(sum, vector) { - t.Errorf("\"\": want % x, got % x", vector, sum) + if !reflect.DeepEqual(sum, vector256) { + t.Errorf("\"\": want % x, got % x", vector256, sum) + } +} + +func TestKeccak512(t *testing.T) { + h := newKeccak512() + sum := h.Sum(nil) + if !reflect.DeepEqual(sum, vector512) { + t.Errorf("\"\": want % x, got % x", vector512, sum) } } func Benchmark256(b *testing.B) { var tmp [Size]byte - h := New() + h := New256() + var msg [BlockSize]byte + if len(msg) != h.BlockSize() { + b.Fatalf("message length does not match block size: want %d got %d", h.BlockSize(), len(msg)) + } b.SetBytes(BlockSize) for i := 0; i < b.N; i++ { h.Sum(tmp[:]) diff --git a/sponge.go b/sponge.go index 1d659e7..d43914e 100644 --- a/sponge.go +++ b/sponge.go @@ -11,28 +11,36 @@ var round = roundGo // digest implements hash.Hash type digest struct { a [5][5]uint64 // a[y][x][z] - buf [BlockSize]byte + buf [200]byte + dsbyte byte len int + size int } -func New() hash.Hash { - return &digest{} -} +func New256() hash.Hash { return &digest{size: 256/8, dsbyte: 0x06} } +func New512() hash.Hash { return &digest{size: 512/8, dsbyte: 0x06} } -func (d *digest) Size() int { return Size } -func (d *digest) BlockSize() int { return BlockSize } +func newKeccak256() hash.Hash { return &digest{size: 256/8, dsbyte: 0x01} } +func newKeccak512() hash.Hash { return &digest{size: 512/8, dsbyte: 0x01} } + +func (d *digest) Size() int { return d.size } +func (d *digest) BlockSize() int { return 200 - d.size*2 } func (d *digest) Reset() { - *d = digest{} + //fmt.Println("resetting") + d.a = [5][5]uint64{} + d.buf = [200]byte{} + d.len = 0 } func (d *digest) Write(b []byte) (int, error) { written := len(b) + bs := d.BlockSize() for len(b) > 0 { - n := copy(d.buf[d.len:], b) + n := copy(d.buf[d.len:bs], b) d.len += n b = b[n:] - if d.len == BlockSize { + if d.len == bs { d.flush() } } @@ -40,7 +48,8 @@ func (d *digest) Write(b []byte) (int, error) { } func (d *digest) flush() { - b := d.buf[:] + //fmt.Printf("Flushing with %d bytes\n", d.len) + b := d.buf[:d.len] loop: for y := range d.a { for x := range d.a[0] { @@ -58,23 +67,24 @@ loop: func keccakf(a *[5][5]uint64) { for i := 0; i < 24; i++ { round(a) - a[0][0] ^= RC[i] + a[0][0] ^= roundc[i] } } func (d0 *digest) Sum(b []byte) []byte { d := *d0 - d.buf[d.len] = 0x01 - for i := d.len + 1; i < BlockSize; i++ { + d.buf[d.len] = d.dsbyte + bs := d.BlockSize() + for i := d.len + 1; i < bs; i++ { d.buf[i] = 0 } - d.buf[BlockSize-1] |= 0x80 + d.buf[bs-1] |= 0x80 + d.len = bs d.flush() - b = le64enc(b, d.a[0][0]) - b = le64enc(b, d.a[0][1]) - b = le64enc(b, d.a[0][2]) - b = le64enc(b, d.a[0][3]) + for i := 0; i < d.size/8; i++ { + b = le64enc(b, d.a[i/5][i%5]) + } return b }