You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

352 lines
11 KiB

// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package blake
import (
"fmt"
"gitlab.com/nitya-sattva/go-x11/hash"
)
// HashSize holds the size of a hash in bytes.
const HashSize = int(64)
// BlockSize holds the size of a block in bytes.
const BlockSize = uintptr(128)
////////////////
type digest struct {
ptr uintptr
h [8]uint64
t [2]uint64
b [BlockSize]byte
}
// New returns a new digest compute a BLAKE512 hash.
func New() hash.Digest {
ref := &digest{}
ref.Reset()
return ref
}
////////////////
// Reset resets the digest to its initial state.
func (ref *digest) Reset() {
ref.ptr = 0
copy(ref.h[:], kInit[:])
ref.t[0], ref.t[1] = 0, 0
}
// Sum appends the current hash to dst and returns the result
// as a slice. It does not change the underlying hash state.
func (ref *digest) Sum(dst []byte) []byte {
dgt := *ref
hsh := [64]byte{}
dgt.Close(hsh[:], 0, 0)
return append(dst, hsh[:]...)
}
// Write more data to the running hash, never returns an error.
func (ref *digest) Write(src []byte) (int, error) {
sln := uintptr(len(src))
fln := len(src)
ptr := ref.ptr
if sln < (BlockSize - ptr) {
copy(ref.b[ptr:], src)
ref.ptr += sln
return int(sln), nil
}
for sln > 0 {
cln := BlockSize - ptr
if cln > sln {
cln = sln
}
sln -= cln
copy(ref.b[ptr:], src[:cln])
src = src[cln:]
ptr += cln
if ptr == BlockSize {
h := ref.h[:]
t := ref.t[:]
t[0] = t[0] + 1024
if t[0] < 1024 {
t[1] += 1
}
ptr = 0
var vec [16]uint64
vec[0x0] = h[0]
vec[0x1] = h[1]
vec[0x2] = h[2]
vec[0x3] = h[3]
vec[0x4] = h[4]
vec[0x5] = h[5]
vec[0x6] = h[6]
vec[0x7] = h[7]
vec[0x8] = kSpec[0]
vec[0x9] = kSpec[1]
vec[0xA] = kSpec[2]
vec[0xB] = kSpec[3]
vec[0xC] = t[0] ^ kSpec[4]
vec[0xD] = t[0] ^ kSpec[5]
vec[0xE] = t[1] ^ kSpec[6]
vec[0xF] = t[1] ^ kSpec[7]
var mat [16]uint64
mat[0x0] = decUInt64be(ref.b[0:])
mat[0x1] = decUInt64be(ref.b[8:])
mat[0x2] = decUInt64be(ref.b[16:])
mat[0x3] = decUInt64be(ref.b[24:])
mat[0x4] = decUInt64be(ref.b[32:])
mat[0x5] = decUInt64be(ref.b[40:])
mat[0x6] = decUInt64be(ref.b[48:])
mat[0x7] = decUInt64be(ref.b[56:])
mat[0x8] = decUInt64be(ref.b[64:])
mat[0x9] = decUInt64be(ref.b[72:])
mat[0xA] = decUInt64be(ref.b[80:])
mat[0xB] = decUInt64be(ref.b[88:])
mat[0xC] = decUInt64be(ref.b[96:])
mat[0xD] = decUInt64be(ref.b[104:])
mat[0xE] = decUInt64be(ref.b[112:])
mat[0xF] = decUInt64be(ref.b[120:])
var sig []uint8
for r := uint8(0); r < 16; r++ {
sig = kSigma[r][:]
vec[0x0] = (vec[0x0] + vec[0x4] + (mat[sig[0x0]] ^ kSpec[sig[0x1]]))
vec[0xC] = (((vec[0xC] ^ vec[0x0]) << (32)) | ((vec[0xC] ^ vec[0x0]) >> 32))
vec[0x8] = (vec[0x8] + vec[0xC])
vec[0x4] = (((vec[0x4] ^ vec[0x8]) << (39)) | ((vec[0x4] ^ vec[0x8]) >> 25))
vec[0x0] = (vec[0x0] + vec[0x4] + (mat[sig[0x1]] ^ kSpec[sig[0x0]]))
vec[0xC] = (((vec[0xC] ^ vec[0x0]) << (48)) | ((vec[0xC] ^ vec[0x0]) >> 16))
vec[0x8] = (vec[0x8] + vec[0xC])
vec[0x4] = (((vec[0x4] ^ vec[0x8]) << (53)) | ((vec[0x4] ^ vec[0x8]) >> 11))
vec[0x1] = (vec[0x1] + vec[0x5] + (mat[sig[0x2]] ^ kSpec[sig[0x3]]))
vec[0xD] = (((vec[0xD] ^ vec[0x1]) << (32)) | ((vec[0xD] ^ vec[0x1]) >> 32))
vec[0x9] = (vec[0x9] + vec[0xD])
vec[0x5] = (((vec[0x5] ^ vec[0x9]) << (39)) | ((vec[0x5] ^ vec[0x9]) >> 25))
vec[0x1] = (vec[0x1] + vec[0x5] + (mat[sig[0x3]] ^ kSpec[sig[0x2]]))
vec[0xD] = (((vec[0xD] ^ vec[0x1]) << (48)) | ((vec[0xD] ^ vec[0x1]) >> 16))
vec[0x9] = (vec[0x9] + vec[0xD])
vec[0x5] = (((vec[0x5] ^ vec[0x9]) << (53)) | ((vec[0x5] ^ vec[0x9]) >> 11))
vec[0x2] = (vec[0x2] + vec[0x6] + (mat[sig[0x4]] ^ kSpec[sig[0x5]]))
vec[0xE] = (((vec[0xE] ^ vec[0x2]) << (32)) | ((vec[0xE] ^ vec[0x2]) >> 32))
vec[0xA] = (vec[0xA] + vec[0xE])
vec[0x6] = (((vec[0x6] ^ vec[0xA]) << (39)) | ((vec[0x6] ^ vec[0xA]) >> 25))
vec[0x2] = (vec[0x2] + vec[0x6] + (mat[sig[0x5]] ^ kSpec[sig[0x4]]))
vec[0xE] = (((vec[0xE] ^ vec[0x2]) << (48)) | ((vec[0xE] ^ vec[0x2]) >> 16))
vec[0xA] = (vec[0xA] + vec[0xE])
vec[0x6] = (((vec[0x6] ^ vec[0xA]) << (53)) | ((vec[0x6] ^ vec[0xA]) >> 11))
vec[0x3] = (vec[0x3] + vec[0x7] + (mat[sig[0x6]] ^ kSpec[sig[0x7]]))
vec[0xF] = (((vec[0xF] ^ vec[0x3]) << (32)) | ((vec[0xF] ^ vec[0x3]) >> 32))
vec[0xB] = (vec[0xB] + vec[0xF])
vec[0x7] = (((vec[0x7] ^ vec[0xB]) << (39)) | ((vec[0x7] ^ vec[0xB]) >> 25))
vec[0x3] = (vec[0x3] + vec[0x7] + (mat[sig[0x7]] ^ kSpec[sig[0x6]]))
vec[0xF] = (((vec[0xF] ^ vec[0x3]) << (48)) | ((vec[0xF] ^ vec[0x3]) >> 16))
vec[0xB] = (vec[0xB] + vec[0xF])
vec[0x7] = (((vec[0x7] ^ vec[0xB]) << (53)) | ((vec[0x7] ^ vec[0xB]) >> 11))
vec[0x0] = (vec[0x0] + vec[0x5] + (mat[sig[0x8]] ^ kSpec[sig[0x9]]))
vec[0xF] = (((vec[0xF] ^ vec[0x0]) << (32)) | ((vec[0xF] ^ vec[0x0]) >> 32))
vec[0xA] = (vec[0xA] + vec[0xF])
vec[0x5] = (((vec[0x5] ^ vec[0xA]) << (39)) | ((vec[0x5] ^ vec[0xA]) >> 25))
vec[0x0] = (vec[0x0] + vec[0x5] + (mat[sig[0x9]] ^ kSpec[sig[0x8]]))
vec[0xF] = (((vec[0xF] ^ vec[0x0]) << (48)) | ((vec[0xF] ^ vec[0x0]) >> 16))
vec[0xA] = (vec[0xA] + vec[0xF])
vec[0x5] = (((vec[0x5] ^ vec[0xA]) << (53)) | ((vec[0x5] ^ vec[0xA]) >> 11))
vec[0x1] = (vec[0x1] + vec[0x6] + (mat[sig[0xA]] ^ kSpec[sig[0xB]]))
vec[0xC] = (((vec[0xC] ^ vec[0x1]) << (32)) | ((vec[0xC] ^ vec[0x1]) >> 32))
vec[0xB] = (vec[0xB] + vec[0xC])
vec[0x6] = (((vec[0x6] ^ vec[0xB]) << (39)) | ((vec[0x6] ^ vec[0xB]) >> 25))
vec[0x1] = (vec[0x1] + vec[0x6] + (mat[sig[0xB]] ^ kSpec[sig[0xA]]))
vec[0xC] = (((vec[0xC] ^ vec[0x1]) << (48)) | ((vec[0xC] ^ vec[0x1]) >> 16))
vec[0xB] = (vec[0xB] + vec[0xC])
vec[0x6] = (((vec[0x6] ^ vec[0xB]) << (53)) | ((vec[0x6] ^ vec[0xB]) >> 11))
vec[0x2] = (vec[0x2] + vec[0x7] + (mat[sig[0xC]] ^ kSpec[sig[0xD]]))
vec[0xD] = (((vec[0xD] ^ vec[0x2]) << (32)) | ((vec[0xD] ^ vec[0x2]) >> 32))
vec[0x8] = (vec[0x8] + vec[0xD])
vec[0x7] = (((vec[0x7] ^ vec[0x8]) << (39)) | ((vec[0x7] ^ vec[0x8]) >> 25))
vec[0x2] = (vec[0x2] + vec[0x7] + (mat[sig[0xD]] ^ kSpec[sig[0xC]]))
vec[0xD] = (((vec[0xD] ^ vec[0x2]) << (48)) | ((vec[0xD] ^ vec[0x2]) >> 16))
vec[0x8] = (vec[0x8] + vec[0xD])
vec[0x7] = (((vec[0x7] ^ vec[0x8]) << (53)) | ((vec[0x7] ^ vec[0x8]) >> 11))
vec[0x3] = (vec[0x3] + vec[0x4] + (mat[sig[0xE]] ^ kSpec[sig[0xF]]))
vec[0xE] = (((vec[0xE] ^ vec[0x3]) << (32)) | ((vec[0xE] ^ vec[0x3]) >> 32))
vec[0x9] = (vec[0x9] + vec[0xE])
vec[0x4] = (((vec[0x4] ^ vec[0x9]) << (39)) | ((vec[0x4] ^ vec[0x9]) >> 25))
vec[0x3] = (vec[0x3] + vec[0x4] + (mat[sig[0xF]] ^ kSpec[sig[0xE]]))
vec[0xE] = (((vec[0xE] ^ vec[0x3]) << (48)) | ((vec[0xE] ^ vec[0x3]) >> 16))
vec[0x9] = (vec[0x9] + vec[0xE])
vec[0x4] = (((vec[0x4] ^ vec[0x9]) << (53)) | ((vec[0x4] ^ vec[0x9]) >> 11))
}
h[0] ^= vec[0x0] ^ vec[0x8]
h[1] ^= vec[0x1] ^ vec[0x9]
h[2] ^= vec[0x2] ^ vec[0xA]
h[3] ^= vec[0x3] ^ vec[0xB]
h[4] ^= vec[0x4] ^ vec[0xC]
h[5] ^= vec[0x5] ^ vec[0xD]
h[6] ^= vec[0x6] ^ vec[0xE]
h[7] ^= vec[0x7] ^ vec[0xF]
}
}
ref.ptr = ptr
return fln, nil
}
// Close the digest by writing the last bits and storing the hash
// in dst. This prepares the digest for reuse by calling reset. A call
// to Close with a dst that is smaller then HashSize will return an error.
func (ref *digest) Close(dst []byte, bits uint8, bcnt uint8) error {
if ln := len(dst); HashSize > ln {
return fmt.Errorf("Blake Close: dst min length: %d, got %d", HashSize, ln)
}
ptr := ref.ptr
bln := uint64((ref.ptr << 3) + uintptr(bcnt))
tpl := ref.t[0] + bln
tph := ref.t[1]
var buf [BlockSize]uint8
{
off := uint8(0x80) >> bcnt
buf[ptr] = uint8((bits & -off) | off)
}
if ptr == 0 && bcnt == 0 {
ref.t[0] = uint64(0xFFFFFFFFFFFFFC00)
ref.t[1] = uint64(0xFFFFFFFFFFFFFFFF)
} else if ref.t[0] == 0 {
ref.t[0] = uint64(0xFFFFFFFFFFFFFC00) + bln
ref.t[1] = uint64(ref.t[1] - 1)
} else {
ref.t[0] -= 1024 - bln
}
if bln <= 894 {
buf[111] |= 1
encUInt64be(buf[112:], tph)
encUInt64be(buf[120:], tpl)
ref.Write(buf[ptr:])
} else {
ref.Write(buf[ptr:])
ref.t[0] = uint64(0xFFFFFFFFFFFFFC00)
ref.t[1] = uint64(0xFFFFFFFFFFFFFFFF)
memset(buf[:112], 0)
buf[111] = 1
encUInt64be(buf[112:], tph)
encUInt64be(buf[120:], tpl)
ref.Write(buf[:])
}
for k := uintptr(0); k < 8; k++ {
encUInt64be(dst[(k<<3):], ref.h[k])
}
ref.Reset()
return nil
}
// Size returns the number of bytes Sum will return.
func (*digest) Size() int {
return HashSize
}
// BlockSize returns the block size of the hash.
func (*digest) BlockSize() int {
return int(BlockSize)
}
////////////////
func memset(dst []byte, src byte) {
for i := range dst {
dst[i] = src
}
}
func decUInt64be(src []byte) uint64 {
return (uint64(src[0])<<56 |
uint64(src[1])<<48 |
uint64(src[2])<<40 |
uint64(src[3])<<32 |
uint64(src[4])<<24 |
uint64(src[5])<<16 |
uint64(src[6])<<8 |
uint64(src[7]))
}
func encUInt64be(dst []byte, src uint64) {
dst[0] = uint8(src >> 56)
dst[1] = uint8(src >> 48)
dst[2] = uint8(src >> 40)
dst[3] = uint8(src >> 32)
dst[4] = uint8(src >> 24)
dst[5] = uint8(src >> 16)
dst[6] = uint8(src >> 8)
dst[7] = uint8(src)
}
////////////////
var kInit = [8]uint64{
uint64(0x6A09E667F3BCC908), uint64(0xBB67AE8584CAA73B),
uint64(0x3C6EF372FE94F82B), uint64(0xA54FF53A5F1D36F1),
uint64(0x510E527FADE682D1), uint64(0x9B05688C2B3E6C1F),
uint64(0x1F83D9ABFB41BD6B), uint64(0x5BE0CD19137E2179),
}
var kSpec = [16]uint64{
uint64(0x243F6A8885A308D3), uint64(0x13198A2E03707344),
uint64(0xA4093822299F31D0), uint64(0x082EFA98EC4E6C89),
uint64(0x452821E638D01377), uint64(0xBE5466CF34E90C6C),
uint64(0xC0AC29B7C97C50DD), uint64(0x3F84D5B5B5470917),
uint64(0x9216D5D98979FB1B), uint64(0xD1310BA698DFB5AC),
uint64(0x2FFD72DBD01ADFB7), uint64(0xB8E1AFED6A267E96),
uint64(0xBA7C9045F12C7F99), uint64(0x24A19947B3916CF7),
uint64(0x0801F2E2858EFC16), uint64(0x636920D871574E69),
}
var kSigma = [16][16]uint8{
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
{12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
{13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
{6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
{10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
}