unroll word<->byte conversions
This commit is contained in:
parent
f87940e245
commit
20804e899d
63
blake3.go
63
blake3.go
|
@ -33,16 +33,42 @@ var iv = [8]uint32{
|
||||||
|
|
||||||
// helper functions for converting between bytes and BLAKE3 "words"
|
// helper functions for converting between bytes and BLAKE3 "words"
|
||||||
|
|
||||||
func bytesToWords(bytes []byte, words []uint32) {
|
func bytesToWords(bytes [64]byte, words *[16]uint32) {
|
||||||
for i := range words {
|
words[0] = binary.LittleEndian.Uint32(bytes[0:])
|
||||||
words[i] = binary.LittleEndian.Uint32(bytes[i*4:])
|
words[1] = binary.LittleEndian.Uint32(bytes[4:])
|
||||||
}
|
words[2] = binary.LittleEndian.Uint32(bytes[8:])
|
||||||
|
words[3] = binary.LittleEndian.Uint32(bytes[12:])
|
||||||
|
words[4] = binary.LittleEndian.Uint32(bytes[16:])
|
||||||
|
words[5] = binary.LittleEndian.Uint32(bytes[20:])
|
||||||
|
words[6] = binary.LittleEndian.Uint32(bytes[24:])
|
||||||
|
words[7] = binary.LittleEndian.Uint32(bytes[28:])
|
||||||
|
words[8] = binary.LittleEndian.Uint32(bytes[32:])
|
||||||
|
words[9] = binary.LittleEndian.Uint32(bytes[36:])
|
||||||
|
words[10] = binary.LittleEndian.Uint32(bytes[40:])
|
||||||
|
words[11] = binary.LittleEndian.Uint32(bytes[44:])
|
||||||
|
words[12] = binary.LittleEndian.Uint32(bytes[48:])
|
||||||
|
words[13] = binary.LittleEndian.Uint32(bytes[52:])
|
||||||
|
words[14] = binary.LittleEndian.Uint32(bytes[56:])
|
||||||
|
words[15] = binary.LittleEndian.Uint32(bytes[60:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func wordsToBytes(words []uint32, bytes []byte) {
|
func wordsToBytes(words [16]uint32, block *[64]byte) {
|
||||||
for i, w := range words {
|
binary.LittleEndian.PutUint32(block[0:], words[0])
|
||||||
binary.LittleEndian.PutUint32(bytes[i*4:], w)
|
binary.LittleEndian.PutUint32(block[4:], words[1])
|
||||||
}
|
binary.LittleEndian.PutUint32(block[8:], words[2])
|
||||||
|
binary.LittleEndian.PutUint32(block[12:], words[3])
|
||||||
|
binary.LittleEndian.PutUint32(block[16:], words[4])
|
||||||
|
binary.LittleEndian.PutUint32(block[20:], words[5])
|
||||||
|
binary.LittleEndian.PutUint32(block[24:], words[6])
|
||||||
|
binary.LittleEndian.PutUint32(block[28:], words[7])
|
||||||
|
binary.LittleEndian.PutUint32(block[32:], words[8])
|
||||||
|
binary.LittleEndian.PutUint32(block[36:], words[9])
|
||||||
|
binary.LittleEndian.PutUint32(block[40:], words[10])
|
||||||
|
binary.LittleEndian.PutUint32(block[44:], words[11])
|
||||||
|
binary.LittleEndian.PutUint32(block[48:], words[12])
|
||||||
|
binary.LittleEndian.PutUint32(block[52:], words[13])
|
||||||
|
binary.LittleEndian.PutUint32(block[56:], words[14])
|
||||||
|
binary.LittleEndian.PutUint32(block[60:], words[15])
|
||||||
}
|
}
|
||||||
|
|
||||||
func g(a, b, c, d, mx, my uint32) (uint32, uint32, uint32, uint32) {
|
func g(a, b, c, d, mx, my uint32) (uint32, uint32, uint32, uint32) {
|
||||||
|
@ -199,7 +225,7 @@ func (cs *chunkState) update(input []byte) {
|
||||||
// input is coming, so this compression is not flagChunkEnd.
|
// input is coming, so this compression is not flagChunkEnd.
|
||||||
if cs.blockLen == blockSize {
|
if cs.blockLen == blockSize {
|
||||||
// copy the chunk block (bytes) into the node block and chain it.
|
// copy the chunk block (bytes) into the node block and chain it.
|
||||||
bytesToWords(cs.block[:], cs.n.block[:])
|
bytesToWords(cs.block, &cs.n.block)
|
||||||
cs.n.cv = cs.n.chainingValue()
|
cs.n.cv = cs.n.chainingValue()
|
||||||
// clear the start flag for all but the first block
|
// clear the start flag for all but the first block
|
||||||
cs.n.flags &^= flagChunkStart
|
cs.n.flags &^= flagChunkStart
|
||||||
|
@ -227,7 +253,7 @@ func (cs *chunkState) node() node {
|
||||||
n := cs.n
|
n := cs.n
|
||||||
// pad the remaining space in the block with zeros
|
// pad the remaining space in the block with zeros
|
||||||
clear(cs.block[cs.blockLen:])
|
clear(cs.block[cs.blockLen:])
|
||||||
bytesToWords(cs.block[:], n.block[:])
|
bytesToWords(cs.block, &n.block)
|
||||||
n.blockLen = uint32(cs.blockLen)
|
n.blockLen = uint32(cs.blockLen)
|
||||||
n.flags |= flagChunkEnd
|
n.flags |= flagChunkEnd
|
||||||
return n
|
return n
|
||||||
|
@ -374,7 +400,9 @@ func New(size int, key []byte) *Hasher {
|
||||||
return newHasher(iv, 0, size)
|
return newHasher(iv, 0, size)
|
||||||
}
|
}
|
||||||
var keyWords [8]uint32
|
var keyWords [8]uint32
|
||||||
bytesToWords(key[:], keyWords[:])
|
for i := range keyWords {
|
||||||
|
keyWords[i] = binary.LittleEndian.Uint32(key[i*4:])
|
||||||
|
}
|
||||||
return newHasher(keyWords, flagKeyedHash, size)
|
return newHasher(keyWords, flagKeyedHash, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,9 +438,12 @@ func DeriveKey(subKey []byte, ctx string, srcKey []byte) {
|
||||||
const derivationIVLen = 32
|
const derivationIVLen = 32
|
||||||
h := newHasher(iv, flagDeriveKeyContext, 32)
|
h := newHasher(iv, flagDeriveKeyContext, 32)
|
||||||
h.Write([]byte(ctx))
|
h.Write([]byte(ctx))
|
||||||
var derivationIV [8]uint32
|
derivationIV := h.Sum(make([]byte, 0, derivationIVLen))
|
||||||
bytesToWords(h.Sum(make([]byte, 0, derivationIVLen)), derivationIV[:])
|
var ivWords [8]uint32
|
||||||
h = newHasher(derivationIV, flagDeriveKeyMaterial, 0)
|
for i := range ivWords {
|
||||||
|
ivWords[i] = binary.LittleEndian.Uint32(derivationIV[i*4:])
|
||||||
|
}
|
||||||
|
h = newHasher(ivWords, flagDeriveKeyMaterial, 0)
|
||||||
// derive the subKey
|
// derive the subKey
|
||||||
h.Write(srcKey)
|
h.Write(srcKey)
|
||||||
h.XOF().Read(subKey)
|
h.XOF().Read(subKey)
|
||||||
|
@ -439,7 +470,7 @@ func (or *OutputReader) Read(p []byte) (int, error) {
|
||||||
if or.off%blockSize == 0 {
|
if or.off%blockSize == 0 {
|
||||||
or.n.counter = or.off / blockSize
|
or.n.counter = or.off / blockSize
|
||||||
words := or.n.compress()
|
words := or.n.compress()
|
||||||
wordsToBytes(words[:], or.block[:])
|
wordsToBytes(words, &or.block)
|
||||||
}
|
}
|
||||||
|
|
||||||
n := copy(p, or.block[or.off%blockSize:])
|
n := copy(p, or.block[or.off%blockSize:])
|
||||||
|
@ -476,7 +507,7 @@ func (or *OutputReader) Seek(offset int64, whence int) (int64, error) {
|
||||||
or.n.counter = uint64(off) / blockSize
|
or.n.counter = uint64(off) / blockSize
|
||||||
if or.off%blockSize != 0 {
|
if or.off%blockSize != 0 {
|
||||||
words := or.n.compress()
|
words := or.n.compress()
|
||||||
wordsToBytes(words[:], or.block[:])
|
wordsToBytes(words, &or.block)
|
||||||
}
|
}
|
||||||
// NOTE: or.off >= 2^63 will result in a negative return value.
|
// NOTE: or.off >= 2^63 will result in a negative return value.
|
||||||
// Nothing we can do about this.
|
// Nothing we can do about this.
|
||||||
|
|
Reference in New Issue