// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package cubed
|
|
|
|
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(32)
|
|
|
|
////////////////
|
|
|
|
type digest struct {
|
|
ptr uintptr
|
|
|
|
h [32]uint32
|
|
|
|
b [BlockSize]byte
|
|
}
|
|
|
|
// New returns a new digest compute a CUBEHASH512 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[:])
|
|
}
|
|
|
|
// 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[:sln])
|
|
ref.ptr += sln
|
|
return int(sln), nil
|
|
}
|
|
|
|
st := ref.h[:]
|
|
buf := ref.b[:]
|
|
for sln > 0 {
|
|
cln := BlockSize - ptr
|
|
|
|
if cln > sln {
|
|
cln = sln
|
|
}
|
|
sln -= cln
|
|
|
|
copy(buf[ptr:], src[:cln])
|
|
src = src[cln:]
|
|
ptr += cln
|
|
|
|
if ptr == BlockSize {
|
|
st[0x00] ^= decUInt32le(buf[0:])
|
|
st[0x01] ^= decUInt32le(buf[4:])
|
|
st[0x02] ^= decUInt32le(buf[8:])
|
|
st[0x03] ^= decUInt32le(buf[12:])
|
|
st[0x04] ^= decUInt32le(buf[16:])
|
|
st[0x05] ^= decUInt32le(buf[20:])
|
|
st[0x06] ^= decUInt32le(buf[24:])
|
|
st[0x07] ^= decUInt32le(buf[28:])
|
|
|
|
runRounds(st)
|
|
runRounds(st)
|
|
|
|
runRounds(st)
|
|
runRounds(st)
|
|
|
|
runRounds(st)
|
|
runRounds(st)
|
|
|
|
runRounds(st)
|
|
runRounds(st)
|
|
|
|
ptr = 0
|
|
}
|
|
}
|
|
|
|
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("Cubed Close: dst min length: %d, got %d", HashSize, ln)
|
|
}
|
|
st := ref.h[:]
|
|
|
|
{
|
|
buf := ref.b[:]
|
|
ptr := ref.ptr + 1
|
|
|
|
z := uint8(0x80) >> bcnt
|
|
buf[ref.ptr] = uint8((bits & -z) | z)
|
|
|
|
memset(buf[ptr:], 0)
|
|
st[0x00] ^= decUInt32le(buf[0:])
|
|
st[0x01] ^= decUInt32le(buf[4:])
|
|
st[0x02] ^= decUInt32le(buf[8:])
|
|
st[0x03] ^= decUInt32le(buf[12:])
|
|
st[0x04] ^= decUInt32le(buf[16:])
|
|
st[0x05] ^= decUInt32le(buf[20:])
|
|
st[0x06] ^= decUInt32le(buf[24:])
|
|
st[0x07] ^= decUInt32le(buf[28:])
|
|
}
|
|
|
|
for i := uint8(0); i < 11; i++ {
|
|
runRounds(st)
|
|
runRounds(st)
|
|
|
|
runRounds(st)
|
|
runRounds(st)
|
|
|
|
runRounds(st)
|
|
runRounds(st)
|
|
|
|
runRounds(st)
|
|
runRounds(st)
|
|
|
|
if i == 0 {
|
|
st[0x1F] ^= uint32(1)
|
|
}
|
|
}
|
|
|
|
for i := uint8(0); i < 16; i++ {
|
|
encUInt32le(dst[(i<<2):], ref.h[i])
|
|
}
|
|
|
|
ref.Reset()
|
|
return nil
|
|
}
|
|
|
|
// Size returns the number of bytes required to store the hash.
|
|
func (*digest) Size() int {
|
|
return int(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 decUInt32le(src []byte) uint32 {
|
|
return (uint32(src[0]) |
|
|
uint32(src[1])<<8 |
|
|
uint32(src[2])<<16 |
|
|
uint32(src[3])<<24)
|
|
}
|
|
|
|
func encUInt32le(dst []byte, src uint32) {
|
|
dst[0] = uint8(src)
|
|
dst[1] = uint8(src >> 8)
|
|
dst[2] = uint8(src >> 16)
|
|
dst[3] = uint8(src >> 24)
|
|
}
|
|
|
|
func runRounds(st []uint32) {
|
|
st[0x10] = (st[0x00] + st[0x10])
|
|
st[0x00] = (st[0x00] << 7) | (st[0x00] >> (32 - 7))
|
|
st[0x11] = (st[0x01] + st[0x11])
|
|
st[0x01] = (st[0x01] << 7) | (st[0x01] >> (32 - 7))
|
|
st[0x12] = (st[0x02] + st[0x12])
|
|
st[0x02] = (st[0x02] << 7) | (st[0x02] >> (32 - 7))
|
|
st[0x13] = (st[0x03] + st[0x13])
|
|
st[0x03] = (st[0x03] << 7) | (st[0x03] >> (32 - 7))
|
|
st[0x14] = (st[0x04] + st[0x14])
|
|
st[0x04] = (st[0x04] << 7) | (st[0x04] >> (32 - 7))
|
|
st[0x15] = (st[0x05] + st[0x15])
|
|
st[0x05] = (st[0x05] << 7) | (st[0x05] >> (32 - 7))
|
|
st[0x16] = (st[0x06] + st[0x16])
|
|
st[0x06] = (st[0x06] << 7) | (st[0x06] >> (32 - 7))
|
|
st[0x17] = (st[0x07] + st[0x17])
|
|
st[0x07] = (st[0x07] << 7) | (st[0x07] >> (32 - 7))
|
|
st[0x18] = (st[0x08] + st[0x18])
|
|
st[0x08] = (st[0x08] << 7) | (st[0x08] >> (32 - 7))
|
|
st[0x19] = (st[0x09] + st[0x19])
|
|
st[0x09] = (st[0x09] << 7) | (st[0x09] >> (32 - 7))
|
|
st[0x1A] = (st[0x0A] + st[0x1A])
|
|
st[0x0A] = (st[0x0A] << 7) | (st[0x0A] >> (32 - 7))
|
|
st[0x1B] = (st[0x0B] + st[0x1B])
|
|
st[0x0B] = (st[0x0B] << 7) | (st[0x0B] >> (32 - 7))
|
|
st[0x1C] = (st[0x0C] + st[0x1C])
|
|
st[0x0C] = (st[0x0C] << 7) | (st[0x0C] >> (32 - 7))
|
|
st[0x1D] = (st[0x0D] + st[0x1D])
|
|
st[0x0D] = (st[0x0D] << 7) | (st[0x0D] >> (32 - 7))
|
|
st[0x1E] = (st[0x0E] + st[0x1E])
|
|
st[0x0E] = (st[0x0E] << 7) | (st[0x0E] >> (32 - 7))
|
|
st[0x1F] = (st[0x0F] + st[0x1F])
|
|
st[0x0F] = (st[0x0F] << 7) | (st[0x0F] >> (32 - 7))
|
|
st[0x08] ^= st[0x10]
|
|
st[0x09] ^= st[0x11]
|
|
st[0x0A] ^= st[0x12]
|
|
st[0x0B] ^= st[0x13]
|
|
st[0x0C] ^= st[0x14]
|
|
st[0x0D] ^= st[0x15]
|
|
st[0x0E] ^= st[0x16]
|
|
st[0x0F] ^= st[0x17]
|
|
st[0x00] ^= st[0x18]
|
|
st[0x01] ^= st[0x19]
|
|
st[0x02] ^= st[0x1A]
|
|
st[0x03] ^= st[0x1B]
|
|
st[0x04] ^= st[0x1C]
|
|
st[0x05] ^= st[0x1D]
|
|
st[0x06] ^= st[0x1E]
|
|
st[0x07] ^= st[0x1F]
|
|
st[0x12] = (st[0x08] + st[0x12])
|
|
st[0x08] = (st[0x08] << 11) | (st[0x08] >> (32 - 11))
|
|
st[0x13] = (st[0x09] + st[0x13])
|
|
st[0x09] = (st[0x09] << 11) | (st[0x09] >> (32 - 11))
|
|
st[0x10] = (st[0x0A] + st[0x10])
|
|
st[0x0A] = (st[0x0A] << 11) | (st[0x0A] >> (32 - 11))
|
|
st[0x11] = (st[0x0B] + st[0x11])
|
|
st[0x0B] = (st[0x0B] << 11) | (st[0x0B] >> (32 - 11))
|
|
st[0x16] = (st[0x0C] + st[0x16])
|
|
st[0x0C] = (st[0x0C] << 11) | (st[0x0C] >> (32 - 11))
|
|
st[0x17] = (st[0x0D] + st[0x17])
|
|
st[0x0D] = (st[0x0D] << 11) | (st[0x0D] >> (32 - 11))
|
|
st[0x14] = (st[0x0E] + st[0x14])
|
|
st[0x0E] = (st[0x0E] << 11) | (st[0x0E] >> (32 - 11))
|
|
st[0x15] = (st[0x0F] + st[0x15])
|
|
st[0x0F] = (st[0x0F] << 11) | (st[0x0F] >> (32 - 11))
|
|
st[0x1A] = (st[0x00] + st[0x1A])
|
|
st[0x00] = (st[0x00] << 11) | (st[0x00] >> (32 - 11))
|
|
st[0x1B] = (st[0x01] + st[0x1B])
|
|
st[0x01] = (st[0x01] << 11) | (st[0x01] >> (32 - 11))
|
|
st[0x18] = (st[0x02] + st[0x18])
|
|
st[0x02] = (st[0x02] << 11) | (st[0x02] >> (32 - 11))
|
|
st[0x19] = (st[0x03] + st[0x19])
|
|
st[0x03] = (st[0x03] << 11) | (st[0x03] >> (32 - 11))
|
|
st[0x1E] = (st[0x04] + st[0x1E])
|
|
st[0x04] = (st[0x04] << 11) | (st[0x04] >> (32 - 11))
|
|
st[0x1F] = (st[0x05] + st[0x1F])
|
|
st[0x05] = (st[0x05] << 11) | (st[0x05] >> (32 - 11))
|
|
st[0x1C] = (st[0x06] + st[0x1C])
|
|
st[0x06] = (st[0x06] << 11) | (st[0x06] >> (32 - 11))
|
|
st[0x1D] = (st[0x07] + st[0x1D])
|
|
st[0x07] = (st[0x07] << 11) | (st[0x07] >> (32 - 11))
|
|
st[0x0C] ^= st[0x12]
|
|
st[0x0D] ^= st[0x13]
|
|
st[0x0E] ^= st[0x10]
|
|
st[0x0F] ^= st[0x11]
|
|
st[0x08] ^= st[0x16]
|
|
st[0x09] ^= st[0x17]
|
|
st[0x0A] ^= st[0x14]
|
|
st[0x0B] ^= st[0x15]
|
|
st[0x04] ^= st[0x1A]
|
|
st[0x05] ^= st[0x1B]
|
|
st[0x06] ^= st[0x18]
|
|
st[0x07] ^= st[0x19]
|
|
st[0x00] ^= st[0x1E]
|
|
st[0x01] ^= st[0x1F]
|
|
st[0x02] ^= st[0x1C]
|
|
st[0x03] ^= st[0x1D]
|
|
|
|
st[0x13] = (st[0x0C] + st[0x13])
|
|
st[0x0C] = (st[0x0C] << 7) | (st[0x0C] >> (32 - 7))
|
|
st[0x12] = (st[0x0D] + st[0x12])
|
|
st[0x0D] = (st[0x0D] << 7) | (st[0x0D] >> (32 - 7))
|
|
st[0x11] = (st[0x0E] + st[0x11])
|
|
st[0x0E] = (st[0x0E] << 7) | (st[0x0E] >> (32 - 7))
|
|
st[0x10] = (st[0x0F] + st[0x10])
|
|
st[0x0F] = (st[0x0F] << 7) | (st[0x0F] >> (32 - 7))
|
|
st[0x17] = (st[0x08] + st[0x17])
|
|
st[0x08] = (st[0x08] << 7) | (st[0x08] >> (32 - 7))
|
|
st[0x16] = (st[0x09] + st[0x16])
|
|
st[0x09] = (st[0x09] << 7) | (st[0x09] >> (32 - 7))
|
|
st[0x15] = (st[0x0A] + st[0x15])
|
|
st[0x0A] = (st[0x0A] << 7) | (st[0x0A] >> (32 - 7))
|
|
st[0x14] = (st[0x0B] + st[0x14])
|
|
st[0x0B] = (st[0x0B] << 7) | (st[0x0B] >> (32 - 7))
|
|
st[0x1B] = (st[0x04] + st[0x1B])
|
|
st[0x04] = (st[0x04] << 7) | (st[0x04] >> (32 - 7))
|
|
st[0x1A] = (st[0x05] + st[0x1A])
|
|
st[0x05] = (st[0x05] << 7) | (st[0x05] >> (32 - 7))
|
|
st[0x19] = (st[0x06] + st[0x19])
|
|
st[0x06] = (st[0x06] << 7) | (st[0x06] >> (32 - 7))
|
|
st[0x18] = (st[0x07] + st[0x18])
|
|
st[0x07] = (st[0x07] << 7) | (st[0x07] >> (32 - 7))
|
|
st[0x1F] = (st[0x00] + st[0x1F])
|
|
st[0x00] = (st[0x00] << 7) | (st[0x00] >> (32 - 7))
|
|
st[0x1E] = (st[0x01] + st[0x1E])
|
|
st[0x01] = (st[0x01] << 7) | (st[0x01] >> (32 - 7))
|
|
st[0x1D] = (st[0x02] + st[0x1D])
|
|
st[0x02] = (st[0x02] << 7) | (st[0x02] >> (32 - 7))
|
|
st[0x1C] = (st[0x03] + st[0x1C])
|
|
st[0x03] = (st[0x03] << 7) | (st[0x03] >> (32 - 7))
|
|
st[0x04] ^= st[0x13]
|
|
st[0x05] ^= st[0x12]
|
|
st[0x06] ^= st[0x11]
|
|
st[0x07] ^= st[0x10]
|
|
st[0x00] ^= st[0x17]
|
|
st[0x01] ^= st[0x16]
|
|
st[0x02] ^= st[0x15]
|
|
st[0x03] ^= st[0x14]
|
|
st[0x0C] ^= st[0x1B]
|
|
st[0x0D] ^= st[0x1A]
|
|
st[0x0E] ^= st[0x19]
|
|
st[0x0F] ^= st[0x18]
|
|
st[0x08] ^= st[0x1F]
|
|
st[0x09] ^= st[0x1E]
|
|
st[0x0A] ^= st[0x1D]
|
|
st[0x0B] ^= st[0x1C]
|
|
st[0x11] = (st[0x04] + st[0x11])
|
|
st[0x04] = (st[0x04] << 11) | (st[0x04] >> (32 - 11))
|
|
st[0x10] = (st[0x05] + st[0x10])
|
|
st[0x05] = (st[0x05] << 11) | (st[0x05] >> (32 - 11))
|
|
st[0x13] = (st[0x06] + st[0x13])
|
|
st[0x06] = (st[0x06] << 11) | (st[0x06] >> (32 - 11))
|
|
st[0x12] = (st[0x07] + st[0x12])
|
|
st[0x07] = (st[0x07] << 11) | (st[0x07] >> (32 - 11))
|
|
st[0x15] = (st[0x00] + st[0x15])
|
|
st[0x00] = (st[0x00] << 11) | (st[0x00] >> (32 - 11))
|
|
st[0x14] = (st[0x01] + st[0x14])
|
|
st[0x01] = (st[0x01] << 11) | (st[0x01] >> (32 - 11))
|
|
st[0x17] = (st[0x02] + st[0x17])
|
|
st[0x02] = (st[0x02] << 11) | (st[0x02] >> (32 - 11))
|
|
st[0x16] = (st[0x03] + st[0x16])
|
|
st[0x03] = (st[0x03] << 11) | (st[0x03] >> (32 - 11))
|
|
st[0x19] = (st[0x0C] + st[0x19])
|
|
st[0x0C] = (st[0x0C] << 11) | (st[0x0C] >> (32 - 11))
|
|
st[0x18] = (st[0x0D] + st[0x18])
|
|
st[0x0D] = (st[0x0D] << 11) | (st[0x0D] >> (32 - 11))
|
|
st[0x1B] = (st[0x0E] + st[0x1B])
|
|
st[0x0E] = (st[0x0E] << 11) | (st[0x0E] >> (32 - 11))
|
|
st[0x1A] = (st[0x0F] + st[0x1A])
|
|
st[0x0F] = (st[0x0F] << 11) | (st[0x0F] >> (32 - 11))
|
|
st[0x1D] = (st[0x08] + st[0x1D])
|
|
st[0x08] = (st[0x08] << 11) | (st[0x08] >> (32 - 11))
|
|
st[0x1C] = (st[0x09] + st[0x1C])
|
|
st[0x09] = (st[0x09] << 11) | (st[0x09] >> (32 - 11))
|
|
st[0x1F] = (st[0x0A] + st[0x1F])
|
|
st[0x0A] = (st[0x0A] << 11) | (st[0x0A] >> (32 - 11))
|
|
st[0x1E] = (st[0x0B] + st[0x1E])
|
|
st[0x0B] = (st[0x0B] << 11) | (st[0x0B] >> (32 - 11))
|
|
st[0x00] ^= st[0x11]
|
|
st[0x01] ^= st[0x10]
|
|
st[0x02] ^= st[0x13]
|
|
st[0x03] ^= st[0x12]
|
|
st[0x04] ^= st[0x15]
|
|
st[0x05] ^= st[0x14]
|
|
st[0x06] ^= st[0x17]
|
|
st[0x07] ^= st[0x16]
|
|
st[0x08] ^= st[0x19]
|
|
st[0x09] ^= st[0x18]
|
|
st[0x0A] ^= st[0x1B]
|
|
st[0x0B] ^= st[0x1A]
|
|
st[0x0C] ^= st[0x1D]
|
|
st[0x0D] ^= st[0x1C]
|
|
st[0x0E] ^= st[0x1F]
|
|
st[0x0F] ^= st[0x1E]
|
|
}
|
|
|
|
////////////////
|
|
|
|
var kInit = [32]uint32{
|
|
uint32(0x2AEA2A61), uint32(0x50F494D4), uint32(0x2D538B8B),
|
|
uint32(0x4167D83E), uint32(0x3FEE2313), uint32(0xC701CF8C),
|
|
uint32(0xCC39968E), uint32(0x50AC5695), uint32(0x4D42C787),
|
|
uint32(0xA647A8B3), uint32(0x97CF0BEF), uint32(0x825B4537),
|
|
uint32(0xEEF864D2), uint32(0xF22090C4), uint32(0xD0E5CD33),
|
|
uint32(0xA23911AE), uint32(0xFCD398D9), uint32(0x148FE485),
|
|
uint32(0x1B017BEF), uint32(0xB6444532), uint32(0x6A536159),
|
|
uint32(0x2FF5781C), uint32(0x91FA7934), uint32(0x0DBADEA9),
|
|
uint32(0xD65C8A2B), uint32(0xA5A70E75), uint32(0xB1C62456),
|
|
uint32(0xBC796576), uint32(0x1921C8F7), uint32(0xE7989AF1),
|
|
uint32(0x7795D246), uint32(0xD43E3B44),
|
|
}
|