Replacing array of arrays of ubyte arrays with custom argon2 matrix

This commit is contained in:
Ugljesa Jovanovic 2020-05-21 21:02:19 +02:00 committed by Ugljesa Jovanovic
parent f5b3eb6b92
commit 13b60a5eee
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
3 changed files with 126 additions and 53 deletions

View File

@ -27,6 +27,7 @@ import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.compressionFun
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.validateArgonParameters
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToUInt
import com.ionspin.kotlin.crypto.util.toLittleEndianUByteArray
import com.ionspin.kotlin.crypto.util.xor
/**
* Created by Ugljesa Jovanovic
@ -132,15 +133,10 @@ class Argon2(
private val useIndependentAddressing = argonType == ArgonType.Argon2id || argonType == ArgonType.Argon2i
// State
private val matrix: Array<Array<UByteArray>>
private val matrix: Argon2Matrix
init {
matrix = Array(parallelism) {
Array(columnCount) {
UByteArray(1024)
}
}
matrix = Argon2Matrix(columnCount, parallelism)
validateArgonParameters(
password,
salt,
@ -154,15 +150,7 @@ class Argon2(
)
}
private fun clearMatrix() {
matrix.forEachIndexed { laneIndex, lane ->
lane.forEachIndexed { columnIndex, block ->
block.forEachIndexed { byteIndex, byte ->
matrix[laneIndex][columnIndex][byteIndex] = 0U
}
}
}
}
private fun populateAddressBlock(
iteration: Int,
@ -202,17 +190,18 @@ class Argon2(
column: Int,
addressBlock: UByteArray?
): Pair<Int, Int> {
val segmentIndex = (column % segmentLength)
val independentIndex = segmentIndex % 128 // 128 is the number of addresses in address block
val (j1, j2) = when (argonType) {
ArgonType.Argon2d -> {
val previousBlock = if (column == 0) {
matrix[lane][columnCount - 1] //Get last block in the SAME lane
val (previousBlockStart, previousBlockEnd) = if (column == 0) {
matrix.getBlockStartAndEndPositions(lane, columnCount - 1) //Get last block in the SAME lane
} else {
matrix[lane][column - 1]
matrix.getBlockStartAndEndPositions(lane, column - 1)
}
val first32Bit = previousBlock.sliceArray(0 until 4).fromLittleEndianArrayToUInt()
val second32Bit = previousBlock.sliceArray(4 until 8).fromLittleEndianArrayToUInt()
val first32Bit = matrix.sliceArray(previousBlockStart until previousBlockStart + 4).fromLittleEndianArrayToUInt()
val second32Bit = matrix.sliceArray(previousBlockStart + 4 until previousBlockStart + 8).fromLittleEndianArrayToUInt()
Pair(first32Bit, second32Bit)
}
ArgonType.Argon2i -> {
@ -230,13 +219,13 @@ class Argon2(
val second32Bit = selectedAddressBlock.sliceArray(4 until 8).fromLittleEndianArrayToUInt()
Pair(first32Bit, second32Bit)
} else {
val previousBlock = if (column == 0) {
matrix[lane][columnCount - 1] //Get last block in the SAME lane
val (previousBlockStart, previousBlockEnd) = if (column == 0) {
matrix.getBlockStartAndEndPositions(lane, columnCount - 1) //Get last block in the SAME lane
} else {
matrix[lane][column - 1]
matrix.getBlockStartAndEndPositions(lane, column - 1)
}
val first32Bit = previousBlock.sliceArray(0 until 4).fromLittleEndianArrayToUInt()
val second32Bit = previousBlock.sliceArray(4 until 8).fromLittleEndianArrayToUInt()
val first32Bit = matrix.sliceArray(previousBlockStart until previousBlockStart + 4).fromLittleEndianArrayToUInt()
val second32Bit = matrix.sliceArray(previousBlockStart + 4 until previousBlockStart + 8).fromLittleEndianArrayToUInt()
Pair(first32Bit, second32Bit)
}
@ -315,35 +304,43 @@ class Argon2(
//Compute B[i][0]
for (i in 0 until parallelism) {
matrix[i][0] =
matrix.setBlockAt(i, 0,
argonBlake2bArbitraryLenghtHash(
(h0 + 0.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray()).toUByteArray(),
1024U
)
)
}
//Compute B[i][1]
for (i in 0 until parallelism) {
matrix[i][1] =
matrix.setBlockAt(i, 1,
argonBlake2bArbitraryLenghtHash(
(h0 + 1.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray()).toUByteArray(),
1024U
)
)
}
//Run all iterations over all lanes and all segments
executeArgonWithSingleThread()
val result = matrix.foldIndexed(ubyteArrayOf()) { 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] }.toUByteArray()
}
// val result = matrix.foldIndexed(ubyteArrayOf()) { 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] }.toUByteArray()
//
// }
// }
//Temporary fold
val acc = matrix.getBlockAt(0, columnCount - 1).copyOf()
for (i in 1 until parallelism) {
acc.xor(matrix.getBlockAt(i, columnCount -1))
}
//Hash the xored last blocks
val hash = argonBlake2bArbitraryLenghtHash(result, tagLength)
clearMatrix()
val hash = argonBlake2bArbitraryLenghtHash(acc, tagLength)
matrix.clearMatrix()
return hash
@ -403,13 +400,14 @@ class Argon2(
column,
addressBlock
)
matrix[lane][column] =
matrix.setBlockAt(lane, column,
compressionFunctionG(
matrix[lane][previousColumn],
matrix[l][z],
matrix[lane][column],
matrix.getBlockAt(lane, previousColumn),
matrix.getBlockAt(l,z),
matrix.getBlockAt(lane,column),
true
).toUByteArray()
)
}
}

View File

@ -28,21 +28,67 @@ package com.ionspin.kotlin.crypto.keyderivation.argon2
internal val storage: UByteArray = UByteArray(columnCount * rowCount * 1024)
operator fun get(rowPosition: Int, columnPosition: Int, inBlockPosition: Int) : UByte {
return storage[rowPosition * (columnCount - 1) * 1024 + columnPosition * 1024 + inBlockPosition]
if (rowPosition > rowCount - 1) {
throw RuntimeException("Invalid row (lane) requested: $rowPosition, rowCount: $rowCount")
}
if (columnPosition > columnCount - 1) {
throw RuntimeException("Invalid column requested: $columnPosition, columnCount: $columnCount")
}
return storage[getBlockStartPosition(rowPosition, columnPosition) + inBlockPosition]
}
operator fun get(rowPosition: Int, columnPosition: Int) : UByteArray {
println("Expensive.")
return storage.copyOfRange(
rowPosition * (columnCount - 1) * 1024 + columnPosition * 1024,
rowPosition * (columnCount - 1) * 1024 + columnPosition * 1024 + 1024
operator fun set(rowPosition: Int, columnPosition: Int, inBlockPosition: Int, value: UByte) {
storage[getBlockStartPosition(rowPosition, columnPosition) + inBlockPosition] = value
}
fun getBlockStartAndEndPositions(rowPosition: Int, columnPosition: Int) : Pair<Int, Int> {
val start = getBlockStartPosition(rowPosition, columnPosition)
return Pair(
start,
start + 1024
)
}
operator fun get(rowPosition: Int) : Array<UByteArray> {
return Array(columnCount) {
this.get(rowPosition, it)
fun sliceArray(indices: IntRange): UByteArray {
return storage.sliceArray(indices)
}
fun getBlockAt(rowPosition: Int, columnPosition: Int) : UByteArray {
println("Expensive get")
return storage.copyOfRange(
getBlockStartPosition(rowPosition, columnPosition),
getBlockStartPosition(rowPosition, columnPosition) + 1024
)
}
fun setBlockAt(rowPosition: Int, columnPosition: Int, blockValue: UByteArray) {
println("Expensive set")
blockValue.copyInto(
storage,
getBlockStartPosition(rowPosition, columnPosition)
)
}
private inline fun getBlockStartPosition(rowPosition: Int, columnPosition: Int) : Int {
return rowPosition * columnCount * 1024 + columnPosition * 1024
}
// operator fun get(rowPosition: Int, columnPosition: Int) : UByteArray {
// println("Expensive.")
// return storage.copyOfRange(
// rowPosition * (columnCount - 1) * 1024 + columnPosition * 1024,
// rowPosition * (columnCount - 1) * 1024 + columnPosition * 1024 + 1024
// )
// }
//
// operator fun get(rowPosition: Int) : Array<UByteArray> {
// return Array(columnCount) {
// this.get(rowPosition, it)
// }
//
// }
internal fun clearMatrix() {
for( index in storage.indices) { storage[index] = 0U }
}
}

View File

@ -36,7 +36,36 @@ class Argon2MatrixTest {
@Test
fun debugTest() {
fun indexAccessTest() {
val argon2Matrix = Argon2Matrix(2, 2)
(zeroesBlock + onesBlock + twosBlock + threesBlock).copyInto(argon2Matrix.storage)
println(argon2Matrix[0, 0, 0])
println(argon2Matrix[0, 1, 0])
println(argon2Matrix[1, 0, 0])
println(argon2Matrix[1, 1, 0])
// argon2Matrix.storage.hexColumsPrint(1024)
var expectedByteValue = 0U.toUByte()
for (lane in 0 until 2) {
for (column in 0 until 2) {
for (blockPosition in 0 until 1024) {
assertTrue {
argon2Matrix[lane, column, blockPosition] == expectedByteValue
}
}
expectedByteValue++
}
}
assertTrue {
argon2Matrix[0, 0, 0] == 0U.toUByte() &&
argon2Matrix[0, 1, 0] == 1U.toUByte() &&
argon2Matrix[1, 0, 0] == 2U.toUByte() &&
argon2Matrix[1, 1, 0] == 3U.toUByte()
}
}
@Test
fun blockRetrievalTest() {
val argon2Matrix = Argon2Matrix(2, 2)
(zeroesBlock + onesBlock + twosBlock + threesBlock).copyInto(argon2Matrix.storage)
println(argon2Matrix[0, 0, 0])