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()
 | 
			
		||||
 | 
			
		||||
            if (finalBlock) {
 | 
			
		||||
//            v[14] = v[14] xor 0xFFFFFFFFFFFFFFFFUL
 | 
			
		||||
                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.keyderivation.KeyDerivationFunction
 | 
			
		||||
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.util.*
 | 
			
		||||
 | 
			
		||||
@ -161,7 +161,7 @@ class Argon2(
 | 
			
		||||
    ): ArgonBlockPointer {
 | 
			
		||||
        //Calculate first pass
 | 
			
		||||
        val zeroesBlock = ArgonBlock()
 | 
			
		||||
        val firstPass = inplaceCompressionFunctionG(
 | 
			
		||||
        val firstPass = compressionFunctionG(
 | 
			
		||||
            zeroesBlock.getBlockPointer(),
 | 
			
		||||
            ArgonBlock(iteration.toULong().toLittleEndianUByteArray() +
 | 
			
		||||
                    lane.toULong().toLittleEndianUByteArray() +
 | 
			
		||||
@ -175,7 +175,7 @@ class Argon2(
 | 
			
		||||
            addressBlock,
 | 
			
		||||
            false
 | 
			
		||||
        )
 | 
			
		||||
        val secondPass = inplaceCompressionFunctionG(
 | 
			
		||||
        val secondPass = compressionFunctionG(
 | 
			
		||||
            zeroesBlock.getBlockPointer(),
 | 
			
		||||
            firstPass,
 | 
			
		||||
            firstPass,
 | 
			
		||||
@ -330,7 +330,7 @@ class Argon2(
 | 
			
		||||
            accPointer.xorInplaceWith(matrix.getBlockPointer(i, columnCount - 1))
 | 
			
		||||
        }
 | 
			
		||||
        //Hash the xored last blocks
 | 
			
		||||
        val hash = argonBlake2bArbitraryLenghtHash(acc.getAsUByteArray(), tagLength)
 | 
			
		||||
        val hash = argonBlake2bArbitraryLenghtHash(acc.storage, tagLength)
 | 
			
		||||
        matrix.clearMatrix()
 | 
			
		||||
        return hash
 | 
			
		||||
 | 
			
		||||
@ -391,7 +391,7 @@ class Argon2(
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            matrix.setBlockAt(lane, column,
 | 
			
		||||
                inplaceCompressionFunctionG(
 | 
			
		||||
                compressionFunctionG(
 | 
			
		||||
                    matrix.getBlockPointer(lane, previousColumn),
 | 
			
		||||
                    matrix.getBlockPointer(l,z),
 | 
			
		||||
                    matrix.getBlockPointer(lane,column),
 | 
			
		||||
 | 
			
		||||
@ -38,6 +38,7 @@ object Argon2Utils {
 | 
			
		||||
    const val R3 = 16
 | 
			
		||||
    const val R4 = 63
 | 
			
		||||
 | 
			
		||||
    //Based on Blake2b mix
 | 
			
		||||
    internal fun inplaceMixRound(v : ULongArray) : ULongArray{
 | 
			
		||||
        mix(v, 0, 4, 8, 12)
 | 
			
		||||
        mix(v, 1, 5, 9, 13)
 | 
			
		||||
@ -47,38 +48,7 @@ object Argon2Utils {
 | 
			
		||||
        mix(v, 1, 6, 11, 12)
 | 
			
		||||
        mix(v, 2, 7, 8, 13)
 | 
			
		||||
        mix(v, 3, 4, 9, 14)
 | 
			
		||||
        return v //Just for chaining, array is already mixed
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //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
 | 
			
		||||
        return v //Just for chaining, array is mixed in place
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //Based on Blake2b mix
 | 
			
		||||
@ -102,14 +72,9 @@ object Argon2Utils {
 | 
			
		||||
        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,
 | 
			
		||||
        referenceBlock: ArgonBlockPointer,
 | 
			
		||||
        currentBlock: ArgonBlockPointer,
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,8 @@
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 * or a UByteArray block
 | 
			
		||||
@ -34,7 +36,7 @@ interface ArgonBlockPointer {
 | 
			
		||||
    operator fun set(blockPosition: Int, value: UByte)
 | 
			
		||||
 | 
			
		||||
    infix fun xorInplaceWith(other: ArgonBlockPointer) : ArgonBlockPointer {
 | 
			
		||||
        (0 until 1024).forEach {
 | 
			
		||||
        for (it in 0 until 1024) {
 | 
			
		||||
            this[it] = this[it] xor other[it]
 | 
			
		||||
        }
 | 
			
		||||
        return this //For chaining
 | 
			
		||||
@ -171,7 +173,6 @@ fun ArgonBlockPointer.getUIntFromPosition(positionInBlock: Int) : UInt {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun setBlockAt(rowPosition: Int, columnPosition: Int, blockValue: UByteArray) {
 | 
			
		||||
        println("Expensive set")
 | 
			
		||||
        blockValue.copyInto(
 | 
			
		||||
            storage,
 | 
			
		||||
            getBlockStartPositionPointer(rowPosition, columnPosition)
 | 
			
		||||
@ -271,7 +272,7 @@ inline class ArgonBlock internal constructor(internal val storage: 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.keyderivation.argon2.Argon2
 | 
			
		||||
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType
 | 
			
		||||
import com.ionspin.kotlin.crypto.util.testBlocking
 | 
			
		||||
import kotlin.test.Test
 | 
			
		||||
import kotlin.test.assertEquals
 | 
			
		||||
import kotlin.test.assertTrue
 | 
			
		||||
import kotlin.time.ExperimentalTime
 | 
			
		||||
import kotlin.time.measureTime
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Created by Ugljesa Jovanovic
 | 
			
		||||
@ -127,25 +130,28 @@ class ReadmeTest {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ExperimentalTime
 | 
			
		||||
    @Test
 | 
			
		||||
    fun argon2StringExample() {
 | 
			
		||||
    fun argon2StringExample() = testBlocking {
 | 
			
		||||
        val argon2Instance = Argon2(
 | 
			
		||||
            password = "Password",
 | 
			
		||||
            salt = "RandomSalt",
 | 
			
		||||
            parallelism = 4,
 | 
			
		||||
            parallelism = 1,
 | 
			
		||||
            tagLength = 64U,
 | 
			
		||||
            requestedMemorySize = 32U, //Travis build on mac fails with higher values
 | 
			
		||||
            numberOfIterations = 4,
 | 
			
		||||
            requestedMemorySize = 4096U, //Travis build on mac fails with higher values
 | 
			
		||||
            numberOfIterations = 100,
 | 
			
		||||
            key = "",
 | 
			
		||||
            associatedData = "",
 | 
			
		||||
            argonType = ArgonType.Argon2id
 | 
			
		||||
        )
 | 
			
		||||
        val tag = argon2Instance.derive()
 | 
			
		||||
        val tagString = tag.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "")
 | 
			
		||||
        val expectedTagString = "ca134003c9f9f76ca8869359c1d9065603ec54ac30f5158f06af647cacaef2c1c3e" +
 | 
			
		||||
                "c71e81960278c0596febc64125acbbe5959146db1c128199a1b7cb38982a9"
 | 
			
		||||
        println("Tag: ${tagString}")
 | 
			
		||||
        assertEquals(tagString, expectedTagString)
 | 
			
		||||
        val time = measureTime {
 | 
			
		||||
            val tag = argon2Instance.derive()
 | 
			
		||||
            val tagString = tag.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "")
 | 
			
		||||
            val expectedTagString = "27c61b6538ef9f4a1250f8712cac09fc4329969295f9440249437d38c1617a005c2702d76a8a59e4cda2dfba48e1132261dacdfd31296945906992ea32f1d06e"
 | 
			
		||||
            println("Tag: ${tagString}")
 | 
			
		||||
            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.ArgonBlock
 | 
			
		||||
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToULong
 | 
			
		||||
import kotlin.random.Random
 | 
			
		||||
import kotlin.random.nextUBytes
 | 
			
		||||
import kotlin.test.Test
 | 
			
		||||
@ -75,9 +76,10 @@ class Argon2Test {
 | 
			
		||||
            6500029010075826286U,
 | 
			
		||||
            16957672821843227543U
 | 
			
		||||
        )
 | 
			
		||||
        val result = Argon2Utils.mixRound(input)
 | 
			
		||||
        val preparedInput = input.chunked(8).map { it.toTypedArray().fromLittleEndianArrayToULong() }.toULongArray()
 | 
			
		||||
        val result = Argon2Utils.inplaceMixRound(preparedInput)
 | 
			
		||||
        assertTrue {
 | 
			
		||||
            expected.contentEquals(result)
 | 
			
		||||
            expected.contentEquals(result.toTypedArray())
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
@ -246,7 +248,7 @@ class Argon2Test {
 | 
			
		||||
        val randomBlock1 = ArgonBlock(randomBlockAsArray).getBlockPointer()
 | 
			
		||||
        val randomBlock2 = ArgonBlock(randomBlockAsArray2).getBlockPointer()
 | 
			
		||||
        val randomBlock3 = ArgonBlock(randomBlockAsArray3).getBlockPointer()
 | 
			
		||||
        val resultWithoutXorAndAllocations = Argon2Utils.inplaceCompressionFunctionG(randomBlock1, randomBlock2, randomBlock3, false)
 | 
			
		||||
        val resultWithoutXorAndAllocations = Argon2Utils.compressionFunctionG(randomBlock1, randomBlock2, randomBlock3, false)
 | 
			
		||||
        assertTrue {
 | 
			
		||||
            expectedWithoutXor.contentEquals(resultWithoutXorAndAllocations.getAsUByteArray())
 | 
			
		||||
        }
 | 
			
		||||
@ -391,7 +393,7 @@ class Argon2Test {
 | 
			
		||||
        val randomBlock1 = ArgonBlock(randomBlockAsArray).getBlockPointer()
 | 
			
		||||
        val randomBlock2 = ArgonBlock(randomBlockAsArray2).getBlockPointer()
 | 
			
		||||
        val randomBlock3 = ArgonBlock(randomBlockAsArray3).getBlockPointer()
 | 
			
		||||
        val resultWithoutXorAndAllocations = Argon2Utils.inplaceCompressionFunctionG(randomBlock1, randomBlock2, randomBlock3, true)
 | 
			
		||||
        val resultWithoutXorAndAllocations = Argon2Utils.compressionFunctionG(randomBlock1, randomBlock2, randomBlock3, true)
 | 
			
		||||
        assertTrue {
 | 
			
		||||
            expectedWithXor.contentEquals(resultWithoutXorAndAllocations.getAsUByteArray())
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user