Add 512-bit hash. Use SHA-3 padding.

master
magical 2014-12-31 23:19:05 -08:00
parent 58e2940852
commit dd21e91ec1
3 changed files with 89 additions and 26 deletions

View File

@ -1,4 +1,34 @@
package keccak 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 roundc = [24]uint64{
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}} 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},
}

View File

@ -5,24 +5,47 @@ import (
"testing" "testing"
) )
var vector = []byte{ var vector256 = []byte{
0xc5, 0xd2, 0x46, 0x01, 0x86, 0xf7, 0x23, 0x3c, 0xc5, 0xd2, 0x46, 0x01, 0x86, 0xf7, 0x23, 0x3c,
0x92, 0x7e, 0x7d, 0xb2, 0xdc, 0xc7, 0x03, 0xc0, 0x92, 0x7e, 0x7d, 0xb2, 0xdc, 0xc7, 0x03, 0xc0,
0xe5, 0x00, 0xb6, 0x53, 0xca, 0x82, 0x27, 0x3b, 0xe5, 0x00, 0xb6, 0x53, 0xca, 0x82, 0x27, 0x3b,
0x7b, 0xfa, 0xd8, 0x04, 0x5d, 0x85, 0xa4, 0x70, 0x7b, 0xfa, 0xd8, 0x04, 0x5d, 0x85, 0xa4, 0x70,
} }
func TestKeccak(t *testing.T) { var vector512 = []byte{
h := New() 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) sum := h.Sum(nil)
if !reflect.DeepEqual(sum, vector) { if !reflect.DeepEqual(sum, vector256) {
t.Errorf("\"\": want % x, got % x", vector, sum) 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) { func Benchmark256(b *testing.B) {
var tmp [Size]byte 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) b.SetBytes(BlockSize)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
h.Sum(tmp[:]) h.Sum(tmp[:])

View File

@ -11,28 +11,36 @@ var round = roundGo
// digest implements hash.Hash // digest implements hash.Hash
type digest struct { type digest struct {
a [5][5]uint64 // a[y][x][z] a [5][5]uint64 // a[y][x][z]
buf [BlockSize]byte buf [200]byte
dsbyte byte
len int len int
size int
} }
func New() hash.Hash { func New256() hash.Hash { return &digest{size: 256/8, dsbyte: 0x06} }
return &digest{} func New512() hash.Hash { return &digest{size: 512/8, dsbyte: 0x06} }
}
func (d *digest) Size() int { return Size } func newKeccak256() hash.Hash { return &digest{size: 256/8, dsbyte: 0x01} }
func (d *digest) BlockSize() int { return BlockSize } 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() { 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) { func (d *digest) Write(b []byte) (int, error) {
written := len(b) written := len(b)
bs := d.BlockSize()
for len(b) > 0 { for len(b) > 0 {
n := copy(d.buf[d.len:], b) n := copy(d.buf[d.len:bs], b)
d.len += n d.len += n
b = b[n:] b = b[n:]
if d.len == BlockSize { if d.len == bs {
d.flush() d.flush()
} }
} }
@ -40,7 +48,8 @@ func (d *digest) Write(b []byte) (int, error) {
} }
func (d *digest) flush() { func (d *digest) flush() {
b := d.buf[:] //fmt.Printf("Flushing with %d bytes\n", d.len)
b := d.buf[:d.len]
loop: loop:
for y := range d.a { for y := range d.a {
for x := range d.a[0] { for x := range d.a[0] {
@ -58,23 +67,24 @@ loop:
func keccakf(a *[5][5]uint64) { func keccakf(a *[5][5]uint64) {
for i := 0; i < 24; i++ { for i := 0; i < 24; i++ {
round(a) round(a)
a[0][0] ^= RC[i] a[0][0] ^= roundc[i]
} }
} }
func (d0 *digest) Sum(b []byte) []byte { func (d0 *digest) Sum(b []byte) []byte {
d := *d0 d := *d0
d.buf[d.len] = 0x01 d.buf[d.len] = d.dsbyte
for i := d.len + 1; i < BlockSize; i++ { bs := d.BlockSize()
for i := d.len + 1; i < bs; i++ {
d.buf[i] = 0 d.buf[i] = 0
} }
d.buf[BlockSize-1] |= 0x80 d.buf[bs-1] |= 0x80
d.len = bs
d.flush() d.flush()
b = le64enc(b, d.a[0][0]) for i := 0; i < d.size/8; i++ {
b = le64enc(b, d.a[0][1]) b = le64enc(b, d.a[i/5][i%5])
b = le64enc(b, d.a[0][2]) }
b = le64enc(b, d.a[0][3])
return b return b
} }