diff --git a/multiplatform-crypto/build.gradle.kts b/multiplatform-crypto/build.gradle.kts index 9564389..56756ab 100644 --- a/multiplatform-crypto/build.gradle.kts +++ b/multiplatform-crypto/build.gradle.kts @@ -312,6 +312,9 @@ kotlin { val linuxArm64Test by getting { dependsOn(nativeTest) } + all { + languageSettings.enableLanguageFeature("InlineClasses") + } } diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/keyderivation/Argon2.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/keyderivation/Argon2.kt index fd1c522..1098a01 100644 --- a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/keyderivation/Argon2.kt +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/keyderivation/Argon2.kt @@ -13,12 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.ionspin.kotlin.crypto.keyderivation import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b import com.ionspin.kotlin.crypto.util.* - /** * * Further resources and examples of implementation: @@ -63,9 +61,17 @@ class Argon2 internal constructor( } + @ExperimentalStdlibApi companion object { + fun Array.xor(target : Array, other : Array) { + if (this.size != other.size || this.size != target.size) { + throw RuntimeException("Invalid array sizes, this ${this.size}, other ${other.size}") + } + target.mapIndexed { index, _ -> this[index] xor other[index]} + } + fun argonBlake2bArbitraryLenghtHash(input: Array, length: UInt): Array { if (length <= 64U) { @@ -88,9 +94,11 @@ class Argon2 internal constructor( return concat } + fun compressionFunctionG(x: Array, y: Array): Array { - val r = Array(1024) { 0U } // view as 8x8 matrix of 16 byte registers - x.forEachIndexed { index, it -> r[index] = it xor y[index] } + val r = x xor y +// val r = Array(1024) { 0U } // view as 8x8 matrix of 16 byte registers +// x.forEachIndexed { index, it -> r[index] = it xor y[index] } // R = X xor Y val q = Array(1024) { 0U } val z = Array(1024) { 0U } // Do the argon/blake2b mixing on rows @@ -115,7 +123,7 @@ class Argon2 internal constructor( ) } // Z = Z xor R - r.forEachIndexed { index, it -> z[index] = it xor z[index] } + z.xor(z, r) return z } @@ -168,19 +176,23 @@ class Argon2 internal constructor( } private fun computeIndexes( - block: Array>>, - pass: Long, - lane: Int, - column: Int, - blockCount: UInt, - iterationCount: UInt, - type: ArgonType, - laneCounter : Int - + indexContext: IndexContext, + matrix : Array>> ): Pair { + val block = indexContext.indexMatrix + val parallelism = indexContext.parallelism + val pass = indexContext.pass + val lane = indexContext.lane + val column = indexContext.column + val blockCount = indexContext.blockCount + val iterationCount = indexContext.iterationCount + val type = indexContext.type + val laneCounter = indexContext.laneCounter + var counter = laneCounter val sliceNumber = column / 4 val sliceLength = blockCount / 4U + val (j1, j2) = when (type) { ArgonType.Argon2i -> { val firstPass = compressionFunctionG( @@ -205,36 +217,43 @@ class Argon2 internal constructor( counter.toUInt().toLittleEndianUByteArray() + Array(968) { 0U } ) - Pair(firstPass, secondPass) + Pair(1U, 1U) } ArgonType.Argon2d -> { Pair( - (block[laneCounter][column - 1].sliceArray(0..3).fromLittleEndianArrayToUInt()), - (block[laneCounter][column - 1].sliceArray(4..7).fromLittleEndianArrayToUInt()) + (matrix[laneCounter][column - 1].sliceArray(0..3).fromLittleEndianArrayToUInt()), + (matrix[laneCounter][column - 1].sliceArray(4..7).fromLittleEndianArrayToUInt()) ) } ArgonType.Argon2id -> { - Pair(emptyArray(), emptyArray()) + Pair(1U, 1U) } } + val l = if (pass == 0L && sliceNumber == 0) { + 2U + } else { + j2 % parallelism + } + +// val availableIndices = if () + + return Pair(1, 1) } - fun populateSegment( - matrix: Array>>, - pass: Long, - lane: Int, - column: Int, - blockCount: UInt, - iterationCount: UInt, - type: ArgonType, - laneCounter : Int - ) { - //TODO handle segment by segment - } - + data class IndexContext( + val indexMatrix: Array, + val parallelism: UInt, + val pass: Long, + val lane: Int, + val column: Int, + val blockCount: UInt, + val iterationCount: UInt, + val type: ArgonType, + val laneCounter: Int + ) internal fun derive( password: Array, @@ -257,11 +276,11 @@ class Argon2 internal constructor( associatedData.size.toUInt().toLittleEndianUByteArray() + associatedData ) - val blockCount = (memorySize / (4U * parallelism)) * (4U * parallelism) // + val blockCount = (memorySize / (4U * parallelism)) * (4U * parallelism) // TODO hmmm val columnCount = blockCount / parallelism //TODO pass handling - val allPasses = (0 .. numberOfIterations.toLong()).map { pass -> + val allPasses = (0..numberOfIterations.toLong()).map { pass -> //Allocate memory as Array of parallelism rows and columnCount colums val matrix = Array(parallelism.toInt()) { Array(columnCount.toInt()) { @@ -291,7 +310,7 @@ class Argon2 internal constructor( for (j in 1..columnCount.toInt()) { val counter = 0 //TODO handle counter - computeIndexes(matrix, pass, i, j, blockCount, numberOfIterations, type) + computeIndexes(matrix, parallelism, pass, i, j, blockCount, numberOfIterations, type) val iPrim = -1 val jPrim = -1 matrix[i][j] = compressionFunctionG(matrix[i][j - 1], matrix[iPrim][jPrim]) diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/util/Util.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/util/Util.kt index 795b180..e936bc8 100644 --- a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/util/Util.kt +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/util/Util.kt @@ -70,7 +70,7 @@ infix fun Array.xor(other : Array) : Array { if (this.size != other.size) { throw RuntimeException("Operands of different sizes are not supported yet") } - return this.copyOf().mapIndexed { index, it -> it xor other[index] }.toTypedArray() + return Array(this.size) { this[it] xor other [it]} } @ExperimentalUnsignedTypes @@ -141,22 +141,22 @@ fun Array.fromBigEndianArrayToULong() : ULong { } @ExperimentalUnsignedTypes -fun Array.fromLittleEndianArrayToUInt() : ULong { +fun Array.fromLittleEndianArrayToUInt() : UInt { if (this.size > 4) { throw RuntimeException("ore than 8 bytes in input, potential overflow") } - var ulong = this.foldIndexed(0UL) { index, acc, uByte -> acc or (uByte.toULong() shl (index * 8))} - return ulong + var uint = this.foldIndexed(0U) { index, acc, uByte -> acc or (uByte.toUInt() shl (index * 8))} + return uint } @ExperimentalUnsignedTypes -fun Array.fromBigEndianArrayToUInt() : ULong { +fun Array.fromBigEndianArrayToUInt() : UInt { if (this.size > 4) { throw RuntimeException("ore than 8 bytes in input, potential overflow") } - var ulong = this.foldIndexed(0UL) { index, acc, uByte -> acc or (uByte.toULong() shl (24 - (index * 8))) } - return ulong + var uint = this.foldIndexed(0U) { index, acc, uByte -> acc or (uByte.toUInt() shl (24 - (index * 8))) } + return uint } @ExperimentalUnsignedTypes