Fixed blake2b not using hash length parameter, fully working 2d variant with correct kat tag

This commit is contained in:
Ugljesa Jovanovic 2020-05-16 10:34:21 +02:00 committed by Ugljesa Jovanovic
parent 1904e2b9f2
commit 6f51a0ec66
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
4 changed files with 72 additions and 16 deletions

View File

@ -150,7 +150,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
val keyBytes = key?.run { val keyBytes = key?.run {
encodeToByteArray().map { it.toUByte() }.toTypedArray() encodeToByteArray().map { it.toUByte() }.toTypedArray()
} ?: emptyArray() } ?: emptyArray()
return digest(inputMessage = array, key = keyBytes) return digest(inputMessage = array, key = keyBytes, hashLength = hashLength)
} }
@ -159,6 +159,9 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
key: Array<UByte>, key: Array<UByte>,
hashLength: Int hashLength: Int
): Array<UByte> { ): Array<UByte> {
if (hashLength > MAX_HASH_BYTES) {
throw RuntimeException("Invalid hash length. Requested length more than maximum length. Requested length $hashLength")
}
val chunkedMessage = inputMessage.chunked(BLOCK_BYTES) val chunkedMessage = inputMessage.chunked(BLOCK_BYTES)
val h = iv.copyOf() val h = iv.copyOf()
@ -202,7 +205,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
compress(h, lastBlockPadded, lastSize.toBigInteger(), true).copyInto(h) compress(h, lastBlockPadded, lastSize.toBigInteger(), true).copyInto(h)
return formatResult(h) return formatResult(h).copyOfRange(0, hashLength)
} }
private fun formatResult(h: Array<ULong>): Array<UByte> { private fun formatResult(h: Array<ULong>): Array<UByte> {

View File

@ -77,7 +77,7 @@ class Argon2 internal constructor(
fun argonBlake2bArbitraryLenghtHash(input: Array<UByte>, length: UInt): Array<UByte> { fun argonBlake2bArbitraryLenghtHash(input: Array<UByte>, length: UInt): Array<UByte> {
if (length <= 64U) { if (length <= 64U) {
return Blake2b.digest(length + input) return Blake2b.digest(inputMessage = length + input, hashLength = length.toInt())
} }
//We can cast to int because UInt even if MAX_VALUE divided by 32 is guaranteed not to overflow //We can cast to int because UInt even if MAX_VALUE divided by 32 is guaranteed not to overflow
val numberOf64ByteBlocks = (1U + ((length - 1U) / 32U) - 2U).toInt() // equivalent to ceil(length/32) - 2 val numberOf64ByteBlocks = (1U + ((length - 1U) / 32U) - 2U).toInt() // equivalent to ceil(length/32) - 2
@ -151,7 +151,8 @@ class Argon2 internal constructor(
private fun extractColumnFromGBlock(gBlock: Array<UByte>, columnPosition: Int): Array<UByte> { private fun extractColumnFromGBlock(gBlock: Array<UByte>, columnPosition: Int): Array<UByte> {
val result = Array<UByte>(128) { 0U } val result = Array<UByte>(128) { 0U }
for (i in 0..7) { for (i in 0..7) {
gBlock.copyOfRange(i * 128 + (columnPosition * 16), i * 128 + (columnPosition * 16) + 16).copyInto(result, i * 16) gBlock.copyOfRange(i * 128 + (columnPosition * 16), i * 128 + (columnPosition * 16) + 16)
.copyInto(result, i * 16)
} }
return result return result
} }
@ -371,7 +372,7 @@ class Argon2 internal constructor(
(slice + 1) * (columnCount / 4) //TODO replace all of these with segment length when consolidating variables (slice + 1) * (columnCount / 4) //TODO replace all of these with segment length when consolidating variables
} }
} }
if ( (startPosition + z.toInt()) % columnCount == -1) { if ((startPosition + z.toInt()) % columnCount == -1) {
println("Debug") println("Debug")
} }
val absolutePosition = (startPosition + z.toInt()) % columnCount val absolutePosition = (startPosition + z.toInt()) % columnCount
@ -492,13 +493,24 @@ class Argon2 internal constructor(
// println("Marker, matrix [$i][1]") // println("Marker, matrix [$i][1]")
} }
// ---- Good until here at least ----
val argonInternalContext = ArgonInternalContext( val argonInternalContext = ArgonInternalContext(
matrix, blockCount, columnCount, segmentLength matrix, blockCount, columnCount, segmentLength
) )
singleThreaded(argonContext, argonInternalContext) singleThreaded(argonContext, argonInternalContext)
return emptyArray() val result = matrix.foldIndexed(emptyArray<UByte>()) { lane, acc, laneArray ->
if (acc.size == 0) {
acc + laneArray[columnCount - 1] // add last element in first lane to the accumulator
} else {
// For each element in our accumulator, xor it with an appropriate element from the last column in current lane (from 1 to `parallelism`)
acc.mapIndexed { index, it -> it xor laneArray[columnCount - 1][index] }
.toTypedArray()
}
}
//Hash the xored last blocks
println("Tag:")
val hash = argonBlake2bArbitraryLenghtHash(result, tagLength)
return hash
} }
fun singleThreaded(argonContext: ArgonContext, argonInternalContext: ArgonInternalContext) { fun singleThreaded(argonContext: ArgonContext, argonInternalContext: ArgonInternalContext) {
@ -511,8 +523,11 @@ class Argon2 internal constructor(
} }
} }
println("Done with $iteration") println("Done with $iteration")
argonInternalContext.matrix[0][0].slice(0 .. 7).toTypedArray().hexColumsPrint(8) argonInternalContext.matrix[0][0].slice(0..7).toTypedArray().hexColumsPrint(8)
argonInternalContext.matrix[argonContext.parallelism.toInt() - 1][argonInternalContext.columnCount - 1].slice(1016 .. 1023).toTypedArray().hexColumsPrint(8) argonInternalContext.matrix[argonContext.parallelism.toInt() - 1][argonInternalContext.columnCount - 1].slice(
1016..1023
).toTypedArray().hexColumsPrint(8)
} }
} }
@ -577,10 +592,29 @@ class Argon2 internal constructor(
} }
} else { } else {
if (slice == 0) { if (slice == 0) {
val (l, z) = computeIndexNew(matrix, lane, 0, columnCount, parallelism.toInt(), iteration, slice, type) val (l, z) = computeIndexNew(
matrix[lane][0] = compressionFunctionG(matrix[lane][columnCount - 1], matrix[l][z], matrix[lane][0], true) matrix,
lane,
0,
columnCount,
parallelism.toInt(),
iteration,
slice,
type
)
matrix[lane][0] =
compressionFunctionG(matrix[lane][columnCount - 1], matrix[l][z], matrix[lane][0], true)
for (column in 1 until segmentLength) { for (column in 1 until segmentLength) {
val (l, z) = computeIndexNew(matrix, lane, column, columnCount, parallelism.toInt(), iteration, slice, type) val (l, z) = computeIndexNew(
matrix,
lane,
column,
columnCount,
parallelism.toInt(),
iteration,
slice,
type
)
println("Calling compress for I: $iteration S: $slice Lane: $lane Column: $column with l: $l z: $z") println("Calling compress for I: $iteration S: $slice Lane: $lane Column: $column with l: $l z: $z")
matrix[lane][column] = matrix[lane][column] =
compressionFunctionG(matrix[lane][column - 1], matrix[l][z], matrix[lane][column], true) compressionFunctionG(matrix[lane][column - 1], matrix[l][z], matrix[lane][column], true)
@ -588,7 +622,16 @@ class Argon2 internal constructor(
} }
} else { } else {
for (column in slice * segmentLength until (slice + 1) * segmentLength) { for (column in slice * segmentLength until (slice + 1) * segmentLength) {
val (l, z) = computeIndexNew(matrix, lane, column, columnCount, parallelism.toInt(), iteration, slice, type) val (l, z) = computeIndexNew(
matrix,
lane,
column,
columnCount,
parallelism.toInt(),
iteration,
slice,
type
)
println("Calling compress for I: $iteration S: $slice Lane: $lane Column: $column with l: $l z: $z") println("Calling compress for I: $iteration S: $slice Lane: $lane Column: $column with l: $l z: $z")
matrix[lane][column] = matrix[lane][column] =
compressionFunctionG(matrix[lane][column - 1], matrix[l][z], matrix[lane][column], true) compressionFunctionG(matrix[lane][column - 1], matrix[l][z], matrix[lane][column], true)
@ -600,8 +643,6 @@ class Argon2 internal constructor(
} }
// //Remaining iteration // //Remaining iteration
// val remainingIterations = (1..numberOfIterations.toInt()).map { iteration -> // val remainingIterations = (1..numberOfIterations.toInt()).map { iteration ->
// //

View File

@ -17,6 +17,7 @@
package com.ionspin.kotlin.crypto.hash.blake2b package com.ionspin.kotlin.crypto.hash.blake2b
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertFailsWith
import kotlin.test.assertTrue import kotlin.test.assertTrue
/** /**
@ -280,4 +281,13 @@ class Blake2BTest {
} }
@Test
fun testInvalidHashLength() {
val test = "1234567890"
assertFailsWith(RuntimeException::class) {
val result = Blake2b.digest(inputString = test, hashLength = 65)
}
}
} }

View File

@ -19,6 +19,7 @@
package com.ionspin.kotlin.crypto.hash.keyderivation package com.ionspin.kotlin.crypto.hash.keyderivation
import com.ionspin.kotlin.crypto.keyderivation.Argon2 import com.ionspin.kotlin.crypto.keyderivation.Argon2
import com.ionspin.kotlin.crypto.util.hexColumsPrint
import kotlin.test.Test import kotlin.test.Test
/** /**
@ -58,6 +59,7 @@ class Argon2Test {
type = Argon2.ArgonType.Argon2d type = Argon2.ArgonType.Argon2d
) )
val result = digest.calculate() val result = digest.calculate()
result.hexColumsPrint(8)
} }
} }