Continuing Argon 2 work

This commit is contained in:
Ugljesa Jovanovic 2020-05-10 11:11:09 +02:00 committed by Ugljesa Jovanovic
parent 803288cbc4
commit 1e0a5b516e
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
3 changed files with 63 additions and 41 deletions

View File

@ -312,6 +312,9 @@ kotlin {
val linuxArm64Test by getting { val linuxArm64Test by getting {
dependsOn(nativeTest) dependsOn(nativeTest)
} }
all {
languageSettings.enableLanguageFeature("InlineClasses")
}
} }

View File

@ -13,12 +13,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.ionspin.kotlin.crypto.keyderivation package com.ionspin.kotlin.crypto.keyderivation
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b
import com.ionspin.kotlin.crypto.util.* import com.ionspin.kotlin.crypto.util.*
/** /**
* *
* Further resources and examples of implementation: * Further resources and examples of implementation:
@ -63,9 +61,17 @@ class Argon2 internal constructor(
} }
@ExperimentalStdlibApi @ExperimentalStdlibApi
companion object { companion object {
fun Array<UByte>.xor(target : Array<UByte>, other : Array<UByte>) {
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<UByte>, length: UInt): Array<UByte> { fun argonBlake2bArbitraryLenghtHash(input: Array<UByte>, length: UInt): Array<UByte> {
if (length <= 64U) { if (length <= 64U) {
@ -88,9 +94,11 @@ class Argon2 internal constructor(
return concat return concat
} }
fun compressionFunctionG(x: Array<UByte>, y: Array<UByte>): Array<UByte> { fun compressionFunctionG(x: Array<UByte>, y: Array<UByte>): Array<UByte> {
val r = Array<UByte>(1024) { 0U } // view as 8x8 matrix of 16 byte registers val r = x xor y
x.forEachIndexed { index, it -> r[index] = it xor y[index] } // val r = Array<UByte>(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<UByte>(1024) { 0U } val q = Array<UByte>(1024) { 0U }
val z = Array<UByte>(1024) { 0U } val z = Array<UByte>(1024) { 0U }
// Do the argon/blake2b mixing on rows // Do the argon/blake2b mixing on rows
@ -115,7 +123,7 @@ class Argon2 internal constructor(
) )
} }
// Z = Z xor R // Z = Z xor R
r.forEachIndexed { index, it -> z[index] = it xor z[index] } z.xor(z, r)
return z return z
} }
@ -168,19 +176,23 @@ class Argon2 internal constructor(
} }
private fun computeIndexes( private fun computeIndexes(
block: Array<Array<Array<UByte>>>, indexContext: IndexContext,
pass: Long, matrix : Array<Array<Array<UByte>>>
lane: Int,
column: Int,
blockCount: UInt,
iterationCount: UInt,
type: ArgonType,
laneCounter : Int
): Pair<Int, Int> { ): Pair<Int, Int> {
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 var counter = laneCounter
val sliceNumber = column / 4 val sliceNumber = column / 4
val sliceLength = blockCount / 4U val sliceLength = blockCount / 4U
val (j1, j2) = when (type) { val (j1, j2) = when (type) {
ArgonType.Argon2i -> { ArgonType.Argon2i -> {
val firstPass = compressionFunctionG( val firstPass = compressionFunctionG(
@ -205,36 +217,43 @@ class Argon2 internal constructor(
counter.toUInt().toLittleEndianUByteArray() + counter.toUInt().toLittleEndianUByteArray() +
Array<UByte>(968) { 0U } Array<UByte>(968) { 0U }
) )
Pair(firstPass, secondPass) Pair(1U, 1U)
} }
ArgonType.Argon2d -> { ArgonType.Argon2d -> {
Pair( Pair(
(block[laneCounter][column - 1].sliceArray(0..3).fromLittleEndianArrayToUInt()), (matrix[laneCounter][column - 1].sliceArray(0..3).fromLittleEndianArrayToUInt()),
(block[laneCounter][column - 1].sliceArray(4..7).fromLittleEndianArrayToUInt()) (matrix[laneCounter][column - 1].sliceArray(4..7).fromLittleEndianArrayToUInt())
) )
} }
ArgonType.Argon2id -> { ArgonType.Argon2id -> {
Pair(emptyArray<UByte>(), emptyArray<UByte>()) Pair(1U, 1U)
} }
} }
val l = if (pass == 0L && sliceNumber == 0) {
2U
} else {
j2 % parallelism
}
// val availableIndices = if ()
return Pair(1, 1) return Pair(1, 1)
} }
fun populateSegment( data class IndexContext(
matrix: Array<Array<Array<UByte>>>, val indexMatrix: Array<UByte>,
pass: Long, val parallelism: UInt,
lane: Int, val pass: Long,
column: Int, val lane: Int,
blockCount: UInt, val column: Int,
iterationCount: UInt, val blockCount: UInt,
type: ArgonType, val iterationCount: UInt,
laneCounter : Int val type: ArgonType,
) { val laneCounter: Int
//TODO handle segment by segment )
}
internal fun derive( internal fun derive(
password: Array<UByte>, password: Array<UByte>,
@ -257,11 +276,11 @@ class Argon2 internal constructor(
associatedData.size.toUInt().toLittleEndianUByteArray() + associatedData 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 val columnCount = blockCount / parallelism
//TODO pass handling //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 //Allocate memory as Array of parallelism rows and columnCount colums
val matrix = Array(parallelism.toInt()) { val matrix = Array(parallelism.toInt()) {
Array(columnCount.toInt()) { Array(columnCount.toInt()) {
@ -291,7 +310,7 @@ class Argon2 internal constructor(
for (j in 1..columnCount.toInt()) { for (j in 1..columnCount.toInt()) {
val counter = 0 //TODO handle counter 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 iPrim = -1
val jPrim = -1 val jPrim = -1
matrix[i][j] = compressionFunctionG(matrix[i][j - 1], matrix[iPrim][jPrim]) matrix[i][j] = compressionFunctionG(matrix[i][j - 1], matrix[iPrim][jPrim])

View File

@ -70,7 +70,7 @@ infix fun Array<UByte>.xor(other : Array<UByte>) : Array<UByte> {
if (this.size != other.size) { if (this.size != other.size) {
throw RuntimeException("Operands of different sizes are not supported yet") 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 @ExperimentalUnsignedTypes
@ -141,22 +141,22 @@ fun Array<UByte>.fromBigEndianArrayToULong() : ULong {
} }
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun Array<UByte>.fromLittleEndianArrayToUInt() : ULong { fun Array<UByte>.fromLittleEndianArrayToUInt() : UInt {
if (this.size > 4) { if (this.size > 4) {
throw RuntimeException("ore than 8 bytes in input, potential overflow") 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))} var uint = this.foldIndexed(0U) { index, acc, uByte -> acc or (uByte.toUInt() shl (index * 8))}
return ulong return uint
} }
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
fun Array<UByte>.fromBigEndianArrayToUInt() : ULong { fun Array<UByte>.fromBigEndianArrayToUInt() : UInt {
if (this.size > 4) { if (this.size > 4) {
throw RuntimeException("ore than 8 bytes in input, potential overflow") 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))) } var uint = this.foldIndexed(0U) { index, acc, uByte -> acc or (uByte.toUInt() shl (24 - (index * 8))) }
return ulong return uint
} }
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes