A bit of cleanup, a bit of profiling
This commit is contained in:
parent
2bbfefb56c
commit
7ce350825e
@ -134,7 +134,6 @@ class Blake2b(val key: UByteArray? = null, val hashLength: Int = 64) : Updatable
|
|||||||
v[13] = v[13] xor (offsetCounter shr BITS_IN_WORD).ulongValue()
|
v[13] = v[13] xor (offsetCounter shr BITS_IN_WORD).ulongValue()
|
||||||
|
|
||||||
if (finalBlock) {
|
if (finalBlock) {
|
||||||
// v[14] = v[14] xor 0xFFFFFFFFFFFFFFFFUL
|
|
||||||
v[14] = v[14].inv()
|
v[14] = v[14].inv()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import com.ionspin.kotlin.crypto.SRNG
|
|||||||
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b
|
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b
|
||||||
import com.ionspin.kotlin.crypto.keyderivation.KeyDerivationFunction
|
import com.ionspin.kotlin.crypto.keyderivation.KeyDerivationFunction
|
||||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.argonBlake2bArbitraryLenghtHash
|
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.argonBlake2bArbitraryLenghtHash
|
||||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.inplaceCompressionFunctionG
|
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.compressionFunctionG
|
||||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.validateArgonParameters
|
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.validateArgonParameters
|
||||||
import com.ionspin.kotlin.crypto.util.*
|
import com.ionspin.kotlin.crypto.util.*
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ class Argon2(
|
|||||||
): ArgonBlockPointer {
|
): ArgonBlockPointer {
|
||||||
//Calculate first pass
|
//Calculate first pass
|
||||||
val zeroesBlock = ArgonBlock()
|
val zeroesBlock = ArgonBlock()
|
||||||
val firstPass = inplaceCompressionFunctionG(
|
val firstPass = compressionFunctionG(
|
||||||
zeroesBlock.getBlockPointer(),
|
zeroesBlock.getBlockPointer(),
|
||||||
ArgonBlock(iteration.toULong().toLittleEndianUByteArray() +
|
ArgonBlock(iteration.toULong().toLittleEndianUByteArray() +
|
||||||
lane.toULong().toLittleEndianUByteArray() +
|
lane.toULong().toLittleEndianUByteArray() +
|
||||||
@ -175,7 +175,7 @@ class Argon2(
|
|||||||
addressBlock,
|
addressBlock,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
val secondPass = inplaceCompressionFunctionG(
|
val secondPass = compressionFunctionG(
|
||||||
zeroesBlock.getBlockPointer(),
|
zeroesBlock.getBlockPointer(),
|
||||||
firstPass,
|
firstPass,
|
||||||
firstPass,
|
firstPass,
|
||||||
@ -330,7 +330,7 @@ class Argon2(
|
|||||||
accPointer.xorInplaceWith(matrix.getBlockPointer(i, columnCount - 1))
|
accPointer.xorInplaceWith(matrix.getBlockPointer(i, columnCount - 1))
|
||||||
}
|
}
|
||||||
//Hash the xored last blocks
|
//Hash the xored last blocks
|
||||||
val hash = argonBlake2bArbitraryLenghtHash(acc.getAsUByteArray(), tagLength)
|
val hash = argonBlake2bArbitraryLenghtHash(acc.storage, tagLength)
|
||||||
matrix.clearMatrix()
|
matrix.clearMatrix()
|
||||||
return hash
|
return hash
|
||||||
|
|
||||||
@ -391,7 +391,7 @@ class Argon2(
|
|||||||
)
|
)
|
||||||
|
|
||||||
matrix.setBlockAt(lane, column,
|
matrix.setBlockAt(lane, column,
|
||||||
inplaceCompressionFunctionG(
|
compressionFunctionG(
|
||||||
matrix.getBlockPointer(lane, previousColumn),
|
matrix.getBlockPointer(lane, previousColumn),
|
||||||
matrix.getBlockPointer(l,z),
|
matrix.getBlockPointer(l,z),
|
||||||
matrix.getBlockPointer(lane,column),
|
matrix.getBlockPointer(lane,column),
|
||||||
|
@ -38,6 +38,7 @@ object Argon2Utils {
|
|||||||
const val R3 = 16
|
const val R3 = 16
|
||||||
const val R4 = 63
|
const val R4 = 63
|
||||||
|
|
||||||
|
//Based on Blake2b mix
|
||||||
internal fun inplaceMixRound(v : ULongArray) : ULongArray{
|
internal fun inplaceMixRound(v : ULongArray) : ULongArray{
|
||||||
mix(v, 0, 4, 8, 12)
|
mix(v, 0, 4, 8, 12)
|
||||||
mix(v, 1, 5, 9, 13)
|
mix(v, 1, 5, 9, 13)
|
||||||
@ -47,38 +48,7 @@ object Argon2Utils {
|
|||||||
mix(v, 1, 6, 11, 12)
|
mix(v, 1, 6, 11, 12)
|
||||||
mix(v, 2, 7, 8, 13)
|
mix(v, 2, 7, 8, 13)
|
||||||
mix(v, 3, 4, 9, 14)
|
mix(v, 3, 4, 9, 14)
|
||||||
return v //Just for chaining, array is already mixed
|
return v //Just for chaining, array is mixed in place
|
||||||
}
|
|
||||||
|
|
||||||
//based on Blake2b mixRound
|
|
||||||
internal fun mixRound(input: UByteArray): Array<ULong> {
|
|
||||||
var v = input.arrayChunked(8).map { it.fromLittleEndianArrayToULong() }.toTypedArray()
|
|
||||||
v = mix(v, 0, 4, 8, 12)
|
|
||||||
v = mix(v, 1, 5, 9, 13)
|
|
||||||
v = mix(v, 2, 6, 10, 14)
|
|
||||||
v = mix(v, 3, 7, 11, 15)
|
|
||||||
v = mix(v, 0, 5, 10, 15)
|
|
||||||
v = mix(v, 1, 6, 11, 12)
|
|
||||||
v = mix(v, 2, 7, 8, 13)
|
|
||||||
v = mix(v, 3, 4, 9, 14)
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun inPlaceMix(v: UByteArray, a: Int, b: Int, c: Int, d: Int) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//Based on Blake2b mix
|
|
||||||
private fun mix(v: Array<ULong>, a: Int, b: Int, c: Int, d: Int): Array<ULong> {
|
|
||||||
v[a] = (v[a] + v[b] + 2U * (v[a] and 0xFFFFFFFFUL) * (v[b] and 0xFFFFFFFFUL))
|
|
||||||
v[d] = (v[d] xor v[a]) rotateRight R1
|
|
||||||
v[c] = (v[c] + v[d] + 2U * (v[c] and 0xFFFFFFFFUL) * (v[d] and 0xFFFFFFFFUL))
|
|
||||||
v[b] = (v[b] xor v[c]) rotateRight R2
|
|
||||||
v[a] = (v[a] + v[b] + 2U * (v[a] and 0xFFFFFFFFUL) * (v[b] and 0xFFFFFFFFUL))
|
|
||||||
v[d] = (v[d] xor v[a]) rotateRight R3
|
|
||||||
v[c] = (v[c] + v[d] + 2U * (v[c] and 0xFFFFFFFFUL) * (v[d] and 0xFFFFFFFFUL))
|
|
||||||
v[b] = (v[b] xor v[c]) rotateRight R4
|
|
||||||
return v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Based on Blake2b mix
|
//Based on Blake2b mix
|
||||||
@ -102,14 +72,9 @@ object Argon2Utils {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun copyIntoGBlockColumn(gBlock: UByteArray, columnPosition: Int, columnData: UByteArray) {
|
|
||||||
for (i in 0..7) {
|
|
||||||
val column = columnData.copyOfRange(i * 16, i * 16 + 16)
|
|
||||||
column.copyInto(gBlock, i * 128 + columnPosition * 16)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun inplaceCompressionFunctionG(
|
|
||||||
|
internal fun compressionFunctionG(
|
||||||
previousBlock: ArgonBlockPointer,
|
previousBlock: ArgonBlockPointer,
|
||||||
referenceBlock: ArgonBlockPointer,
|
referenceBlock: ArgonBlockPointer,
|
||||||
currentBlock: ArgonBlockPointer,
|
currentBlock: ArgonBlockPointer,
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
package com.ionspin.kotlin.crypto.keyderivation.argon2
|
package com.ionspin.kotlin.crypto.keyderivation.argon2
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.util.xor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a pointer to a Argon2 Block, this abstracts what the backing structure is, a Argon 2 Matrix or
|
* Represents a pointer to a Argon2 Block, this abstracts what the backing structure is, a Argon 2 Matrix or
|
||||||
* or a UByteArray block
|
* or a UByteArray block
|
||||||
@ -34,7 +36,7 @@ interface ArgonBlockPointer {
|
|||||||
operator fun set(blockPosition: Int, value: UByte)
|
operator fun set(blockPosition: Int, value: UByte)
|
||||||
|
|
||||||
infix fun xorInplaceWith(other: ArgonBlockPointer) : ArgonBlockPointer {
|
infix fun xorInplaceWith(other: ArgonBlockPointer) : ArgonBlockPointer {
|
||||||
(0 until 1024).forEach {
|
for (it in 0 until 1024) {
|
||||||
this[it] = this[it] xor other[it]
|
this[it] = this[it] xor other[it]
|
||||||
}
|
}
|
||||||
return this //For chaining
|
return this //For chaining
|
||||||
@ -171,7 +173,6 @@ fun ArgonBlockPointer.getUIntFromPosition(positionInBlock: Int) : UInt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setBlockAt(rowPosition: Int, columnPosition: Int, blockValue: UByteArray) {
|
fun setBlockAt(rowPosition: Int, columnPosition: Int, blockValue: UByteArray) {
|
||||||
println("Expensive set")
|
|
||||||
blockValue.copyInto(
|
blockValue.copyInto(
|
||||||
storage,
|
storage,
|
||||||
getBlockStartPositionPointer(rowPosition, columnPosition)
|
getBlockStartPositionPointer(rowPosition, columnPosition)
|
||||||
@ -271,7 +272,7 @@ inline class ArgonBlock internal constructor(internal val storage: UByteArray) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getAsUByteArray(): UByteArray {
|
override fun getAsUByteArray(): UByteArray {
|
||||||
return storageBlock.storage.slice(blockStartPosition until blockStartPosition + 1024).toUByteArray()
|
return storageBlock.storage
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,12 @@ import com.ionspin.kotlin.crypto.hash.sha.Sha256
|
|||||||
import com.ionspin.kotlin.crypto.hash.sha.Sha512
|
import com.ionspin.kotlin.crypto.hash.sha.Sha512
|
||||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2
|
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2
|
||||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType
|
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType
|
||||||
|
import com.ionspin.kotlin.crypto.util.testBlocking
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
import kotlin.time.ExperimentalTime
|
||||||
|
import kotlin.time.measureTime
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ugljesa Jovanovic
|
* Created by Ugljesa Jovanovic
|
||||||
@ -127,25 +130,28 @@ class ReadmeTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExperimentalTime
|
||||||
@Test
|
@Test
|
||||||
fun argon2StringExample() {
|
fun argon2StringExample() = testBlocking {
|
||||||
val argon2Instance = Argon2(
|
val argon2Instance = Argon2(
|
||||||
password = "Password",
|
password = "Password",
|
||||||
salt = "RandomSalt",
|
salt = "RandomSalt",
|
||||||
parallelism = 4,
|
parallelism = 1,
|
||||||
tagLength = 64U,
|
tagLength = 64U,
|
||||||
requestedMemorySize = 32U, //Travis build on mac fails with higher values
|
requestedMemorySize = 4096U, //Travis build on mac fails with higher values
|
||||||
numberOfIterations = 4,
|
numberOfIterations = 100,
|
||||||
key = "",
|
key = "",
|
||||||
associatedData = "",
|
associatedData = "",
|
||||||
argonType = ArgonType.Argon2id
|
argonType = ArgonType.Argon2id
|
||||||
)
|
)
|
||||||
|
val time = measureTime {
|
||||||
val tag = argon2Instance.derive()
|
val tag = argon2Instance.derive()
|
||||||
val tagString = tag.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "")
|
val tagString = tag.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "")
|
||||||
val expectedTagString = "ca134003c9f9f76ca8869359c1d9065603ec54ac30f5158f06af647cacaef2c1c3e" +
|
val expectedTagString = "27c61b6538ef9f4a1250f8712cac09fc4329969295f9440249437d38c1617a005c2702d76a8a59e4cda2dfba48e1132261dacdfd31296945906992ea32f1d06e"
|
||||||
"c71e81960278c0596febc64125acbbe5959146db1c128199a1b7cb38982a9"
|
|
||||||
println("Tag: ${tagString}")
|
println("Tag: ${tagString}")
|
||||||
assertEquals(tagString, expectedTagString)
|
assertEquals(tagString, expectedTagString)
|
||||||
|
}
|
||||||
|
println("Time $time")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ package com.ionspin.kotlin.crypto.hash.argon
|
|||||||
|
|
||||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils
|
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils
|
||||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonBlock
|
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonBlock
|
||||||
|
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToULong
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
import kotlin.random.nextUBytes
|
import kotlin.random.nextUBytes
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
@ -75,9 +76,10 @@ class Argon2Test {
|
|||||||
6500029010075826286U,
|
6500029010075826286U,
|
||||||
16957672821843227543U
|
16957672821843227543U
|
||||||
)
|
)
|
||||||
val result = Argon2Utils.mixRound(input)
|
val preparedInput = input.chunked(8).map { it.toTypedArray().fromLittleEndianArrayToULong() }.toULongArray()
|
||||||
|
val result = Argon2Utils.inplaceMixRound(preparedInput)
|
||||||
assertTrue {
|
assertTrue {
|
||||||
expected.contentEquals(result)
|
expected.contentEquals(result.toTypedArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -246,7 +248,7 @@ class Argon2Test {
|
|||||||
val randomBlock1 = ArgonBlock(randomBlockAsArray).getBlockPointer()
|
val randomBlock1 = ArgonBlock(randomBlockAsArray).getBlockPointer()
|
||||||
val randomBlock2 = ArgonBlock(randomBlockAsArray2).getBlockPointer()
|
val randomBlock2 = ArgonBlock(randomBlockAsArray2).getBlockPointer()
|
||||||
val randomBlock3 = ArgonBlock(randomBlockAsArray3).getBlockPointer()
|
val randomBlock3 = ArgonBlock(randomBlockAsArray3).getBlockPointer()
|
||||||
val resultWithoutXorAndAllocations = Argon2Utils.inplaceCompressionFunctionG(randomBlock1, randomBlock2, randomBlock3, false)
|
val resultWithoutXorAndAllocations = Argon2Utils.compressionFunctionG(randomBlock1, randomBlock2, randomBlock3, false)
|
||||||
assertTrue {
|
assertTrue {
|
||||||
expectedWithoutXor.contentEquals(resultWithoutXorAndAllocations.getAsUByteArray())
|
expectedWithoutXor.contentEquals(resultWithoutXorAndAllocations.getAsUByteArray())
|
||||||
}
|
}
|
||||||
@ -391,7 +393,7 @@ class Argon2Test {
|
|||||||
val randomBlock1 = ArgonBlock(randomBlockAsArray).getBlockPointer()
|
val randomBlock1 = ArgonBlock(randomBlockAsArray).getBlockPointer()
|
||||||
val randomBlock2 = ArgonBlock(randomBlockAsArray2).getBlockPointer()
|
val randomBlock2 = ArgonBlock(randomBlockAsArray2).getBlockPointer()
|
||||||
val randomBlock3 = ArgonBlock(randomBlockAsArray3).getBlockPointer()
|
val randomBlock3 = ArgonBlock(randomBlockAsArray3).getBlockPointer()
|
||||||
val resultWithoutXorAndAllocations = Argon2Utils.inplaceCompressionFunctionG(randomBlock1, randomBlock2, randomBlock3, true)
|
val resultWithoutXorAndAllocations = Argon2Utils.compressionFunctionG(randomBlock1, randomBlock2, randomBlock3, true)
|
||||||
assertTrue {
|
assertTrue {
|
||||||
expectedWithXor.contentEquals(resultWithoutXorAndAllocations.getAsUByteArray())
|
expectedWithXor.contentEquals(resultWithoutXorAndAllocations.getAsUByteArray())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user