refactor Blake and Blake2

This commit is contained in:
2025-12-04 19:05:54 +01:00
parent 85ab748c07
commit 16390b0308
6 changed files with 112 additions and 137 deletions

View File

@@ -43,12 +43,25 @@ object `Blake-224` : HashFunction() {
) )
override fun hash(value: UByteArray): UByteArray { override fun hash(value: UByteArray): UByteArray {
val l = value.size.toULong() * 8UL
val h = initial.copyOf() val h = initial.copyOf()
var t = 0U var t = 0U
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(64) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 512UL).toUInt()
compress(h, block, t)
}
return h.sliceArray(0..6).toUByteArray()
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 64 != 56) { while (size % 64 != 56) {
@@ -56,56 +69,39 @@ object `Blake-224` : HashFunction() {
} }
addAll(l.toUByteArray()) addAll(l.toUByteArray())
}.toUByteArray() }.toUByteArray()
// compress
val blocks = paddedValue
.chunked(64) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 512UL).toUInt()
val m = block.toUIntArray()
compress(h, m, t)
}
return h.sliceArray(0..6).toUByteArray()
} }
private fun compress( private fun compress(
h: UIntArray, h: UIntArray,
m: UIntArray, block: UByteArray,
t: UInt, t: UInt,
) { ) {
// initialization val m = block.toUIntArray()
val v = UIntArray(16) val v = UIntArray(16)
for (i in 0..<8) v[i] = h[i] for (i in 0..<8) v[i] = h[i]
for (i in 0..<4) v[i + 8] = c[i] for (i in 0..<4) v[i + 8] = c[i]
for (i in 0..<2) v[i + 12] = c[i + 4] xor t for (i in 0..<2) v[i + 12] = c[i + 4] xor t
for (i in 0..<2) v[i + 14] = c[i + 6] for (i in 0..<2) v[i + 14] = c[i + 6]
// rounds repeat(14) { r ->
for (r in 0..<14) {
val s = sigma[r % 10] val s = sigma[r % 10]
// column
g(v, 0, 4, 8, 12, m[s[0]] xor c[s[1]], m[s[1]] xor c[s[0]]) g(v, 0, 4, 8, 12, m[s[0]] xor c[s[1]], m[s[1]] xor c[s[0]])
g(v, 1, 5, 9, 13, m[s[2]] xor c[s[3]], m[s[3]] xor c[s[2]]) g(v, 1, 5, 9, 13, m[s[2]] xor c[s[3]], m[s[3]] xor c[s[2]])
g(v, 2, 6, 10, 14, m[s[4]] xor c[s[5]], m[s[5]] xor c[s[4]]) g(v, 2, 6, 10, 14, m[s[4]] xor c[s[5]], m[s[5]] xor c[s[4]])
g(v, 3, 7, 11, 15, m[s[6]] xor c[s[7]], m[s[7]] xor c[s[6]]) g(v, 3, 7, 11, 15, m[s[6]] xor c[s[7]], m[s[7]] xor c[s[6]])
// diagonal
g(v, 0, 5, 10, 15, m[s[8]] xor c[s[9]], m[s[9]] xor c[s[8]]) g(v, 0, 5, 10, 15, m[s[8]] xor c[s[9]], m[s[9]] xor c[s[8]])
g(v, 1, 6, 11, 12, m[s[10]] xor c[s[11]], m[s[11]] xor c[s[10]]) g(v, 1, 6, 11, 12, m[s[10]] xor c[s[11]], m[s[11]] xor c[s[10]])
g(v, 2, 7, 8, 13, m[s[12]] xor c[s[13]], m[s[13]] xor c[s[12]]) g(v, 2, 7, 8, 13, m[s[12]] xor c[s[13]], m[s[13]] xor c[s[12]])
g(v, 3, 4, 9, 14, m[s[14]] xor c[s[15]], m[s[15]] xor c[s[14]]) g(v, 3, 4, 9, 14, m[s[14]] xor c[s[15]], m[s[15]] xor c[s[14]])
} }
// finalization
for (i in 0..7) { for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8] h[i] = h[i] xor v[i] xor v[i + 8]
} }
} }
// round function
private fun g( private fun g(
v: UIntArray, v: UIntArray,
a: Int, a: Int,

View File

@@ -43,12 +43,25 @@ object `Blake-256` : HashFunction() {
) )
override fun hash(value: UByteArray): UByteArray { override fun hash(value: UByteArray): UByteArray {
val l = value.size.toULong() * 8UL
val h = initial.copyOf() val h = initial.copyOf()
var t = 0U var t = 0U
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(64) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 512UL).toUInt()
compress(h, block, t)
}
return h.toUByteArray()
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 64 != 55) { while (size % 64 != 55) {
@@ -57,56 +70,39 @@ object `Blake-256` : HashFunction() {
add(0x01U) add(0x01U)
addAll(l.toUByteArray()) addAll(l.toUByteArray())
}.toUByteArray() }.toUByteArray()
// compress
val blocks = paddedValue
.chunked(64) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 512UL).toUInt()
val m = block.toUIntArray()
compress(h, m, t)
}
return h.toUByteArray()
} }
private fun compress( private fun compress(
h: UIntArray, h: UIntArray,
m: UIntArray, block: UByteArray,
t: UInt, t: UInt,
) { ) {
// initialization val m = block.toUIntArray()
val v = UIntArray(16) val v = UIntArray(16)
for (i in 0..<8) v[i] = h[i] for (i in 0..<8) v[i] = h[i]
for (i in 0..<4) v[i + 8] = c[i] for (i in 0..<4) v[i + 8] = c[i]
for (i in 0..<2) v[i + 12] = c[i + 4] xor t for (i in 0..<2) v[i + 12] = c[i + 4] xor t
for (i in 0..<2) v[i + 14] = c[i + 6] for (i in 0..<2) v[i + 14] = c[i + 6]
// rounds repeat(14) { r ->
for (r in 0..<14) {
val s = sigma[r % 10] val s = sigma[r % 10]
// column
g(v, 0, 4, 8, 12, m[s[0]] xor c[s[1]], m[s[1]] xor c[s[0]]) g(v, 0, 4, 8, 12, m[s[0]] xor c[s[1]], m[s[1]] xor c[s[0]])
g(v, 1, 5, 9, 13, m[s[2]] xor c[s[3]], m[s[3]] xor c[s[2]]) g(v, 1, 5, 9, 13, m[s[2]] xor c[s[3]], m[s[3]] xor c[s[2]])
g(v, 2, 6, 10, 14, m[s[4]] xor c[s[5]], m[s[5]] xor c[s[4]]) g(v, 2, 6, 10, 14, m[s[4]] xor c[s[5]], m[s[5]] xor c[s[4]])
g(v, 3, 7, 11, 15, m[s[6]] xor c[s[7]], m[s[7]] xor c[s[6]]) g(v, 3, 7, 11, 15, m[s[6]] xor c[s[7]], m[s[7]] xor c[s[6]])
// diagonal
g(v, 0, 5, 10, 15, m[s[8]] xor c[s[9]], m[s[9]] xor c[s[8]]) g(v, 0, 5, 10, 15, m[s[8]] xor c[s[9]], m[s[9]] xor c[s[8]])
g(v, 1, 6, 11, 12, m[s[10]] xor c[s[11]], m[s[11]] xor c[s[10]]) g(v, 1, 6, 11, 12, m[s[10]] xor c[s[11]], m[s[11]] xor c[s[10]])
g(v, 2, 7, 8, 13, m[s[12]] xor c[s[13]], m[s[13]] xor c[s[12]]) g(v, 2, 7, 8, 13, m[s[12]] xor c[s[13]], m[s[13]] xor c[s[12]])
g(v, 3, 4, 9, 14, m[s[14]] xor c[s[15]], m[s[15]] xor c[s[14]]) g(v, 3, 4, 9, 14, m[s[14]] xor c[s[15]], m[s[15]] xor c[s[14]])
} }
// finalization
for (i in 0..7) { for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8] h[i] = h[i] xor v[i] xor v[i + 8]
} }
} }
// round function
private fun g( private fun g(
v: UIntArray, v: UIntArray,
a: Int, a: Int,

View File

@@ -43,12 +43,25 @@ object `Blake-384` : HashFunction() {
) )
override fun hash(value: UByteArray): UByteArray { override fun hash(value: UByteArray): UByteArray {
val l = value.size.toULong() * 8UL
val h = initial.copyOf() val h = initial.copyOf()
var t = 0UL var t = 0UL
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(128) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 1024UL)
compress(h, block, t)
}
return h.sliceArray(0..5).toUByteArray()
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 128 != 120) { while (size % 128 != 120) {
@@ -56,56 +69,39 @@ object `Blake-384` : HashFunction() {
} }
addAll(l.toUByteArray()) addAll(l.toUByteArray())
}.toUByteArray() }.toUByteArray()
// compress
val blocks = paddedValue
.chunked(128) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 1024UL)
val m = block.toULongArray()
compress(h, m, t)
}
return h.sliceArray(0..5).toUByteArray()
} }
private fun compress( private fun compress(
h: ULongArray, h: ULongArray,
m: ULongArray, block: UByteArray,
t: ULong, t: ULong,
) { ) {
// initialization val m = block.toULongArray()
val v = ULongArray(16) val v = ULongArray(16)
for (i in 0..<8) v[i] = h[i] for (i in 0..<8) v[i] = h[i]
for (i in 0..<4) v[i + 8] = c[i] for (i in 0..<4) v[i + 8] = c[i]
for (i in 0..<2) v[i + 12] = c[i + 4] xor t for (i in 0..<2) v[i + 12] = c[i + 4] xor t
for (i in 0..<2) v[i + 14] = c[i + 6] for (i in 0..<2) v[i + 14] = c[i + 6]
// rounds repeat(16) { r ->
for (r in 0..<16) {
val s = sigma[r % 10] val s = sigma[r % 10]
// column
g(v, 0, 4, 8, 12, m[s[0]] xor c[s[1]], m[s[1]] xor c[s[0]]) g(v, 0, 4, 8, 12, m[s[0]] xor c[s[1]], m[s[1]] xor c[s[0]])
g(v, 1, 5, 9, 13, m[s[2]] xor c[s[3]], m[s[3]] xor c[s[2]]) g(v, 1, 5, 9, 13, m[s[2]] xor c[s[3]], m[s[3]] xor c[s[2]])
g(v, 2, 6, 10, 14, m[s[4]] xor c[s[5]], m[s[5]] xor c[s[4]]) g(v, 2, 6, 10, 14, m[s[4]] xor c[s[5]], m[s[5]] xor c[s[4]])
g(v, 3, 7, 11, 15, m[s[6]] xor c[s[7]], m[s[7]] xor c[s[6]]) g(v, 3, 7, 11, 15, m[s[6]] xor c[s[7]], m[s[7]] xor c[s[6]])
// diagonal
g(v, 0, 5, 10, 15, m[s[8]] xor c[s[9]], m[s[9]] xor c[s[8]]) g(v, 0, 5, 10, 15, m[s[8]] xor c[s[9]], m[s[9]] xor c[s[8]])
g(v, 1, 6, 11, 12, m[s[10]] xor c[s[11]], m[s[11]] xor c[s[10]]) g(v, 1, 6, 11, 12, m[s[10]] xor c[s[11]], m[s[11]] xor c[s[10]])
g(v, 2, 7, 8, 13, m[s[12]] xor c[s[13]], m[s[13]] xor c[s[12]]) g(v, 2, 7, 8, 13, m[s[12]] xor c[s[13]], m[s[13]] xor c[s[12]])
g(v, 3, 4, 9, 14, m[s[14]] xor c[s[15]], m[s[15]] xor c[s[14]]) g(v, 3, 4, 9, 14, m[s[14]] xor c[s[15]], m[s[15]] xor c[s[14]])
} }
// finalization
for (i in 0..7) { for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8] h[i] = h[i] xor v[i] xor v[i + 8]
} }
} }
// round function
private fun g( private fun g(
v: ULongArray, v: ULongArray,
a: Int, a: Int,

View File

@@ -43,12 +43,25 @@ object `Blake-512` : HashFunction() {
) )
override fun hash(value: UByteArray): UByteArray { override fun hash(value: UByteArray): UByteArray {
val l = value.size.toULong() * 8UL
val h = initial.copyOf() val h = initial.copyOf()
var t = 0UL var t = 0UL
val l = value.size.toULong() * 8UL
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(128) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 1024UL)
compress(h, block, t)
}
return h.toUByteArray()
}
private fun pad(
value: UByteArray,
): UByteArray {
val l = value.size.toULong() * 8UL
return buildList {
addAll(value) addAll(value)
add(0x80U) add(0x80U)
while (size % 128 != 111) { while (size % 128 != 111) {
@@ -58,56 +71,39 @@ object `Blake-512` : HashFunction() {
repeat(8) { add(0x00U) } repeat(8) { add(0x00U) }
addAll(l.toUByteArray()) addAll(l.toUByteArray())
}.toUByteArray() }.toUByteArray()
// compress
val blocks = paddedValue
.chunked(128) { it.toUByteArray() }
for (block in blocks) {
t += minOf(l - t, 1024UL)
val m = block.toULongArray()
compress(h, m, t)
}
return h.toUByteArray()
} }
private fun compress( private fun compress(
h: ULongArray, h: ULongArray,
m: ULongArray, block: UByteArray,
t: ULong, t: ULong,
) { ) {
// initialization val m = block.toULongArray()
val v = ULongArray(16) val v = ULongArray(16)
for (i in 0..<8) v[i] = h[i] for (i in 0..<8) v[i] = h[i]
for (i in 0..<4) v[i + 8] = c[i] for (i in 0..<4) v[i + 8] = c[i]
for (i in 0..<2) v[i + 12] = c[i + 4] xor t for (i in 0..<2) v[i + 12] = c[i + 4] xor t
for (i in 0..<2) v[i + 14] = c[i + 6] for (i in 0..<2) v[i + 14] = c[i + 6]
// rounds repeat(16) { r ->
for (r in 0..<16) {
val s = sigma[r % 10] val s = sigma[r % 10]
// column
g(v, 0, 4, 8, 12, m[s[0]] xor c[s[1]], m[s[1]] xor c[s[0]]) g(v, 0, 4, 8, 12, m[s[0]] xor c[s[1]], m[s[1]] xor c[s[0]])
g(v, 1, 5, 9, 13, m[s[2]] xor c[s[3]], m[s[3]] xor c[s[2]]) g(v, 1, 5, 9, 13, m[s[2]] xor c[s[3]], m[s[3]] xor c[s[2]])
g(v, 2, 6, 10, 14, m[s[4]] xor c[s[5]], m[s[5]] xor c[s[4]]) g(v, 2, 6, 10, 14, m[s[4]] xor c[s[5]], m[s[5]] xor c[s[4]])
g(v, 3, 7, 11, 15, m[s[6]] xor c[s[7]], m[s[7]] xor c[s[6]]) g(v, 3, 7, 11, 15, m[s[6]] xor c[s[7]], m[s[7]] xor c[s[6]])
// diagonal
g(v, 0, 5, 10, 15, m[s[8]] xor c[s[9]], m[s[9]] xor c[s[8]]) g(v, 0, 5, 10, 15, m[s[8]] xor c[s[9]], m[s[9]] xor c[s[8]])
g(v, 1, 6, 11, 12, m[s[10]] xor c[s[11]], m[s[11]] xor c[s[10]]) g(v, 1, 6, 11, 12, m[s[10]] xor c[s[11]], m[s[11]] xor c[s[10]])
g(v, 2, 7, 8, 13, m[s[12]] xor c[s[13]], m[s[13]] xor c[s[12]]) g(v, 2, 7, 8, 13, m[s[12]] xor c[s[13]], m[s[13]] xor c[s[12]])
g(v, 3, 4, 9, 14, m[s[14]] xor c[s[15]], m[s[15]] xor c[s[14]]) g(v, 3, 4, 9, 14, m[s[14]] xor c[s[15]], m[s[15]] xor c[s[14]])
} }
// finalization
for (i in 0..7) { for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8] h[i] = h[i] xor v[i] xor v[i + 8]
} }
} }
// round function
private fun g( private fun g(
v: ULongArray, v: ULongArray,
a: Int, a: Int,

View File

@@ -36,65 +36,60 @@ class Blake2b(
) )
override fun hash(value: UByteArray): UByteArray { override fun hash(value: UByteArray): UByteArray {
val l = value.size.toULong()
val h = initial.copyOf() val h = initial.copyOf()
h[0] = h[0] xor (0x01010000UL or bytes.toULong()) h[0] = h[0] xor (0x01010000UL or bytes.toULong())
var t = 0UL var t = 0UL
val l = value.size.toULong()
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(128) { it.toUByteArray() }
for ((i, block) in blocks.withIndex()) {
t += minOf(l - t, 128UL)
compress(h, block, t, i == blocks.lastIndex)
}
return h.toUByteArray(ByteOrder.LITTLE_ENDIAN).sliceArray(0..<bytes)
}
private fun pad(
value: UByteArray,
): UByteArray {
return buildList {
addAll(value) addAll(value)
if (isEmpty()) add(0x00U) if (isEmpty()) add(0x00U)
while (size % 128 != 0) { while (size % 128 != 0) {
add(0x00U) add(0x00U)
} }
}.toUByteArray() }.toUByteArray()
// compress
val blocks = paddedValue
.chunked(128) { it.toUByteArray() }
for ((i, block) in blocks.withIndex()) {
t += minOf(l - t, 128UL)
val m = block.toULongArray()
compress(h, m, t, i == blocks.lastIndex)
}
return h.toUByteArray(ByteOrder.LITTLE_ENDIAN).sliceArray(0..<bytes)
} }
private fun compress( private fun compress(
h: ULongArray, h: ULongArray,
m: ULongArray, block: UByteArray,
t: ULong, t: ULong,
last: Boolean, last: Boolean,
) { ) {
// initialization val m = block.toULongArray()
val v = ULongArray(16) val v = ULongArray(16)
for (i in 0..<8) v[i] = h[i] for (i in 0..<8) v[i] = h[i]
for (i in 0..<8) v[i + 8] = initial[i] for (i in 0..<8) v[i + 8] = initial[i]
v[12] = v[12] xor t v[12] = v[12] xor t
if (last) v[14] = v[14].inv() if (last) v[14] = v[14].inv()
// rounds repeat(12) { r ->
for (r in 0..<12) {
val s = sigma[r % 10] val s = sigma[r % 10]
// column
mix(v, 0, 4, 8, 12, m[s[0]], m[s[1]]) mix(v, 0, 4, 8, 12, m[s[0]], m[s[1]])
mix(v, 1, 5, 9, 13, m[s[2]], m[s[3]]) mix(v, 1, 5, 9, 13, m[s[2]], m[s[3]])
mix(v, 2, 6, 10, 14, m[s[4]], m[s[5]]) mix(v, 2, 6, 10, 14, m[s[4]], m[s[5]])
mix(v, 3, 7, 11, 15, m[s[6]], m[s[7]]) mix(v, 3, 7, 11, 15, m[s[6]], m[s[7]])
// diagonal
mix(v, 0, 5, 10, 15, m[s[8]], m[s[9]]) mix(v, 0, 5, 10, 15, m[s[8]], m[s[9]])
mix(v, 1, 6, 11, 12, m[s[10]], m[s[11]]) mix(v, 1, 6, 11, 12, m[s[10]], m[s[11]])
mix(v, 2, 7, 8, 13, m[s[12]], m[s[13]]) mix(v, 2, 7, 8, 13, m[s[12]], m[s[13]])
mix(v, 3, 4, 9, 14, m[s[14]], m[s[15]]) mix(v, 3, 4, 9, 14, m[s[14]], m[s[15]])
} }
// finalization
for (i in 0..7) { for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8] h[i] = h[i] xor v[i] xor v[i + 8]
} }

