Add 512-bit hash. Use SHA-3 padding.
parent
58e2940852
commit
dd21e91ec1
34
const.go
34
const.go
|
@ -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},
|
||||||
|
}
|
||||||
|
|
|
@ -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[:])
|
||||||
|
|
46
sponge.go
46
sponge.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue