First steps

This commit is contained in:
Ugljesa Jovanovic authored and Ugljesa Jovanovic committed 2020-05-24 10:16:53 +02:00
1 parent aecad37e64
commit 9858eaa5fb
52 files changed
+5088 -526

No files matched your search

+1
View File
@@ -186,6 +186,7 @@ kotlin {
implementation(kotlin(Deps.Common.test))
implementation(Deps.Common.coroutines)
implementation(Deps.Common.kotlinBigNum)
implementation(project(":multiplatform-crypto-api"))
}
}
val commonTest by getting {
@@ -0,0 +1,14 @@
package com.ionspin.kotlin.crypto
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bPure
import com.ionspin.kotlin.crypto.hash.sha.Sha256Pure
import com.ionspin.kotlin.crypto.hash.sha.Sha512Pure
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 24-May-2020
*/
typealias Blake2bStateless = Blake2bPure.Companion
typealias Sha256Stateless = Sha256Pure.Companion
typealias Sha512Stateless = Sha512Pure.Companion
@@ -1,50 +0,0 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ionspin.kotlin.crypto.hash
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 20-Jul-2019
*/
interface Hash {
val MAX_HASH_BYTES : Int
}
@ExperimentalUnsignedTypes
interface UpdatableHash : Hash {
fun update(data : UByteArray)
fun update(data : String)
fun digest() : UByteArray
fun digestString() : String
}
@ExperimentalUnsignedTypes
interface StatelessHash : Hash {
fun digest(inputString: String, key: String? = null, hashLength: Int = MAX_HASH_BYTES): UByteArray
fun digest(
inputMessage: UByteArray = ubyteArrayOf(),
key: UByteArray = ubyteArrayOf(),
hashLength: Int = MAX_HASH_BYTES
): UByteArray
}
@@ -19,9 +19,6 @@ package com.ionspin.kotlin.crypto.hash.blake2b
import com.ionspin.kotlin.bignum.integer.BigInteger
import com.ionspin.kotlin.bignum.integer.toBigInteger
import com.ionspin.kotlin.crypto.*
import com.ionspin.kotlin.crypto.hash.StatelessHash
import com.ionspin.kotlin.crypto.hash.UpdatableHash
import com.ionspin.kotlin.crypto.util.chunked
import com.ionspin.kotlin.crypto.util.rotateRight
/**
@@ -31,9 +28,9 @@ import com.ionspin.kotlin.crypto.util.rotateRight
*/
@ExperimentalUnsignedTypes
class Blake2b(val key: UByteArray? = null, val hashLength: Int = 64) : UpdatableHash {
class Blake2bPure(val key: UByteArray? = null, val hashLength: Int = 64) : Blake2b {
companion object : StatelessHash {
companion object : Blake2bStatelessInterface {
//Hack start
//If this line is not included konanc 1.4-M1 fails to link because it cant find ByteArray which is
//a backing class for UByteArray
@@ -255,7 +252,7 @@ class Blake2b(val key: UByteArray? = null, val hashLength: Int = 64) : Updatable
requestedHashLenght
)
override val MAX_HASH_BYTES: Int = Blake2b.MAX_HASH_BYTES
override val MAX_HASH_BYTES: Int = Blake2bPure.MAX_HASH_BYTES
var h = iv.copyOf()
var counter = BigInteger.ZERO
@@ -16,7 +16,6 @@
package com.ionspin.kotlin.crypto.hash.sha
import com.ionspin.kotlin.crypto.util.chunked
import com.ionspin.kotlin.crypto.hash.StatelessHash
import com.ionspin.kotlin.crypto.hash.UpdatableHash
import com.ionspin.kotlin.crypto.util.rotateRight
@@ -30,12 +29,12 @@ import com.ionspin.kotlin.crypto.util.rotateRight
@ExperimentalUnsignedTypes
class Sha256 : UpdatableHash {
class Sha256Pure : Sha256 {
override val MAX_HASH_BYTES: Int = 32
companion object : StatelessHash {
companion object : StatelessSha256 {
const val BLOCK_SIZE = 512
const val BLOCK_SIZE_IN_BYTES = 64
const val UINT_MASK = 0xFFFFFFFFU
@@ -16,7 +16,6 @@
package com.ionspin.kotlin.crypto.hash.sha
import com.ionspin.kotlin.crypto.util.chunked
import com.ionspin.kotlin.crypto.hash.StatelessHash
import com.ionspin.kotlin.crypto.hash.UpdatableHash
import com.ionspin.kotlin.crypto.util.rotateRight
@@ -28,11 +27,11 @@ import com.ionspin.kotlin.crypto.util.rotateRight
*/
@ExperimentalUnsignedTypes
class Sha512 : UpdatableHash {
class Sha512Pure : Sha512 {
override val MAX_HASH_BYTES: Int = 32
companion object : StatelessHash {
companion object : StatelessSha512 {
const val BLOCK_SIZE = 1024
const val BLOCK_SIZE_IN_BYTES = 128
const val CHUNK_SIZE = 80
@@ -1,26 +0,0 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ionspin.kotlin.crypto.keyderivation
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 16-May-2020
*/
interface KeyDerivationFunction {
fun derive() : UByteArray
}
@@ -1,406 +1,10 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package com.ionspin.kotlin.crypto.keyderivation.argon2
import com.ionspin.kotlin.bignum.integer.toBigInteger
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.compressionFunctionG
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.validateArgonParameters
import com.ionspin.kotlin.crypto.util.*
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 16-May-2020
* on 24-May-2020
*/
enum class ArgonType(val typeId: Int) {
Argon2d(0), Argon2i(1), Argon2id(2)
}
data class SegmentPosition(
val iteration: Int,
val lane: Int,
val slice: Int
)
data class ArgonResult(
val hashBytes: UByteArray,
val salt: UByteArray
) {
val hashString by lazy { hashBytes.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "") }
val saltString by lazy { salt.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "") }
}
@ExperimentalStdlibApi
class Argon2(
private val password: UByteArray,
private val salt: UByteArray = ubyteArrayOf(),
private val parallelism: Int = 1,
private val tagLength: UInt = 64U,
requestedMemorySize: UInt = 0U,
private val numberOfIterations: Int = 1,
private val key: UByteArray = ubyteArrayOf(),
private val associatedData: UByteArray = ubyteArrayOf(),
private val argonType: ArgonType = ArgonType.Argon2id
) : KeyDerivationFunction {
companion object {
fun derive(
password: String,
salt: String? = null,
key: String,
associatedData: String,
parallelism: Int = 16,
tagLength: Int = 64,
memory: Int = 4096,
numberOfIterations: Int = 10,
): ArgonResult {
val salt = SRNG.getRandomBytes(64)
val argon = Argon2(
password.encodeToByteArray().toUByteArray(),
salt,
parallelism,
tagLength.toUInt(),
memory.toUInt(),
numberOfIterations,
key.encodeToByteArray().toUByteArray(),
associatedData.encodeToByteArray().toUByteArray(),
ArgonType.Argon2id
)
val resultArray = argon.derive()
return ArgonResult(resultArray, salt)
}
}
constructor(
password: String,
salt: String = "",
parallelism: Int = 1,
tagLength: UInt = 64U,
requestedMemorySize: UInt = 0U,
numberOfIterations: Int = 10,
key: String = "",
associatedData: String = "",
argonType: ArgonType = ArgonType.Argon2id
) : this(
password.encodeToByteArray().toUByteArray(),
salt.encodeToByteArray().toUByteArray(),
parallelism,
tagLength,
requestedMemorySize,
numberOfIterations,
key.encodeToByteArray().toUByteArray(),
associatedData.encodeToByteArray().toUByteArray(),
argonType
)
//We support only the latest version
private val versionNumber: UInt = 0x13U
//Use either requested memory size, or default, or throw exception if the requested amount is less than 8*parallelism
private val memorySize = if (requestedMemorySize == 0U) {
((8 * parallelism) * 2).toUInt()
} else {
requestedMemorySize
}
private val blockCount = (memorySize / (4U * parallelism.toUInt())) * (4U * parallelism.toUInt())
private val columnCount = (blockCount / parallelism.toUInt()).toInt()
private val segmentLength = columnCount / 4
private val useIndependentAddressing = argonType == ArgonType.Argon2id || argonType == ArgonType.Argon2i
// State
private val matrix: ArgonMatrix
init {
matrix = ArgonMatrix(columnCount, parallelism)
validateArgonParameters(
password,
salt,
parallelism,
tagLength,
requestedMemorySize,
numberOfIterations,
key,
associatedData,
argonType
)
}
private fun populateAddressBlock(
iteration: Int,
slice: Int,
lane: Int,
addressBlock: ArgonBlockPointer,
addressCounter: ULong
): ArgonBlockPointer {
//Calculate first pass
val zeroesBlock = ArgonBlock()
val firstPass = compressionFunctionG(
zeroesBlock.getBlockPointer(),
ArgonBlock(iteration.toULong().toLittleEndianUByteArray() +
lane.toULong().toLittleEndianUByteArray() +
slice.toULong().toLittleEndianUByteArray() +
blockCount.toULong().toLittleEndianUByteArray() +
numberOfIterations.toULong().toLittleEndianUByteArray() +
argonType.typeId.toULong().toLittleEndianUByteArray() +
addressCounter.toLittleEndianUByteArray() +
UByteArray(968) { 0U }
).getBlockPointer(),
addressBlock,
false
)
val secondPass = compressionFunctionG(
zeroesBlock.getBlockPointer(),
firstPass,
firstPass,
false
)
return secondPass
}
private fun computeReferenceBlockIndexes(
iteration: Int,
slice: Int,
lane: Int,
column: Int,
addressBlockPointer: ArgonBlockPointer?
): 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 previousBlockStart = if (column == 0) {
matrix.getBlockPointer(lane, columnCount - 1) //Get last block in the SAME lane
} else {
matrix.getBlockPointer(lane, column - 1)
}
val first32Bit = matrix.sliceArray(previousBlockStart.asInt() until previousBlockStart.asInt() + 4).fromLittleEndianArrayToUInt()
val second32Bit = matrix.sliceArray(previousBlockStart.asInt() + 4 until previousBlockStart.asInt() + 8).fromLittleEndianArrayToUInt()
Pair(first32Bit, second32Bit)
}
ArgonType.Argon2i -> {
val first32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8)
val second32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8 + 4)
Pair(first32Bit, second32Bit)
}
ArgonType.Argon2id -> {
if (iteration == 0 && (slice == 0 || slice == 1)) {
val first32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8)
val second32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8 + 4)
Pair(first32Bit, second32Bit)
} else {
val previousBlockStart = if (column == 0) {
matrix.getBlockPointer(lane, columnCount - 1) //Get last block in the SAME lane
} else {
matrix.getBlockPointer(lane, column - 1)
}
val first32Bit = matrix.sliceArray(previousBlockStart.asInt() until previousBlockStart.asInt() + 4).fromLittleEndianArrayToUInt()
val second32Bit = matrix.sliceArray(previousBlockStart.asInt() + 4 until previousBlockStart.asInt() + 8).fromLittleEndianArrayToUInt()
Pair(first32Bit, second32Bit)
}
}
}
//If this is first iteration and first slice, block is taken from the current lane
val l = if (iteration == 0 && slice == 0) {
lane
} else {
(j2.toBigInteger() % parallelism).intValue()
}
val referenceAreaSize = if (iteration == 0) {
if (slice == 0) {
//All indices except the previous
segmentIndex - 1
} else {
if (lane == l) {
//Same lane
column - 1
} else {
slice * (columnCount / 4) + if (segmentIndex == 0) { // Check if column is first block of the SEGMENT
-1
} else {
0
}
}
}
} else {
if (lane == l) {
columnCount - (columnCount / 4) + (segmentIndex - 1)
} else {
columnCount - (columnCount / 4) + if (segmentIndex == 0) {
-1
} else {
0
}
}
}
val x = (j1.toULong() * j1) shr 32
val y = (referenceAreaSize.toULong() * x) shr 32
val z = referenceAreaSize.toULong() - 1U - y
val startPosition = if (iteration == 0) {
0
} else {
if (slice == 3) {
0
} else {
(slice + 1) * segmentLength
}
}
val absolutePosition = (startPosition + z.toInt()) % columnCount
return Pair(l, absolutePosition)
}
override fun derive(): UByteArray {
val blakeInput = parallelism.toUInt().toLittleEndianUByteArray() +
tagLength.toLittleEndianUByteArray() +
memorySize.toLittleEndianUByteArray() +
numberOfIterations.toUInt().toLittleEndianUByteArray() +
versionNumber.toLittleEndianUByteArray() +
argonType.typeId.toUInt().toLittleEndianUByteArray() +
password.size.toUInt().toLittleEndianUByteArray() + password +
salt.size.toUInt().toLittleEndianUByteArray() + salt +
key.size.toUInt().toLittleEndianUByteArray() + key +
associatedData.size.toUInt().toLittleEndianUByteArray() + associatedData
val h0 = Blake2b.digest(
blakeInput
)
//Compute B[i][0]
for (i in 0 until parallelism) {
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.setBlockAt(i, 1,
argonBlake2bArbitraryLenghtHash(
(h0 + 1.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray()).toUByteArray(),
1024U
)
)
}
//Run all iterations over all lanes and all segments
executeArgonWithSingleThread()
val acc = ArgonBlock(matrix.getBlockAt(0, columnCount - 1))
val accPointer = acc.getBlockPointer()
for (i in 1 until parallelism) {
accPointer.xorInplaceWith(matrix.getBlockPointer(i, columnCount - 1))
}
//Hash the xored last blocks
val hash = argonBlake2bArbitraryLenghtHash(acc.storage, tagLength)
matrix.clearMatrix()
return hash
}
private fun executeArgonWithSingleThread() {
for (iteration in 0 until numberOfIterations) {
for (slice in 0 until 4) {
for (lane in 0 until parallelism) {
val segmentPosition = SegmentPosition(iteration, lane, slice)
processSegment(segmentPosition)
}
}
}
}
private fun processSegment(segmentPosition: SegmentPosition) {
val iteration = segmentPosition.iteration
val slice = segmentPosition.slice
val lane = segmentPosition.lane
var addressBlock: ArgonBlockPointer? = null
var addressCounter = 1UL //Starts from 1 in each segment as defined by the spec
//Generate initial segment address block
if (useIndependentAddressing) {
addressBlock = ArgonBlock().getBlockPointer()
addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock, addressCounter)
addressCounter++
}
val startColumn = if (iteration == 0 && slice == 0) {
2
} else {
slice * segmentLength
}
for (column in startColumn until (slice + 1) * segmentLength) {
val segmentIndex = column - (slice * segmentLength)
//Each address block contains 128 addresses, and we use one per iteration,
//so once we do 128 iterations we need to calculate a new address block
if (useIndependentAddressing && segmentIndex != 0 && segmentIndex % 128 == 0) {
addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock!!, addressCounter)
addressCounter++
}
val previousColumn = if (column == 0) {
columnCount - 1
} else {
column - 1
}
val (l, z) = computeReferenceBlockIndexes(
iteration,
slice,
lane,
column,
addressBlock
)
matrix.setBlockAt(lane, column,
compressionFunctionG(
matrix.getBlockPointer(lane, previousColumn),
matrix.getBlockPointer(l,z),
matrix.getBlockPointer(lane,column),
true
).getAsUByteArray()
)
}
}
}
interface Argon2 : KeyDerivationFunction
@@ -0,0 +1,405 @@
/*
* Copyright 2019 Ugljesa Jovanovic
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package com.ionspin.kotlin.crypto.keyderivation.argon2
import com.ionspin.kotlin.bignum.integer.toBigInteger
import com.ionspin.kotlin.crypto.SRNG
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bStateless
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.argonBlake2bArbitraryLenghtHash
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.compressionFunctionG
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.validateArgonParameters
import com.ionspin.kotlin.crypto.util.*
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 16-May-2020
*/
enum class ArgonType(val typeId: Int) {
Argon2d(0), Argon2i(1), Argon2id(2)
}
data class SegmentPosition(
val iteration: Int,
val lane: Int,
val slice: Int
)
data class ArgonResult(
val hashBytes: UByteArray,
val salt: UByteArray
) {
val hashString by lazy { hashBytes.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "") }
val saltString by lazy { salt.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "") }
}
@ExperimentalStdlibApi
class Argon2Pure(
private val password: UByteArray,
private val salt: UByteArray = ubyteArrayOf(),
private val parallelism: Int = 1,
private val tagLength: UInt = 64U,
requestedMemorySize: UInt = 0U,
private val numberOfIterations: Int = 1,
private val key: UByteArray = ubyteArrayOf(),
private val associatedData: UByteArray = ubyteArrayOf(),
private val argonType: ArgonType = ArgonType.Argon2id
) : Argon2 {
companion object {
fun derive(
password: String,
salt: String? = null,
key: String,
associatedData: String,
parallelism: Int = 16,
tagLength: Int = 64,
memory: Int = 4096,
numberOfIterations: Int = 10,
): ArgonResult {
val salt = SRNG.getRandomBytes(64)
val argon = Argon2Pure(
password.encodeToByteArray().toUByteArray(),
salt,
parallelism,
tagLength.toUInt(),
memory.toUInt(),
numberOfIterations,
key.encodeToByteArray().toUByteArray(),
associatedData.encodeToByteArray().toUByteArray(),
ArgonType.Argon2id
)
val resultArray = argon.derive()
return ArgonResult(resultArray, salt)
}
}
constructor(
password: String,
salt: String = "",
parallelism: Int = 1,
tagLength: UInt = 64U,
requestedMemorySize: UInt = 0U,
numberOfIterations: Int = 10,
key: String = "",
associatedData: String = "",
argonType: ArgonType = ArgonType.Argon2id
) : this(
password.encodeToByteArray().toUByteArray(),
salt.encodeToByteArray().toUByteArray(),
parallelism,
tagLength,
requestedMemorySize,
numberOfIterations,
key.encodeToByteArray().toUByteArray(),
associatedData.encodeToByteArray().toUByteArray(),
argonType
)
//We support only the latest version
private val versionNumber: UInt = 0x13U
//Use either requested memory size, or default, or throw exception if the requested amount is less than 8*parallelism
private val memorySize = if (requestedMemorySize == 0U) {
((8 * parallelism) * 2).toUInt()
} else {
requestedMemorySize
}
private val blockCount = (memorySize / (4U * parallelism.toUInt())) * (4U * parallelism.toUInt())
private val columnCount = (blockCount / parallelism.toUInt()).toInt()
private val segmentLength = columnCount / 4
private val useIndependentAddressing = argonType == ArgonType.Argon2id || argonType == ArgonType.Argon2i
// State
private val matrix: ArgonMatrix
init {
matrix = ArgonMatrix(columnCount, parallelism)
validateArgonParameters(
password,
salt,
parallelism,
tagLength,
requestedMemorySize,
numberOfIterations,
key,
associatedData,
argonType
)
}
private fun populateAddressBlock(
iteration: Int,
slice: Int,
lane: Int,
addressBlock: ArgonBlockPointer,
addressCounter: ULong
): ArgonBlockPointer {
//Calculate first pass
val zeroesBlock = ArgonBlock()
val firstPass = compressionFunctionG(
zeroesBlock.getBlockPointer(),
ArgonBlock(iteration.toULong().toLittleEndianUByteArray() +
lane.toULong().toLittleEndianUByteArray() +
slice.toULong().toLittleEndianUByteArray() +
blockCount.toULong().toLittleEndianUByteArray() +
numberOfIterations.toULong().toLittleEndianUByteArray() +
argonType.typeId.toULong().toLittleEndianUByteArray() +
addressCounter.toLittleEndianUByteArray() +
UByteArray(968) { 0U }
).getBlockPointer(),
addressBlock,
false
)
val secondPass = compressionFunctionG(
zeroesBlock.getBlockPointer(),
firstPass,
firstPass,
false
)
return secondPass
}
private fun computeReferenceBlockIndexes(
iteration: Int,
slice: Int,
lane: Int,
column: Int,
addressBlockPointer: ArgonBlockPointer?
): 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 previousBlockStart = if (column == 0) {
matrix.getBlockPointer(lane, columnCount - 1) //Get last block in the SAME lane
} else {
matrix.getBlockPointer(lane, column - 1)
}
val first32Bit = matrix.sliceArray(previousBlockStart.asInt() until previousBlockStart.asInt() + 4).fromLittleEndianArrayToUInt()
val second32Bit = matrix.sliceArray(previousBlockStart.asInt() + 4 until previousBlockStart.asInt() + 8).fromLittleEndianArrayToUInt()
Pair(first32Bit, second32Bit)
}
ArgonType.Argon2i -> {
val first32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8)
val second32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8 + 4)
Pair(first32Bit, second32Bit)
}
ArgonType.Argon2id -> {
if (iteration == 0 && (slice == 0 || slice == 1)) {
val first32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8)
val second32Bit = addressBlockPointer!!.getUIntFromPosition(independentIndex * 8 + 4)
Pair(first32Bit, second32Bit)
} else {
val previousBlockStart = if (column == 0) {
matrix.getBlockPointer(lane, columnCount - 1) //Get last block in the SAME lane
} else {
matrix.getBlockPointer(lane, column - 1)
}
val first32Bit = matrix.sliceArray(previousBlockStart.asInt() until previousBlockStart.asInt() + 4).fromLittleEndianArrayToUInt()
val second32Bit = matrix.sliceArray(previousBlockStart.asInt() + 4 until previousBlockStart.asInt() + 8).fromLittleEndianArrayToUInt()
Pair(first32Bit, second32Bit)
}
}
}
//If this is first iteration and first slice, block is taken from the current lane
val l = if (iteration == 0 && slice == 0) {
lane
} else {
(j2.toBigInteger() % parallelism).intValue()
}
val referenceAreaSize = if (iteration == 0) {
if (slice == 0) {
//All indices except the previous
segmentIndex - 1
} else {
if (lane == l) {
//Same lane
column - 1
} else {
slice * (columnCount / 4) + if (segmentIndex == 0) { // Check if column is first block of the SEGMENT
-1
} else {
0
}
}
}
} else {
if (lane == l) {
columnCount - (columnCount / 4) + (segmentIndex - 1)
} else {
columnCount - (columnCount / 4) + if (segmentIndex == 0) {
-1
} else {
0
}
}
}
val x = (j1.toULong() * j1) shr 32
val y = (referenceAreaSize.toULong() * x) shr 32
val z = referenceAreaSize.toULong() - 1U - y
val startPosition = if (iteration == 0) {
0
} else {
if (slice == 3) {
0
} else {
(slice + 1) * segmentLength
}
}
val absolutePosition = (startPosition + z.toInt()) % columnCount
return Pair(l, absolutePosition)
}
override fun derive(): UByteArray {
val blakeInput = parallelism.toUInt().toLittleEndianUByteArray() +
tagLength.toLittleEndianUByteArray() +
memorySize.toLittleEndianUByteArray() +
numberOfIterations.toUInt().toLittleEndianUByteArray() +
versionNumber.toLittleEndianUByteArray() +
argonType.typeId.toUInt().toLittleEndianUByteArray() +
password.size.toUInt().toLittleEndianUByteArray() + password +
salt.size.toUInt().toLittleEndianUByteArray() + salt +
key.size.toUInt().toLittleEndianUByteArray() + key +
associatedData.size.toUInt().toLittleEndianUByteArray() + associatedData
val h0 = Blake2bStateless.digest(
blakeInput
)
//Compute B[i][0]
for (i in 0 until parallelism) {
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.setBlockAt(i, 1,
argonBlake2bArbitraryLenghtHash(
(h0 + 1.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray()).toUByteArray(),
1024U
)
)
}
//Run all iterations over all lanes and all segments
executeArgonWithSingleThread()
val acc = ArgonBlock(matrix.getBlockAt(0, columnCount - 1))
val accPointer = acc.getBlockPointer()
for (i in 1 until parallelism) {
accPointer.xorInplaceWith(matrix.getBlockPointer(i, columnCount - 1))
}
//Hash the xored last blocks
val hash = argonBlake2bArbitraryLenghtHash(acc.storage, tagLength)
matrix.clearMatrix()
return hash
}
private fun executeArgonWithSingleThread() {
for (iteration in 0 until numberOfIterations) {
for (slice in 0 until 4) {
for (lane in 0 until parallelism) {
val segmentPosition = SegmentPosition(iteration, lane, slice)
processSegment(segmentPosition)
}
}
}
}
private fun processSegment(segmentPosition: SegmentPosition) {
val iteration = segmentPosition.iteration
val slice = segmentPosition.slice
val lane = segmentPosition.lane
var addressBlock: ArgonBlockPointer? = null
var addressCounter = 1UL //Starts from 1 in each segment as defined by the spec
//Generate initial segment address block
if (useIndependentAddressing) {
addressBlock = ArgonBlock().getBlockPointer()
addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock, addressCounter)
addressCounter++
}
val startColumn = if (iteration == 0 && slice == 0) {
2
} else {
slice * segmentLength
}
for (column in startColumn until (slice + 1) * segmentLength) {
val segmentIndex = column - (slice * segmentLength)
//Each address block contains 128 addresses, and we use one per iteration,
//so once we do 128 iterations we need to calculate a new address block
if (useIndependentAddressing && segmentIndex != 0 && segmentIndex % 128 == 0) {
addressBlock = populateAddressBlock(iteration, slice, lane, addressBlock!!, addressCounter)
addressCounter++
}
val previousColumn = if (column == 0) {
columnCount - 1
} else {
column - 1
}
val (l, z) = computeReferenceBlockIndexes(
iteration,
slice,
lane,
column,
addressBlock
)
matrix.setBlockAt(lane, column,
compressionFunctionG(
matrix.getBlockPointer(lane, previousColumn),
matrix.getBlockPointer(l,z),
matrix.getBlockPointer(lane,column),
true
).getAsUByteArray()
)
}
}
}
@@ -18,10 +18,8 @@
package com.ionspin.kotlin.crypto.keyderivation.argon2
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bPure
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Utils.BLOCK_SIZE
import com.ionspin.kotlin.crypto.util.arrayChunked
import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToULong
import com.ionspin.kotlin.crypto.util.plus
import com.ionspin.kotlin.crypto.util.rotateRight
@@ -101,17 +99,17 @@ object Argon2Utils {
internal fun argonBlake2bArbitraryLenghtHash(input: UByteArray, length: UInt): UByteArray {
if (length <= 64U) {
return Blake2b.digest(inputMessage = length + input, hashLength = length.toInt())
return Blake2bPure.digest(inputMessage = length + input, hashLength = length.toInt())
}
//We can cast to int because UInt even if MAX_VALUE divided by 32 is guaranteed not to overflow
val numberOf64ByteBlocks = (1U + ((length - 1U) / 32U) - 2U).toInt() // equivalent to ceil(length/32) - 2
val v = Array<UByteArray>(numberOf64ByteBlocks) { ubyteArrayOf() }
v[0] = Blake2b.digest(length + input)
v[0] = Blake2bPure.digest(length + input)
for (i in 1 until numberOf64ByteBlocks) {
v[i] = Blake2b.digest(v[i - 1])
v[i] = Blake2bPure.digest(v[i - 1])
}
val remainingPartOfInput = length.toInt() - numberOf64ByteBlocks * 32
val vLast = Blake2b.digest(v[numberOf64ByteBlocks - 1], hashLength = remainingPartOfInput)
val vLast = Blake2bPure.digest(v[numberOf64ByteBlocks - 1], hashLength = remainingPartOfInput)
val concat =
(v.map { it.copyOfRange(0, 32) })
.plus(listOf(vLast))
@@ -16,11 +16,7 @@
package com.ionspin.kotlin.crypto.parallelization
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2
import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext
import kotlin.time.ExperimentalTime
import kotlin.time.measureTime
/**
* Created by Ugljesa Jovanovic
@@ -17,13 +17,12 @@
package com.ionspin.kotlin.crypto.symmetric
import com.ionspin.kotlin.crypto.SRNG
import com.ionspin.kotlin.crypto.util.chunked
import com.ionspin.kotlin.crypto.util.xor
/**
* Advanced encryption standard with cipher block chaining and PKCS #5
*
* For bulk encryption/decryption use [AesCbc.encrypt] and [AesCbc.decrypt]
* For bulk encryption/decryption use [AesCbcPure.encrypt] and [AesCbcPure.decrypt]
*
* To get an instance of AesCbc and then feed it data sequentially with [addData] use [createEncryptor] and [createDecryptor]
*
@@ -32,7 +31,7 @@ import com.ionspin.kotlin.crypto.util.xor
* on 21-Sep-2019
*/
@ExperimentalUnsignedTypes
class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializationVector: UByteArray? = null) {
class AesCbcPure internal constructor(val aesKey: AesKey, val mode: Mode, initializationVector: UByteArray? = null) {
companion object {
const val BLOCK_BYTES = 16
@@ -40,22 +39,22 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
* Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all
* data call [encrypt]
*/
fun createEncryptor(aesKey: AesKey) : AesCbc {
return AesCbc(aesKey, Mode.ENCRYPT)
fun createEncryptor(aesKey: AesKey) : AesCbcPure {
return AesCbcPure(aesKey, Mode.ENCRYPT)
}
/**
* Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all
* data call [decrypt]
*/
fun createDecryptor(aesKey : AesKey) : AesCbc {
return AesCbc(aesKey, Mode.DECRYPT)
fun createDecryptor(aesKey : AesKey) : AesCbcPure {
return AesCbcPure(aesKey, Mode.DECRYPT)
}
/**
* Bulk encryption, returns encrypted data and a random initialization vector
*/
fun encrypt(aesKey: AesKey, data: UByteArray): EncryptedDataAndInitializationVector {
val aesCbc = AesCbc(aesKey, Mode.ENCRYPT)
val aesCbc = AesCbcPure(aesKey, Mode.ENCRYPT)
aesCbc.addData(data)
return aesCbc.encrypt()
}
@@ -64,7 +63,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
* Bulk decryption, returns decrypted data
*/
fun decrypt(aesKey: AesKey, data: UByteArray, initialCounter: UByteArray? = null): UByteArray {
val aesCbc = AesCbc(aesKey, Mode.DECRYPT, initialCounter)
val aesCbc = AesCbcPure(aesKey, Mode.DECRYPT, initialCounter)
aesCbc.addData(data)
return aesCbc.decrypt()
}
@@ -199,17 +198,17 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
Mode.ENCRYPT -> {
currentOutput = if (currentOutput.isEmpty()) {
println("IV: $initVector")
Aes.encrypt(aesKey, data xor initVector)
AesPure.encrypt(aesKey, data xor initVector)
} else {
Aes.encrypt(aesKey, data xor currentOutput)
AesPure.encrypt(aesKey, data xor currentOutput)
}
currentOutput
}
Mode.DECRYPT -> {
if (currentOutput.isEmpty()) {
currentOutput = Aes.decrypt(aesKey, data) xor initVector
currentOutput = AesPure.decrypt(aesKey, data) xor initVector
} else {
currentOutput = Aes.decrypt(aesKey, data) xor previousEncrypted
currentOutput = AesPure.decrypt(aesKey, data) xor previousEncrypted
}
previousEncrypted = data
currentOutput
@@ -20,15 +20,14 @@ import com.ionspin.kotlin.bignum.Endianness
import com.ionspin.kotlin.bignum.integer.BigInteger
import com.ionspin.kotlin.bignum.modular.ModularBigInteger
import com.ionspin.kotlin.crypto.SRNG
import com.ionspin.kotlin.crypto.util.chunked
import com.ionspin.kotlin.crypto.symmetric.AesCtr.Companion.encrypt
import com.ionspin.kotlin.crypto.symmetric.AesCtrPure.Companion.encrypt
import com.ionspin.kotlin.crypto.util.xor
/**
*
* Advanced encryption standard with counter mode
*
* For bulk encryption/decryption use [AesCtr.encrypt] and [AesCtr.decrypt]
* For bulk encryption/decryption use [AesCtrPure.encrypt] and [AesCtrPure.decrypt]
*
* To get an instance of AesCtr and then feed it data sequentially with [addData] use [createEncryptor] and [createDecryptor]
*
@@ -37,7 +36,7 @@ import com.ionspin.kotlin.crypto.util.xor
* on 22-Sep-2019
*/
@ExperimentalUnsignedTypes
class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCounter: UByteArray? = null) {
class AesCtrPure internal constructor(val aesKey: AesKey, val mode: Mode, initialCounter: UByteArray? = null) {
companion object {
const val BLOCK_BYTES = 16
@@ -47,21 +46,21 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
* Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all
* data call [encrypt]
*/
fun createEncryptor(aesKey: AesKey) : AesCtr {
return AesCtr(aesKey, Mode.ENCRYPT)
fun createEncryptor(aesKey: AesKey) : AesCtrPure {
return AesCtrPure(aesKey, Mode.ENCRYPT)
}
/**
* Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all
* data call [decrypt]
*/
fun createDecryptor(aesKey : AesKey) : AesCtr {
return AesCtr(aesKey, Mode.DECRYPT)
fun createDecryptor(aesKey : AesKey) : AesCtrPure {
return AesCtrPure(aesKey, Mode.DECRYPT)
}
/**
* Bulk encryption, returns encrypted data and a random initial counter
*/
fun encrypt(aesKey: AesKey, data: UByteArray): EncryptedDataAndInitialCounter {
val aesCtr = AesCtr(aesKey, Mode.ENCRYPT)
val aesCtr = AesCtrPure(aesKey, Mode.ENCRYPT)
aesCtr.addData(data)
return aesCtr.encrypt()
}
@@ -69,7 +68,7 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
* Bulk decryption, returns decrypted data
*/
fun decrypt(aesKey: AesKey, data: UByteArray, initialCounter: UByteArray? = null): UByteArray {
val aesCtr = AesCtr(aesKey, Mode.DECRYPT, initialCounter)
val aesCtr = AesCtrPure(aesKey, Mode.DECRYPT, initialCounter)
aesCtr.addData(data)
return aesCtr.decrypt()
}
@@ -165,10 +164,10 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
val blockCountAsByteArray = blockCount.toUByteArray(Endianness.BIG).toUByteArray().expandCounterTo16Bytes()
return when (mode) {
Mode.ENCRYPT -> {
Aes.encrypt(aesKey, blockCountAsByteArray) xor data
AesPure.encrypt(aesKey, blockCountAsByteArray) xor data
}
Mode.DECRYPT -> {
Aes.encrypt(aesKey, blockCountAsByteArray) xor data
AesPure.encrypt(aesKey, blockCountAsByteArray) xor data
}
}
@@ -6,7 +6,7 @@ import com.ionspin.kotlin.crypto.util.flattenToUByteArray
* Created by Ugljesa Jovanovic (jovanovic.ugljesa@gmail.com) on 07/Sep/2019
*/
@ExperimentalUnsignedTypes
internal class Aes internal constructor(val aesKey: AesKey, val input: UByteArray) {
internal class AesPure internal constructor(val aesKey: AesKey, val input: UByteArray) {
companion object {
private val debug = false
@@ -57,11 +57,11 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: UByteArra
val rcon: UByteArray = ubyteArrayOf(0x8DU, 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, 0x1BU, 0x36U)
fun encrypt(aesKey: AesKey, input: UByteArray): UByteArray {
return Aes(aesKey, input).encrypt()
return AesPure(aesKey, input).encrypt()
}
fun decrypt(aesKey: AesKey, input: UByteArray): UByteArray {
return Aes(aesKey, input).decrypt()
return AesPure(aesKey, input).decrypt()
}
}
@@ -16,10 +16,10 @@
package com.ionspin.kotlin.crypto
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b
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.hash.blake2b.Blake2bPure
import com.ionspin.kotlin.crypto.hash.sha.Sha256Pure
import com.ionspin.kotlin.crypto.hash.sha.Sha512Pure
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Pure
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType
import com.ionspin.kotlin.crypto.util.testBlocking
import kotlin.test.Test
@@ -40,7 +40,7 @@ class ReadmeTest {
@Test
fun blake2bObjectExample() {
val input = "abc"
val result = Blake2b.digest(input)
val result = Blake2bPure.digest(input)
//@formatter:off
val expectedResult = ubyteArrayOf(
0xBAU,0x80U,0xA5U,0x3FU,0x98U,0x1CU,0x4DU,0x0DU,0x6AU,0x27U,0x97U,0xB6U,0x9FU,0x12U,0xF6U,0xE9U,
@@ -59,7 +59,7 @@ class ReadmeTest {
fun blake2bInstanceExample() {
val test = "abc"
val key = "key"
val blake2b = Blake2b(key)
val blake2b = Blake2bPure(key)
blake2b.update(test)
val result = blake2b.digest()
@@ -79,7 +79,7 @@ class ReadmeTest {
@Test
fun sha256Example() {
val input = "abc"
val result = Sha256.digest(inputString = input)
val result = Sha256Pure.digest(inputString = input)
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
@@ -92,7 +92,7 @@ class ReadmeTest {
@Test
fun sha512Example() {
val input = "abc"
val result = Sha512.digest(inputMessage = input.encodeToByteArray().map { it.toUByte() }.toUByteArray())
val result = Sha512Pure.digest(inputMessage = input.encodeToByteArray().map { it.toUByte() }.toUByteArray())
println(result.map { it.toString(16) })
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
@@ -106,7 +106,7 @@ class ReadmeTest {
@ExperimentalStdlibApi
@Test
fun sha256UpdatableExample() {
val sha256 = Sha256()
val sha256 = Sha256Pure()
sha256.update("abc")
val result = sha256.digest()
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
@@ -118,7 +118,7 @@ class ReadmeTest {
@ExperimentalStdlibApi
@Test
fun sha512UpdatableExample() {
val sha512 = Sha512()
val sha512 = Sha512Pure()
sha512.update("abc")
val result = sha512.digest()
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
@@ -133,13 +133,13 @@ class ReadmeTest {
@ExperimentalTime
@Test
fun argon2StringExample() = testBlocking {
val argon2Instance = Argon2(
val argon2Instance = Argon2Pure(
password = "Password",
salt = "RandomSalt",
parallelism = 1,
tagLength = 64U,
requestedMemorySize = 4096U,
numberOfIterations = 100,
numberOfIterations = 2,
key = "",
associatedData = "",
argonType = ArgonType.Argon2id
@@ -147,7 +147,7 @@ class ReadmeTest {
val time = measureTime {
val tag = argon2Instance.derive()
val tagString = tag.map { it.toString(16).padStart(2, '0') }.joinToString(separator = "")
val expectedTagString = "27c61b6538ef9f4a1250f8712cac09fc4329969295f9440249437d38c1617a005c2702d76a8a59e4cda2dfba48e1132261dacdfd31296945906992ea32f1d06e"
val expectedTagString = "c19db7e22d1480702b943872c863baf8c43b53d0c3e2c782cd07bfc613eda159233bd821a945c239c5085c70257f7c93d8a809f81c4af367f4ad8f0443a8fc47"
println("Tag: ${tagString}")
assertEquals(tagString, expectedTagString)
}
@@ -18,7 +18,7 @@
package com.ionspin.kotlin.crypto.hash.argon
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2
import com.ionspin.kotlin.crypto.keyderivation.argon2.Argon2Pure
import com.ionspin.kotlin.crypto.keyderivation.argon2.ArgonType
import com.ionspin.kotlin.crypto.util.hexColumsPrint
import kotlin.test.Test
@@ -57,7 +57,7 @@ class Argon2KATTest {
val secret: UByteArray = ubyteArrayOf(0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U)
val associatedData: UByteArray = ubyteArrayOf(0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U)
val digest = Argon2(
val digest = Argon2Pure(
password,
salt,
parallelism.toInt(),
@@ -98,7 +98,7 @@ class Argon2KATTest {
val secret: UByteArray = ubyteArrayOf(0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U)
val associatedData: UByteArray = ubyteArrayOf(0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U)
val digest = Argon2(
val digest = Argon2Pure(
password,
salt,
parallelism.toInt(),
@@ -139,7 +139,7 @@ class Argon2KATTest {
val secret: UByteArray = ubyteArrayOf(0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U, 0x03U)
val associatedData: UByteArray = ubyteArrayOf(0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U, 0x04U)
val digest = Argon2(
val digest = Argon2Pure(
password,
salt,
parallelism.toInt(),
@@ -46,7 +46,7 @@ class Blake2BTest {
"1234567890" +
"1234567890"
val result = Blake2b.digest(test)
val result = Blake2bPure.digest(test)
//Generated with b2sum 8.31
val expectedResult = ubyteArrayOf(
//@formatter:off
@@ -77,7 +77,7 @@ class Blake2BTest {
"1234567890"
val result = Blake2b.digest(test)
val result = Blake2bPure.digest(test)
val expectedResultString = "800bb78cd4da18995c8074713bb674" +
"3cd94b2b6490a693fe4000ed00833b88b7b474d94af9cfed246b1b" +
"4ce1935a76154d7ea7c410493557741d18ec3a08da75"
@@ -93,7 +93,7 @@ class Blake2BTest {
fun testDigest() {
val test = "111111111122222222223333333333333"
val result = Blake2b.digest(test)
val result = Blake2bPure.digest(test)
//Generated with b2sum 8.31
val expectedResult = ubyteArrayOf(
//@formatter:off
@@ -115,7 +115,7 @@ class Blake2BTest {
val test = "abc"
val key = "key"
val result = Blake2b.digest(test, key)
val result = Blake2bPure.digest(test, key)
assertTrue {
result.isNotEmpty()
@@ -134,7 +134,7 @@ class Blake2BTest {
fun testDigestFromRfc() {
val test = "abc"
val result = Blake2b.digest(test)
val result = Blake2bPure.digest(test)
//@formatter:off
val expectedResult = ubyteArrayOf(
@@ -272,7 +272,7 @@ class Blake2BTest {
for (i in 0 until mixChain.size - 1) {
val inputRound = mixChain[i]
val round = i
val result = Blake2b.mixRound(inputRound, message, round)
val result = Blake2bPure.mixRound(inputRound, message, round)
val expectedResult = mixChain[i + 1]
assertTrue {
result.contentEquals(expectedResult)
@@ -286,7 +286,7 @@ class Blake2BTest {
fun testInvalidHashLength() {
val test = "1234567890"
assertFailsWith(RuntimeException::class) {
val result = Blake2b.digest(inputString = test, hashLength = 65)
val result = Blake2bPure.digest(inputString = test, hashLength = 65)
}
}
@@ -42,7 +42,7 @@ class Blake2bInstanceTest {
//@formatter:on
)
val blake2b = Blake2b()
val blake2b = Blake2bPure()
for (i in 0 until updates) {
blake2b.update(input)
}
@@ -60,7 +60,7 @@ class Blake2bInstanceTest {
val expectedResult = "2F49AEB613E34E924E175A6AF2FAAD7BC78235F9C5E461C68FD5B47E".toLowerCase() +
"E8E2FD2FB4C07D7E4A72404612D92899AF8A328F3B614ED77244B481151D40B11E32A4".toLowerCase()
val blake2b = Blake2b()
val blake2b = Blake2bPure()
for (i in 0 until updates) {
blake2b.update(input)
}
@@ -74,7 +74,7 @@ class Blake2bInstanceTest {
fun testDigestWithKey() {
val test = "abc"
val key = "key"
val blake2b = Blake2b(key)
val blake2b = Blake2bPure(key)
blake2b.update(test)
val result = blake2b.digest()
@@ -37,7 +37,7 @@ class Blake2bKnowAnswerTests {
fun knownAnswerTest() {
kat.forEach {
val parsedInput = it.input.chunked(2).map { it.toUByte(16) }.toUByteArray()
val result = Blake2b.digest(
val result = Blake2bPure.digest(
inputMessage = parsedInput,
key = it.key.chunked(2).map { it.toUByte(16) }.toUByteArray()
)
@@ -53,7 +53,7 @@ class Blake2bKnowAnswerTests {
kat.forEach { kat ->
val parsedInput = kat.input.chunked(2).map { it.toUByte(16) }.toUByteArray()
val chunkedInput = parsedInput.toList().chunked(128).map { it.toUByteArray() }
val blake2b = Blake2b(key = kat.key.chunked(2).map { it.toUByte(16) }.toUByteArray())
val blake2b = Blake2bPure(key = kat.key.chunked(2).map { it.toUByte(16) }.toUByteArray())
chunkedInput.forEach { blake2b.update(it) }
val result = blake2b.digest()
assertTrue("KAT ${kat.input} \nkey: ${kat.key} \nexpected: {${kat.hash}") {
@@ -31,7 +31,7 @@ class Sha256Test {
@Test
fun testWellKnownValue() {
val result = Sha256.digest(inputString = "abc")
val result = Sha256Pure.digest(inputString = "abc")
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
@@ -44,7 +44,7 @@ class Sha256Test {
@Test
fun testWellKnownDoubleBlock() {
val resultDoubleBlock = Sha256.digest(inputString = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
val resultDoubleBlock = Sha256Pure.digest(inputString = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
val expectedResultForDoubleBlock = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
@@ -56,7 +56,7 @@ class Sha256Test {
fun testWellKnown3() { //It's good that I'm consistent with names.
val resultDoubleBlock = Sha256.digest(inputString = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = Sha256Pure.digest(inputString = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"
assertTrue {
@@ -71,7 +71,7 @@ class Sha256Test {
for (i in 0 until 1000000) {
inputBuilder.append("a")
}
val resultDoubleBlock = Sha256.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toUByteArray())
val resultDoubleBlock = Sha256Pure.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toUByteArray())
val expectedResultForDoubleBlock = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
@@ -31,7 +31,7 @@ class Sha256UpdatableTest {
@ExperimentalStdlibApi
@Test
fun testWellKnownValue() {
val sha256 = Sha256()
val sha256 = Sha256Pure()
sha256.update("abc")
val result = sha256.digest()
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
@@ -43,7 +43,7 @@ class Sha256UpdatableTest {
@ExperimentalStdlibApi
@Test
fun testWellKnownDoubleBlock() {
val sha256 = Sha256()
val sha256 = Sha256Pure()
sha256.update(data = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
val resultDoubleBlock = sha256.digest()
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
@@ -56,7 +56,7 @@ class Sha256UpdatableTest {
@ExperimentalStdlibApi
@Test
fun testWellKnown3() { //It's good that I'm consistent with names.
val sha256 = Sha256()
val sha256 = Sha256Pure()
sha256.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = sha256.digest()
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
@@ -69,7 +69,7 @@ class Sha256UpdatableTest {
@ExperimentalStdlibApi
@Test
fun testWellKnownLong() {
val sha256 = Sha256()
val sha256 = Sha256Pure()
for (i in 0 until 10000) {
sha256.update("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
}
@@ -84,7 +84,7 @@ class Sha256UpdatableTest {
@ExperimentalStdlibApi
@Test
fun testWellKnownLonger() {
val sha256 = Sha256()
val sha256 = Sha256Pure()
for (i in 0 until 16_777_216) {
if (i % 10000 == 0) {
println("$i/16777216")
@@ -30,7 +30,7 @@ class Sha512Test {
@Test
fun testWellKnownValue() {
val result = Sha512.digest(inputMessage = "abc".encodeToByteArray().map { it.toUByte() }.toUByteArray())
val result = Sha512Pure.digest(inputMessage = "abc".encodeToByteArray().map { it.toUByte() }.toUByteArray())
println(result.map {it.toString(16)})
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
@@ -45,7 +45,7 @@ class Sha512Test {
@ExperimentalStdlibApi
@Test
fun testWellKnown3() {
val sha512 = Sha512()
val sha512 = Sha512Pure()
sha512.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = sha512.digest()
val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +
@@ -62,7 +62,7 @@ class Sha512Test {
for (i in 0 until 1000000) {
inputBuilder.append("a")
}
val resultDoubleBlock = Sha512.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toUByteArray())
val resultDoubleBlock = Sha512Pure.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toUByteArray())
val expectedResultForDoubleBlock = "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"
assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
@@ -29,7 +29,7 @@ class Sha512UpdatableTest {
@ExperimentalStdlibApi
@Test
fun testWellKnownValue() {
val sha512 = Sha512()
val sha512 = Sha512Pure()
sha512.update("abc")
val result = sha512.digest()
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
@@ -44,7 +44,7 @@ class Sha512UpdatableTest {
@ExperimentalStdlibApi
@Test
fun testWellKnownDoubleBlock() {
val sha512 = Sha512()
val sha512 = Sha512Pure()
sha512.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = sha512.digest()
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
@@ -58,7 +58,7 @@ class Sha512UpdatableTest {
@ExperimentalStdlibApi
@Test
fun testWellKnownLong() {
val sha512 = Sha512()
val sha512 = Sha512Pure()
for (i in 0 until 10000) {
sha512.update("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
}
@@ -73,7 +73,7 @@ class Sha512UpdatableTest {
@ExperimentalStdlibApi
@Test
fun testWellKnownLonger() {
val sha512 = Sha512()
val sha512 = Sha512Pure()
for (i in 0 until 16_777_216) {
if (i % 10000 == 0) {
println("$i/16777216")
@@ -16,7 +16,6 @@
package com.ionspin.kotlin.crypto.symmetric
import com.ionspin.kotlin.crypto.util.hexStringToUByteArray
import com.ionspin.kotlin.crypto.util.hexStringToUByteArray
import com.ionspin.kotlin.crypto.util.toHexString
import kotlin.test.Test
@@ -38,7 +37,7 @@ class AesCbcTest {
val plaintext = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val expectedCipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
val aesCbc =
AesCbc(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initializationVector = iv.hexStringToUByteArray())
AesCbcPure(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initializationVector = iv.hexStringToUByteArray())
aesCbc.addData(plaintext.hexStringToUByteArray())
val encrypted = aesCbc.encrypt()
println("Encrypted: ${encrypted.encryptedData.toHexString()}")
@@ -59,8 +58,8 @@ class AesCbcTest {
val plainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val encryptedDataAndInitializationVector = AesCbc.encrypt(key, plainText.hexStringToUByteArray())
val decrypted = AesCbc.decrypt(
val encryptedDataAndInitializationVector = AesCbcPure.encrypt(key, plainText.hexStringToUByteArray())
val decrypted = AesCbcPure.decrypt(
key,
encryptedDataAndInitializationVector.encryptedData,
encryptedDataAndInitializationVector.initilizationVector
@@ -77,7 +76,7 @@ class AesCbcTest {
val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val aesCbc =
AesCbc(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initializationVector = iv.hexStringToUByteArray())
AesCbcPure(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initializationVector = iv.hexStringToUByteArray())
aesCbc.addData(cipherText.hexStringToUByteArray())
val decrypted = aesCbc.decrypt()
println("Decrypted: ${decrypted.toHexString()}")
@@ -96,7 +95,7 @@ class AesCbcTest {
val iv = "57f02a5c5339daeb0a2908a06ac6393f"
val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
val decrypted = AesCbc.decrypt(AesKey.Aes128Key(key), cipherText.hexStringToUByteArray(), iv.hexStringToUByteArray())
val decrypted = AesCbcPure.decrypt(AesKey.Aes128Key(key), cipherText.hexStringToUByteArray(), iv.hexStringToUByteArray())
println("Decrypted: ${decrypted.toHexString()}")
expectedPlainText == decrypted.toHexString()
@@ -38,7 +38,7 @@ class AesCtrTest {
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val expectedCipherText =
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
val aesCtr = AesCtr(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initialCounter = ic.hexStringToUByteArray())
val aesCtr = AesCtrPure(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initialCounter = ic.hexStringToUByteArray())
aesCtr.addData(
plaintext.hexStringToUByteArray()
)
@@ -57,8 +57,8 @@ class AesCtrTest {
val key = AesKey.Aes128Key(keyString)
val plainText = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val encryptedDataAndInitializationVector = AesCtr.encrypt(key, plainText.hexStringToUByteArray())
val decrypted = AesCtr.decrypt(
val encryptedDataAndInitializationVector = AesCtrPure.encrypt(key, plainText.hexStringToUByteArray())
val decrypted = AesCtrPure.decrypt(
key,
encryptedDataAndInitializationVector.encryptedData,
encryptedDataAndInitializationVector.initialCounter
@@ -77,7 +77,7 @@ class AesCtrTest {
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
val expectedPlainText =
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val aesCtr = AesCtr(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initialCounter = ic.hexStringToUByteArray())
val aesCtr = AesCtrPure(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initialCounter = ic.hexStringToUByteArray())
aesCtr.addData(cipherText.hexStringToUByteArray())
val decrypted = aesCtr.decrypt()
println("Decrypted: ${decrypted.toHexString()}")
@@ -97,7 +97,7 @@ class AesCtrTest {
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
val expectedPlainText =
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
val decrypted = AesCtr.decrypt(AesKey.Aes128Key(key), cipherText.hexStringToUByteArray(), ic.hexStringToUByteArray())
val decrypted = AesCtrPure.decrypt(AesKey.Aes128Key(key), cipherText.hexStringToUByteArray(), ic.hexStringToUByteArray())
println("Decrypted: ${decrypted.toHexString()}")
expectedPlainText == decrypted.toHexString()
}
@@ -20,7 +20,7 @@ class AesTest {
ubyteArrayOf(0U, 0U, 0U, 0U),
ubyteArrayOf(0U, 0U, 0U, 0U)
)
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
val aes = AesPure(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
fakeState.copyInto(aes.state)
aes.subBytes()
assertTrue {
@@ -42,7 +42,7 @@ class AesTest {
ubyteArrayOf(2U, 3U, 0U, 1U),
ubyteArrayOf(3U, 0U, 1U, 2U)
)
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
val aes = AesPure(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
fakeState.copyInto(aes.state)
aes.shiftRows()
assertTrue {
@@ -56,7 +56,7 @@ class AesTest {
assertTrue {
val a = 0x57U
val b = 0x83U
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
val aes = AesPure(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
val c = aes.galoisFieldMultiply(a.toUByte(), b.toUByte())
c == 0xC1U.toUByte()
}
@@ -64,7 +64,7 @@ class AesTest {
assertTrue {
val a = 0x57U
val b = 0x13U
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
val aes = AesPure(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
val c = aes.galoisFieldMultiply(a.toUByte(), b.toUByte())
c == 0xFEU.toUByte()
}
@@ -89,7 +89,7 @@ class AesTest {
ubyteArrayOf(0xbcU, 0x9dU, 0x01U, 0xc6U)
)
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
val aes = AesPure(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
fakeState.copyInto(aes.state)
aes.mixColumns()
assertTrue {
@@ -116,7 +116,7 @@ class AesTest {
).toTypedArray()
val aes = Aes(AesKey.Aes128Key(key), irrelevantInput)
val aes = AesPure(AesKey.Aes128Key(key), irrelevantInput)
val result = aes.expandedKey.map {
it.foldIndexed(0U) { index, acc, uByte ->
acc + (uByte.toUInt() shl (24 - index * 8))
@@ -140,7 +140,7 @@ class AesTest {
).toTypedArray()
val aes = Aes(AesKey.Aes192Key(key), irrelevantInput)
val aes = AesPure(AesKey.Aes192Key(key), irrelevantInput)
val result = aes.expandedKey.map {
it.foldIndexed(0U) { index, acc, uByte ->
acc + (uByte.toUInt() shl (24 - index * 8))
@@ -166,7 +166,7 @@ class AesTest {
).toTypedArray()
val aes = Aes(AesKey.Aes256Key(key), irrelevantInput)
val aes = AesPure(AesKey.Aes256Key(key), irrelevantInput)
val result = aes.expandedKey.map {
it.foldIndexed(0U) { index, acc, uByte ->
acc + (uByte.toUInt() shl (24 - index * 8))
@@ -183,7 +183,7 @@ class AesTest {
val key = "2b7e151628aed2a6abf7158809cf4f3c"
val expectedResult = "3925841d02dc09fbdc118597196a0b32"
val aes = Aes(AesKey.Aes128Key(key), input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
val aes = AesPure(AesKey.Aes128Key(key), input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
val result = aes.encrypt()
assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
@@ -197,12 +197,12 @@ class AesTest {
val key = "2b7e151628aed2a6abf7158809cf4f3c"
val expectedResult = "3925841d02dc09fbdc118597196a0b32"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val aes = Aes(AesKey.Aes128Key(key), original)
val aes = AesPure(AesKey.Aes128Key(key), original)
val encrypted = aes.encrypt()
assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
}
val decrypted = Aes.decrypt(AesKey.Aes128Key(key), encrypted)
val decrypted = AesPure.decrypt(AesKey.Aes128Key(key), encrypted)
decrypted.contentEquals(original)
}
@@ -211,12 +211,12 @@ class AesTest {
val key = "000102030405060708090a0b0c0d0e0f"
val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val aes = Aes(AesKey.Aes128Key(key), original)
val aes = AesPure(AesKey.Aes128Key(key), original)
val encrypted = aes.encrypt()
assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
}
val aesDec = Aes(AesKey.Aes128Key(key), encrypted)
val aesDec = AesPure(AesKey.Aes128Key(key), encrypted)
val decrypted = aesDec.decrypt()
assertTrue {
aesDec.expandedKey.contentDeepEquals(aes.expandedKey)
@@ -229,11 +229,11 @@ class AesTest {
val key = "000102030405060708090a0b0c0d0e0f"
val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val encrypted = Aes.encrypt(AesKey.Aes128Key(key), original)
val encrypted = AesPure.encrypt(AesKey.Aes128Key(key), original)
assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
}
val decrypted = Aes.decrypt(AesKey.Aes128Key(key), encrypted)
val decrypted = AesPure.decrypt(AesKey.Aes128Key(key), encrypted)
decrypted.contentEquals(original)
}
@@ -242,11 +242,11 @@ class AesTest {
val key = "000102030405060708090a0b0c0d0e0f1011121314151617"
val expectedResult = "dda97ca4864cdfe06eaf70a0ec0d7191"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val encrypted = Aes.encrypt(AesKey.Aes192Key(key), original)
val encrypted = AesPure.encrypt(AesKey.Aes192Key(key), original)
assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
}
val decrypted = Aes.decrypt(AesKey.Aes192Key(key), encrypted)
val decrypted = AesPure.decrypt(AesKey.Aes192Key(key), encrypted)
decrypted.contentEquals(original)
}
@@ -255,11 +255,11 @@ class AesTest {
val key = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
val expectedResult = "8ea2b7ca516745bfeafc49904b496089"
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
val encrypted = Aes.encrypt(AesKey.Aes256Key(key), original)
val encrypted = AesPure.encrypt(AesKey.Aes256Key(key), original)
assertTrue {
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
}
val decrypted = Aes.decrypt(AesKey.Aes256Key(key), encrypted)
val decrypted = AesPure.decrypt(AesKey.Aes256Key(key), encrypted)
decrypted.contentEquals(original)
}
}