View File

@@ -36,40 +36,40 @@ class Blake2s(
) )
override fun hash(value: UByteArray): UByteArray { override fun hash(value: UByteArray): UByteArray {
val l = value.size.toULong()
val h = initial.copyOf() val h = initial.copyOf()
h[0] = h[0] xor (0x01010000U or bytes.toUInt()) h[0] = h[0] xor (0x01010000U or bytes.toUInt())
var t = 0U var t = 0U
val l = value.size.toULong()
// padding val blocks = pad(value)
val paddedValue = buildList { .chunked(64) { it.toUByteArray() }
for ((i, block) in blocks.withIndex()) {
t += minOf(l - t, 64UL).toUInt()
compress(h, block, t, i == blocks.lastIndex)
}
return h.toUByteArray(LITTLE_ENDIAN).sliceArray(0..<bytes)
}
private fun pad(
value: UByteArray,
): UByteArray {
return buildList {
addAll(value) addAll(value)
if (isEmpty()) add(0x00U) if (isEmpty()) add(0x00U)
while (size % 64 != 0) { while (size % 64 != 0) {
add(0x00U) add(0x00U)
} }
}.toUByteArray() }.toUByteArray()
// compress
val blocks = paddedValue
.chunked(64) { it.toUByteArray() }
for ((i, block) in blocks.withIndex()) {
t += minOf(l - t, 64U).toUInt()
val m = block.toUIntArray()
compress(h, m, t, i == blocks.lastIndex)
}
return h.toUByteArray(LITTLE_ENDIAN).sliceArray(0..<bytes)
} }
private fun compress( private fun compress(
h: UIntArray, h: UIntArray,
m: UIntArray, block: UByteArray,
t: UInt, t: UInt,
last: Boolean, last: Boolean,
) { ) {
// initialization val m = block.toUIntArray()
val v = UIntArray(16) val v = UIntArray(16)
for (i in 0..<8) v[i] = h[i] for (i in 0..<8) v[i] = h[i]
for (i in 0..<8) v[i + 8] = initial[i] for (i in 0..<8) v[i + 8] = initial[i]
@@ -77,24 +77,20 @@ class Blake2s(
v[12] = v[12] xor t v[12] = v[12] xor t
if (last) v[14] = v[14].inv() if (last) v[14] = v[14].inv()
// rounds repeat(10) { r ->
for (r in 0..<10) {
val s = sigma[r] val s = sigma[r]
// column
mix(v, 0, 4, 8, 12, m[s[0]], m[s[1]]) mix(v, 0, 4, 8, 12, m[s[0]], m[s[1]])
mix(v, 1, 5, 9, 13, m[s[2]], m[s[3]]) mix(v, 1, 5, 9, 13, m[s[2]], m[s[3]])
mix(v, 2, 6, 10, 14, m[s[4]], m[s[5]]) mix(v, 2, 6, 10, 14, m[s[4]], m[s[5]])
mix(v, 3, 7, 11, 15, m[s[6]], m[s[7]]) mix(v, 3, 7, 11, 15, m[s[6]], m[s[7]])
// diagonal
mix(v, 0, 5, 10, 15, m[s[8]], m[s[9]]) mix(v, 0, 5, 10, 15, m[s[8]], m[s[9]])
mix(v, 1, 6, 11, 12, m[s[10]], m[s[11]]) mix(v, 1, 6, 11, 12, m[s[10]], m[s[11]])
mix(v, 2, 7, 8, 13, m[s[12]], m[s[13]]) mix(v, 2, 7, 8, 13, m[s[12]], m[s[13]])
mix(v, 3, 4, 9, 14, m[s[14]], m[s[15]]) mix(v, 3, 4, 9, 14, m[s[14]], m[s[15]])
} }
// finalization
for (i in 0..7) { for (i in 0..7) {
h[i] = h[i] xor v[i] xor v[i + 8] h[i] = h[i] xor v[i] xor v[i + 8]
} }