|
|
// Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the LICENSE file.
package skein1024
import ( "github.com/aead/skein" "github.com/aead/skein/threefish" )
type hashFunc struct { hashsize int hVal, hValCpy [17]uint64 tweak [3]uint64 block [threefish.BlockSize1024]byte off int hasMsg bool }
func (s *hashFunc) BlockSize() int { return threefish.BlockSize1024 }
func (s *hashFunc) Size() int { return s.hashsize }
func (s *hashFunc) Reset() { for i := range s.block { s.block[i] = 0 } s.off = 0 s.hasMsg = false
s.hVal = s.hValCpy
s.tweak[0] = 0 s.tweak[1] = skein.CfgMessage<<56 | skein.FirstBlock }
func (s *hashFunc) Write(p []byte) (n int, err error) { s.hasMsg = true
n = len(p) var block [16]uint64
dif := threefish.BlockSize1024 - s.off if s.off > 0 && n > dif { s.off += copy(s.block[s.off:], p[:dif]) p = p[dif:] if s.off == threefish.BlockSize1024 && len(p) > 0 { bytesToBlock(&block, s.block[:]) s.update(&block) s.off = 0 } }
if length := len(p); length > threefish.BlockSize1024 { nn := length & (^(threefish.BlockSize1024 - 1)) // length -= (length % BlockSize)
if length == nn { nn -= threefish.BlockSize1024 } for i := 0; i < len(p[:nn]); i += threefish.BlockSize1024 { bytesToBlock(&block, p[i:]) s.update(&block) } p = p[nn:] }
if len(p) > 0 { s.off += copy(s.block[s.off:], p) } return }
func (s *hashFunc) Sum(b []byte) []byte { s0 := *s // copy
if s0.hasMsg { s0.finalizeHash() }
var out [threefish.BlockSize1024]byte var ctr uint64 for i := s0.hashsize; i > 0; i -= threefish.BlockSize1024 { s0.output(&out, ctr) ctr++ b = append(b, out[:]...) }
return b[:s0.hashsize] }
func (s *hashFunc) update(block *[16]uint64) { threefish.IncrementTweak(&(s.tweak), threefish.BlockSize1024)
threefish.UBI1024(block, &(s.hVal), &(s.tweak))
s.tweak[1] &^= skein.FirstBlock }
func (s *hashFunc) output(dst *[threefish.BlockSize1024]byte, counter uint64) { var block [16]uint64 block[0] = counter
hVal := s.hVal var outTweak = [3]uint64{8, skein.CfgOutput<<56 | skein.FirstBlock | skein.FinalBlock, 0}
threefish.UBI1024(&block, &hVal, &outTweak) block[0] ^= counter
blockToBytes(dst[:], &block) }
func (s *hashFunc) initialize(hashsize int, conf *skein.Config) { if hashsize < 1 { panic("skein1024: invalid hashsize for Skein-1024") }
s.hashsize = hashsize
var key, pubKey, keyID, nonce, personal []byte if conf != nil { key = conf.Key pubKey = conf.PublicKey keyID = conf.KeyID nonce = conf.Nonce personal = conf.Personal }
if len(key) > 0 { s.tweak[0] = 0 s.tweak[1] = skein.CfgKey<<56 | skein.FirstBlock s.Write(key) s.finalizeHash() }
var cfg [32]byte schemaId := skein.SchemaID cfg[0] = byte(schemaId) cfg[1] = byte(schemaId >> 8) cfg[2] = byte(schemaId >> 16) cfg[3] = byte(schemaId >> 24) cfg[4] = byte(schemaId >> 32) cfg[5] = byte(schemaId >> 40) cfg[6] = byte(schemaId >> 48) cfg[7] = byte(schemaId >> 56)
bits := uint64(s.hashsize * 8) cfg[8] = byte(bits) cfg[9] = byte(bits >> 8) cfg[10] = byte(bits >> 16) cfg[11] = byte(bits >> 24) cfg[12] = byte(bits >> 32) cfg[13] = byte(bits >> 40) cfg[14] = byte(bits >> 48) cfg[15] = byte(bits >> 56)
s.tweak[0] = 0 s.tweak[1] = skein.CfgConfig<<56 | skein.FirstBlock s.Write(cfg[:]) s.finalizeHash()
if len(personal) > 0 { s.tweak[0] = 0 s.tweak[1] = skein.CfgPersonal<<56 | skein.FirstBlock s.Write(personal) s.finalizeHash() }
if len(pubKey) > 0 { s.tweak[0] = 0 s.tweak[1] = skein.CfgPublicKey<<56 | skein.FirstBlock s.Write(pubKey) s.finalizeHash() }
if len(keyID) > 0 { s.tweak[0] = 0 s.tweak[1] = skein.CfgKeyID<<56 | skein.FirstBlock s.Write(keyID) s.finalizeHash() }
if len(nonce) > 0 { s.tweak[0] = 0 s.tweak[1] = skein.CfgNonce<<56 | skein.FirstBlock s.Write(nonce) s.finalizeHash() }
s.hValCpy = s.hVal
s.Reset() }
func (s *hashFunc) finalizeHash() { threefish.IncrementTweak(&(s.tweak), uint64(s.off)) s.tweak[1] |= skein.FinalBlock // set the last block flag
for i := s.off; i < len(s.block); i++ { s.block[i] = 0 } s.off = 0
var block [16]uint64 bytesToBlock(&block, s.block[:])
threefish.UBI1024(&block, &(s.hVal), &(s.tweak)) }
|