Replacing array of arrays of ubyte arrays with custom argon2 matrix
This commit is contained in:
		
							parent
							
								
									f5b3eb6b92
								
							
						
					
					
						commit
						13b60a5eee
					
				@ -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()
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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 }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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])
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user