diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/CryptoProvider.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/CryptoProvider.kt index ba8f95e..bc0449e 100644 --- a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/CryptoProvider.kt +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/CryptoProvider.kt @@ -1,5 +1,6 @@ package com.ionspin.kotlin.crypto +import com.ionspin.kotlin.crypto.hash.UpdatableHash import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bProperties import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bPure import com.ionspin.kotlin.crypto.hash.encodeToUByteArray @@ -16,7 +17,7 @@ typealias Blake2bPureStateless = Blake2bPure.Companion typealias Sha256PureStateless = Sha256Pure.Companion typealias Sha512PureStateless = Sha512Pure.Companion -object Crypto : CryptoProvider { +object Primitives : CryptoProvider { override suspend fun initialize() { //Nothing to do atm. } @@ -25,7 +26,6 @@ object Crypto : CryptoProvider { done() } - object Blake2b { fun updateable(key: UByteArray? = null, hashLength: Int = Blake2bProperties.MAX_HASH_BYTES): com.ionspin.kotlin.crypto.hash.blake2b.Blake2b { checkInitialization() @@ -62,6 +62,7 @@ object Crypto : CryptoProvider { } } + private fun checkInitialization() { // Nothing to do atm } @@ -85,20 +86,23 @@ interface Encryptable { fun encryptableData() : UByteArray } -object PublicApi { - data class HashedData(val hash: UByteArray) { - fun toHexString() : String { - return hash.toHexString() - } +data class HashedData(val hash: UByteArray) { + fun toHexString() : String { + return hash.toHexString() } +} - data class EncryptedData(val encrypted: UByteArray) - +data class EncryptedData(val encrypted: UByteArray) +object PublicApi { object Hash { - fun hash() : HashedData { - TODO() + fun hash(data: UByteArray, key : UByteArray = ubyteArrayOf()) : HashedData { + return HashedData(Blake2bPureStateless.digest(data, key)) + } + + fun updateableHash(key: UByteArray? = null) : UpdatableHash { + return Blake2bPure(key) } } object Symmetric { diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/authenticated/ChaCha20Poly1305Pure.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/authenticated/ChaCha20Poly1305Pure.kt index cdaabbb..0d379bf 100644 --- a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/authenticated/ChaCha20Poly1305Pure.kt +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/authenticated/ChaCha20Poly1305Pure.kt @@ -12,7 +12,7 @@ import com.ionspin.kotlin.crypto.util.toLittleEndianUByteArray * ugljesa.jovanovic@ionspin.com * on 17-Jun-2020 */ -class ChaCha20Poly1305Pure { +internal class ChaCha20Poly1305Pure { companion object { fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, additionalData: UByteArray) : UByteArray { @@ -38,8 +38,6 @@ class ChaCha20Poly1305Pure { } } val oneTimeKey = ChaCha20Pure.hash(state).sliceArray(0 until 32) - println("Poly key:") - oneTimeKey.hexColumsPrint() val cipherText = ChaCha20Pure.encrypt(key, nonce, message, 1U) val additionalDataPad = UByteArray(16 - additionalData.size % 16) { 0U } val cipherTextPad = UByteArray(16 - cipherText.size % 16) { 0U } @@ -47,11 +45,7 @@ class ChaCha20Poly1305Pure { cipherText + cipherTextPad + additionalData.size.toULong().toLittleEndianUByteArray() + cipherText.size.toULong().toLittleEndianUByteArray() - println("Mac data") - macData.hexColumsPrint() val tag = Poly1305.poly1305Authenticate(oneTimeKey, macData) - println("Tag:") - tag.hexColumsPrint() return cipherText + tag } } diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Pure.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Pure.kt index fa96a96..f70f6c3 100644 --- a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Pure.kt +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Pure.kt @@ -1,11 +1,8 @@ package com.ionspin.kotlin.crypto.authenticated -import com.ionspin.kotlin.bignum.Endianness -import com.ionspin.kotlin.bignum.integer.BigInteger import com.ionspin.kotlin.crypto.mac.Poly1305 import com.ionspin.kotlin.crypto.symmetric.ChaCha20Pure import com.ionspin.kotlin.crypto.symmetric.XChaCha20Pure -import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToUIntWithPosition import com.ionspin.kotlin.crypto.util.hexColumsPrint import com.ionspin.kotlin.crypto.util.toLittleEndianUByteArray @@ -14,7 +11,7 @@ import com.ionspin.kotlin.crypto.util.toLittleEndianUByteArray * ugljesa.jovanovic@ionspin.com * on 17-Jun-2020 */ -class XChaCha20Poly1305Pure { +internal class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray, val additionalData: UByteArray) { companion object { fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, additionalData: UByteArray) : UByteArray { @@ -24,7 +21,10 @@ class XChaCha20Poly1305Pure { oneTimeKey.toLittleEndianUByteArray(), ubyteArrayOf(0U, 0U, 0U, 0U) + nonce.sliceArray(16 until 24), UByteArray(64) { 0U }, - 0U + 0U // If this is moved as a default parameter in encrypt, and not here (in 1.4-M2) + // js compiler dies with: e: java.lang.NullPointerException + // at org.jetbrains.kotlin.ir.backend.js.lower.ConstTransformer$visitConst$1$3.invoke(ConstLowering.kt:28) + // at org.jetbrains.kotlin.ir.backend.js.lower.ConstTransformer.lowerConst(ConstLowering.kt:38) ) println("Poly sub-key:") oneTimeKey.hexColumsPrint() @@ -37,16 +37,25 @@ class XChaCha20Poly1305Pure { cipherText + cipherTextPad + additionalData.size.toULong().toLittleEndianUByteArray() + cipherText.size.toULong().toLittleEndianUByteArray() - - oneTimeKey.toLittleEndianUByteArray().hexColumsPrint() - - println("Ciphertext:") - cipherText.hexColumsPrint() val tag = Poly1305.poly1305Authenticate(authKey, macData) - println("Tag:") - tag.hexColumsPrint() return cipherText + tag } } + +// val encryption = XChaCha20Pure(key, nonce, initialCounter = 0U) { +// +// } +// +// +// fun encryptPartialData(data: UByteArray) : UByteArray { +// +// } +// +// fun finish() : UByteArray { +// +// } + + + } \ No newline at end of file diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/mac/Poly1305.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/mac/Poly1305.kt index 1a40bb6..4281ec5 100644 --- a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/mac/Poly1305.kt +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/mac/Poly1305.kt @@ -39,16 +39,9 @@ class Poly1305 { val r = UByteArray(16) { key[it] } val s= UByteArray(16) { key[it + 16]} clampR(r) - println("P: ${P.toString(16)}") - println("R:") - r.hexColumsPrint() - println("S:") - s.hexColumsPrint() var accumulator = BigInteger.ZERO val rAsBigInt = BigInteger.fromUByteArray(r, Endianness.LITTLE) - println("R: ${rAsBigInt.toString(16)}") val sAsBigInt = BigInteger.fromUByteArray(s, Endianness.LITTLE) - println("S: ${sAsBigInt.toString(16)}") val blocks = message.size / 16 val remainder = message.size % 16 @@ -56,32 +49,20 @@ class Poly1305 { val slice = message.sliceArray(i * 16 until i * 16 + 16) slice.hexColumsPrint() val blockAsInt = BigInteger.fromUByteArray(slice, Endianness.LITTLE) + powersOfTwo[128] - println("blockAsInt: ${blockAsInt.toString(16)}") accumulator += blockAsInt - println("Accumlator: ${accumulator.toString(16)}") accumulator *= rAsBigInt - println("Accumlator: ${accumulator.toString(16)}") accumulator %= P - println("Accumlator: ${accumulator.toString(16)}") } if (remainder != 0) { val slice = message.sliceArray(blocks * 16 until blocks * 16 + remainder) val blockAsInt = BigInteger.fromUByteArray(slice, Endianness.LITTLE) + powersOfTwo[remainder * 8] - println("blockAsInt: ${blockAsInt.toString(16)}") accumulator += blockAsInt - println("Accumlator: ${accumulator.toString(16)}") accumulator *= rAsBigInt - println("Accumlator: ${accumulator.toString(16)}") accumulator %= P - println("Accumlator: ${accumulator.toString(16)}") } - - println("Result mask: ${resultMask.toString(16)}") accumulator += sAsBigInt - println("Before mask: ${accumulator.toString(16)}") accumulator = accumulator and resultMask - println("Accumlator: ${accumulator.toString(16)}") val result = accumulator.toUByteArray(Endianness.BIG) result.reverse() return result diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/ChaCha20Pure.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/ChaCha20Pure.kt index fec7711..58f7d54 100644 --- a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/ChaCha20Pure.kt +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/ChaCha20Pure.kt @@ -57,7 +57,7 @@ internal class ChaCha20Pure { val sigma2_32 = 2036477234U //ubyteArrayOf(50U, 45U, 98U, 121U) val sigma3_32 = 1797285236U //ubyteArrayOf(116U, 101U, 32U, 107U) - fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, initialCounter: UInt = 0U): UByteArray { + fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, initialCounter: UInt): UByteArray { val ciphertext = UByteArray(message.size) val state = UIntArray(16) { when (it) { diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/XChaCha20Pure.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/XChaCha20Pure.kt index 8a92444..9171d31 100644 --- a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/XChaCha20Pure.kt +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/XChaCha20Pure.kt @@ -1,7 +1,7 @@ package com.ionspin.kotlin.crypto.symmetric import com.ionspin.kotlin.crypto.util.fromLittleEndianArrayToUIntWithPosition -import com.ionspin.kotlin.crypto.util.hexColumsPrint +import com.ionspin.kotlin.crypto.util.overwriteWithZeroes import com.ionspin.kotlin.crypto.util.xorWithPositionsAndInsertIntoArray /** @@ -9,8 +9,9 @@ import com.ionspin.kotlin.crypto.util.xorWithPositionsAndInsertIntoArray * ugljesa.jovanovic@ionspin.com * on 14-Jun-2020 */ -internal class XChaCha20Pure { +class XChaCha20Pure(key: UByteArray, nonce: UByteArray, initialCounter: UInt = 0U) { companion object { + fun hChacha(key: UByteArray, nonce: UByteArray) : UIntArray { val state = UIntArray(16) { when (it) { @@ -79,6 +80,7 @@ internal class XChaCha20Pure { else -> 0U } } + hChaChaKey.overwriteWithZeroes() val blocks = message.size / 64 val remainder = message.size % 64 for (i in 0 until blocks) { @@ -98,4 +100,79 @@ internal class XChaCha20Pure { } + val state: UIntArray + val keystreamBuffer = UByteArray(64) { 0U} + var keystreamRemainingCounter = 0 + var processedBytesSoFar = 0 + + init { + val hChaChaKey = hChacha(key, nonce) + state = UIntArray(16) { + when (it) { + 0 -> ChaCha20Pure.sigma0_32 + 1 -> ChaCha20Pure.sigma1_32 + 2 -> ChaCha20Pure.sigma2_32 + 3 -> ChaCha20Pure.sigma3_32 + 4 -> hChaChaKey[0] + 5 -> hChaChaKey[1] + 6 -> hChaChaKey[2] + 7 -> hChaChaKey[3] + 8 -> hChaChaKey[4] + 9 -> hChaChaKey[5] + 10 -> hChaChaKey[6] + 11 -> hChaChaKey[7] + 12 -> initialCounter + 13 -> 0U + 14 -> nonce.fromLittleEndianArrayToUIntWithPosition(16) + 15 -> nonce.fromLittleEndianArrayToUIntWithPosition(20) + else -> 0U + } + } + hChaChaKey.overwriteWithZeroes() + } + + fun encryptPartialData(data: UByteArray) : UByteArray { + val ciphertext = UByteArray(data.size) { 0U } + //First use remaining keystream + var processedBytes = 0 + if (data.size > keystreamRemainingCounter) { + keystreamBuffer.xorWithPositionsAndInsertIntoArray( + 64 - keystreamRemainingCounter, 64, + data, 0, + ciphertext, 0 + ) + processedBytes += keystreamRemainingCounter + keystreamRemainingCounter = 0 + } + //Then do full blocks + var remainingBytes = data.size - processedBytes + for (i in 0 until remainingBytes / 64) { + ChaCha20Pure.hash(state).xorWithPositionsAndInsertIntoArray( + 0, 64, + data, processedBytes, + ciphertext, processedBytes + ) + state[12] += 1U + if (state[12] == 0U) { + state[13] += 1U + } + processedBytes += 64 + } + //Then do the remainder that didn't fit into 64byte blocks + remainingBytes = data.size - processedBytes + ChaCha20Pure.hash(state).copyInto(keystreamBuffer) + state[12] += 1U + if (state[12] == 0U) { + state[13] += 1U + } + keystreamBuffer.xorWithPositionsAndInsertIntoArray( + 0, remainingBytes, + data, processedBytes, + ciphertext, processedBytes + ) + keystreamRemainingCounter = 64 - remainingBytes + processedBytesSoFar += data.size + return ciphertext + } + } \ No newline at end of file diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/util/Util.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/util/Util.kt index 2a6be8f..13fe647 100644 --- a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/util/Util.kt +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/util/Util.kt @@ -18,7 +18,7 @@ package com.ionspin.kotlin.crypto.util - +//TODO Reorganize this, currently it's just a pile of useful helper functions val _emitIntArray: IntArray = intArrayOf(1) /** @@ -108,11 +108,16 @@ fun UByteArray.xorWithPositions(start: Int, end: Int, other : UByteArray, otherS return UByteArray(end - start) { this[start + it] xor other[otherStart + it] } } +/** + * Start index is included, end index is excluded + */ fun UByteArray.xorWithPositionsAndInsertIntoArray( start: Int, end: Int, other : UByteArray, otherStart: Int, - targetArray: UByteArray, targetStart : Int) { - for (i in start until end) { + targetArray: UByteArray, targetStart : Int +) { + val length = end - start + for (i in 0 until length) { targetArray[targetStart + i] = this[start + i] xor other[otherStart + i] } } @@ -340,6 +345,12 @@ operator fun UInt.plus(other : UByteArray) : UByteArray { return this.toLittleEndianUByteArray() + other } +fun UIntArray.overwriteWithZeroes() { + for (i in 0 until size) { + this[i] = 0U + } +} + //AES Flatten fun Collection.flattenToUByteArray(): UByteArray { val result = UByteArray(sumBy { it.size }) diff --git a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/authenticated/ChaCha20Poly1305Test.kt b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/authenticated/ChaCha20Poly1305Test.kt index cf19262..26975f4 100644 --- a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/authenticated/ChaCha20Poly1305Test.kt +++ b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/authenticated/ChaCha20Poly1305Test.kt @@ -1,56 +1,56 @@ -//package com.ionspin.kotlin.crypto.authenticated -// -//import com.ionspin.kotlin.crypto.hash.encodeToUByteArray -//import com.ionspin.kotlin.crypto.util.hexColumsPrint -//import kotlin.test.Test -//import kotlin.test.assertTrue -// -///** -// * Created by Ugljesa Jovanovic -// * ugljesa.jovanovic@ionspin.com -// * on 17-Jun-2020 -// */ -//class ChaCha20Poly1305Test { -// -// -// -// @Test -// fun chaCha20Poly1305() { -// val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " + -// "only one tip for the future, sunscreen would be it.").encodeToUByteArray() -// -// val additionalData = ubyteArrayOf( -// 0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U -// ) -// val key = ubyteArrayOf( -// 0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U, -// 0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU, -// 0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U, -// 0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU, -// ) -// -// val nonce = ubyteArrayOf( -// 0x07U, 0x00U, 0x00U, 0x00U, 0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U -// ) -// //Ciphertext + Poly1305TAG -// val expected = ubyteArrayOf( -// 0xd3U, 0x1aU, 0x8dU, 0x34U, 0x64U, 0x8eU, 0x60U, 0xdbU, 0x7bU, 0x86U, 0xafU, 0xbcU, 0x53U, 0xefU, 0x7eU, 0xc2U, -// 0xa4U, 0xadU, 0xedU, 0x51U, 0x29U, 0x6eU, 0x08U, 0xfeU, 0xa9U, 0xe2U, 0xb5U, 0xa7U, 0x36U, 0xeeU, 0x62U, 0xd6U, -// 0x3dU, 0xbeU, 0xa4U, 0x5eU, 0x8cU, 0xa9U, 0x67U, 0x12U, 0x82U, 0xfaU, 0xfbU, 0x69U, 0xdaU, 0x92U, 0x72U, 0x8bU, -// 0x1aU, 0x71U, 0xdeU, 0x0aU, 0x9eU, 0x06U, 0x0bU, 0x29U, 0x05U, 0xd6U, 0xa5U, 0xb6U, 0x7eU, 0xcdU, 0x3bU, 0x36U, -// 0x92U, 0xddU, 0xbdU, 0x7fU, 0x2dU, 0x77U, 0x8bU, 0x8cU, 0x98U, 0x03U, 0xaeU, 0xe3U, 0x28U, 0x09U, 0x1bU, 0x58U, -// 0xfaU, 0xb3U, 0x24U, 0xe4U, 0xfaU, 0xd6U, 0x75U, 0x94U, 0x55U, 0x85U, 0x80U, 0x8bU, 0x48U, 0x31U, 0xd7U, 0xbcU, -// 0x3fU, 0xf4U, 0xdeU, 0xf0U, 0x8eU, 0x4bU, 0x7aU, 0x9dU, 0xe5U, 0x76U, 0xd2U, 0x65U, 0x86U, 0xceU, 0xc6U, 0x4bU, -// 0x61U, 0x16U, 0x1aU, 0xe1U, 0x0bU, 0x59U, 0x4fU, 0x09U, 0xe2U, 0x6aU, 0x7eU, 0x90U, 0x2eU, 0xcbU, 0xd0U, 0x60U, -// 0x06U, 0x91U -// ) -// val result = ChaCha20Poly1305Pure.encrypt(key, nonce, message, additionalData) -// result.hexColumsPrint() -// assertTrue { -// result.contentEquals(expected) -// } -// -// } -// -// -//} \ No newline at end of file +package com.ionspin.kotlin.crypto.authenticated + +import com.ionspin.kotlin.crypto.hash.encodeToUByteArray +import com.ionspin.kotlin.crypto.util.hexColumsPrint +import kotlin.test.Test +import kotlin.test.assertTrue + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 17-Jun-2020 + */ +class ChaCha20Poly1305Test { + + + + @Test + fun chaCha20Poly1305() { + val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " + + "only one tip for the future, sunscreen would be it.").encodeToUByteArray() + + val additionalData = ubyteArrayOf( + 0x50U, 0x51U, 0x52U, 0x53U, 0xc0U, 0xc1U, 0xc2U, 0xc3U, 0xc4U, 0xc5U, 0xc6U, 0xc7U + ) + val key = ubyteArrayOf( + 0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U, + 0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU, + 0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U, + 0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU, + ) + + val nonce = ubyteArrayOf( + 0x07U, 0x00U, 0x00U, 0x00U, 0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U + ) + //Ciphertext + Poly1305TAG + val expected = ubyteArrayOf( + 0xd3U, 0x1aU, 0x8dU, 0x34U, 0x64U, 0x8eU, 0x60U, 0xdbU, 0x7bU, 0x86U, 0xafU, 0xbcU, 0x53U, 0xefU, 0x7eU, 0xc2U, + 0xa4U, 0xadU, 0xedU, 0x51U, 0x29U, 0x6eU, 0x08U, 0xfeU, 0xa9U, 0xe2U, 0xb5U, 0xa7U, 0x36U, 0xeeU, 0x62U, 0xd6U, + 0x3dU, 0xbeU, 0xa4U, 0x5eU, 0x8cU, 0xa9U, 0x67U, 0x12U, 0x82U, 0xfaU, 0xfbU, 0x69U, 0xdaU, 0x92U, 0x72U, 0x8bU, + 0x1aU, 0x71U, 0xdeU, 0x0aU, 0x9eU, 0x06U, 0x0bU, 0x29U, 0x05U, 0xd6U, 0xa5U, 0xb6U, 0x7eU, 0xcdU, 0x3bU, 0x36U, + 0x92U, 0xddU, 0xbdU, 0x7fU, 0x2dU, 0x77U, 0x8bU, 0x8cU, 0x98U, 0x03U, 0xaeU, 0xe3U, 0x28U, 0x09U, 0x1bU, 0x58U, + 0xfaU, 0xb3U, 0x24U, 0xe4U, 0xfaU, 0xd6U, 0x75U, 0x94U, 0x55U, 0x85U, 0x80U, 0x8bU, 0x48U, 0x31U, 0xd7U, 0xbcU, + 0x3fU, 0xf4U, 0xdeU, 0xf0U, 0x8eU, 0x4bU, 0x7aU, 0x9dU, 0xe5U, 0x76U, 0xd2U, 0x65U, 0x86U, 0xceU, 0xc6U, 0x4bU, + 0x61U, 0x16U, 0x1aU, 0xe1U, 0x0bU, 0x59U, 0x4fU, 0x09U, 0xe2U, 0x6aU, 0x7eU, 0x90U, 0x2eU, 0xcbU, 0xd0U, 0x60U, + 0x06U, 0x91U + ) + val result = ChaCha20Poly1305Pure.encrypt(key, nonce, message, additionalData) + result.hexColumsPrint() + assertTrue { + result.contentEquals(expected) + } + + } + + +} \ No newline at end of file diff --git a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/XChaCha20Test.kt b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/XChaCha20Test.kt index 2aec810..d745e41 100644 --- a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/XChaCha20Test.kt +++ b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/XChaCha20Test.kt @@ -1,5 +1,6 @@ package com.ionspin.kotlin.crypto.symmetric +import com.ionspin.kotlin.crypto.hash.encodeToUByteArray import com.ionspin.kotlin.crypto.util.hexColumsPrint import kotlin.test.Test import kotlin.test.assertTrue @@ -39,55 +40,96 @@ class XChaCha20Test { @Test fun testXChaCha20() { val key = ubyteArrayOf( - 0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U, 0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU, - 0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U, 0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU + 0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U, + 0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU, + 0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U, + 0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU ) val nonce = ubyteArrayOf( - 0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, + 0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, + 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, 0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x58U ) val message = ubyteArrayOf( - 0x54U, 0x68U, 0x65U, 0x20U, 0x64U, 0x68U, 0x6fU, 0x6cU, 0x65U, 0x20U, 0x28U, 0x70U, 0x72U, 0x6fU, 0x6eU, 0x6fU, - 0x75U, 0x6eU, 0x63U, 0x65U, 0x64U, 0x20U, 0x22U, 0x64U, 0x6fU, 0x6cU, 0x65U, 0x22U, 0x29U, 0x20U, 0x69U, 0x73U, - 0x20U, 0x61U, 0x6cU, 0x73U, 0x6fU, 0x20U, 0x6bU, 0x6eU, 0x6fU, 0x77U, 0x6eU, 0x20U, 0x61U, 0x73U, 0x20U, 0x74U, - 0x68U, 0x65U, 0x20U, 0x41U, 0x73U, 0x69U, 0x61U, 0x74U, 0x69U, 0x63U, 0x20U, 0x77U, 0x69U, 0x6cU, 0x64U, 0x20U, - 0x64U, 0x6fU, 0x67U, 0x2cU, 0x20U, 0x72U, 0x65U, 0x64U, 0x20U, 0x64U, 0x6fU, 0x67U, 0x2cU, 0x20U, 0x61U, 0x6eU, - 0x64U, 0x20U, 0x77U, 0x68U, 0x69U, 0x73U, 0x74U, 0x6cU, 0x69U, 0x6eU, 0x67U, 0x20U, 0x64U, 0x6fU, 0x67U, 0x2eU, - 0x20U, 0x49U, 0x74U, 0x20U, 0x69U, 0x73U, 0x20U, 0x61U, 0x62U, 0x6fU, 0x75U, 0x74U, 0x20U, 0x74U, 0x68U, 0x65U, - 0x20U, 0x73U, 0x69U, 0x7aU, 0x65U, 0x20U, 0x6fU, 0x66U, 0x20U, 0x61U, 0x20U, 0x47U, 0x65U, 0x72U, 0x6dU, 0x61U, - 0x6eU, 0x20U, 0x73U, 0x68U, 0x65U, 0x70U, 0x68U, 0x65U, 0x72U, 0x64U, 0x20U, 0x62U, 0x75U, 0x74U, 0x20U, 0x6cU, - 0x6fU, 0x6fU, 0x6bU, 0x73U, 0x20U, 0x6dU, 0x6fU, 0x72U, 0x65U, 0x20U, 0x6cU, 0x69U, 0x6bU, 0x65U, 0x20U, 0x61U, - 0x20U, 0x6cU, 0x6fU, 0x6eU, 0x67U, 0x2dU, 0x6cU, 0x65U, 0x67U, 0x67U, 0x65U, 0x64U, 0x20U, 0x66U, 0x6fU, 0x78U, - 0x2eU, 0x20U, 0x54U, 0x68U, 0x69U, 0x73U, 0x20U, 0x68U, 0x69U, 0x67U, 0x68U, 0x6cU, 0x79U, 0x20U, 0x65U, 0x6cU, - 0x75U, 0x73U, 0x69U, 0x76U, 0x65U, 0x20U, 0x61U, 0x6eU, 0x64U, 0x20U, 0x73U, 0x6bU, 0x69U, 0x6cU, 0x6cU, 0x65U, - 0x64U, 0x20U, 0x6aU, 0x75U, 0x6dU, 0x70U, 0x65U, 0x72U, 0x20U, 0x69U, 0x73U, 0x20U, 0x63U, 0x6cU, 0x61U, 0x73U, - 0x73U, 0x69U, 0x66U, 0x69U, 0x65U, 0x64U, 0x20U, 0x77U, 0x69U, 0x74U, 0x68U, 0x20U, 0x77U, 0x6fU, 0x6cU, 0x76U, - 0x65U, 0x73U, 0x2cU, 0x20U, 0x63U, 0x6fU, 0x79U, 0x6fU, 0x74U, 0x65U, 0x73U, 0x2cU, 0x20U, 0x6aU, 0x61U, 0x63U, - 0x6bU, 0x61U, 0x6cU, 0x73U, 0x2cU, 0x20U, 0x61U, 0x6eU, 0x64U, 0x20U, 0x66U, 0x6fU, 0x78U, 0x65U, 0x73U, 0x20U, - 0x69U, 0x6eU, 0x20U, 0x74U, 0x68U, 0x65U, 0x20U, 0x74U, 0x61U, 0x78U, 0x6fU, 0x6eU, 0x6fU, 0x6dU, 0x69U, 0x63U, - 0x20U, 0x66U, 0x61U, 0x6dU, 0x69U, 0x6cU, 0x79U, 0x20U, 0x43U, 0x61U, 0x6eU, 0x69U, 0x64U, 0x61U, 0x65U, 0x2eU, + 0x54U, 0x68U, 0x65U, 0x20U, 0x64U, 0x68U, 0x6fU, 0x6cU, + 0x65U, 0x20U, 0x28U, 0x70U, 0x72U, 0x6fU, 0x6eU, 0x6fU, + 0x75U, 0x6eU, 0x63U, 0x65U, 0x64U, 0x20U, 0x22U, 0x64U, + 0x6fU, 0x6cU, 0x65U, 0x22U, 0x29U, 0x20U, 0x69U, 0x73U, + 0x20U, 0x61U, 0x6cU, 0x73U, 0x6fU, 0x20U, 0x6bU, 0x6eU, + 0x6fU, 0x77U, 0x6eU, 0x20U, 0x61U, 0x73U, 0x20U, 0x74U, + 0x68U, 0x65U, 0x20U, 0x41U, 0x73U, 0x69U, 0x61U, 0x74U, + 0x69U, 0x63U, 0x20U, 0x77U, 0x69U, 0x6cU, 0x64U, 0x20U, + 0x64U, 0x6fU, 0x67U, 0x2cU, 0x20U, 0x72U, 0x65U, 0x64U, + 0x20U, 0x64U, 0x6fU, 0x67U, 0x2cU, 0x20U, 0x61U, 0x6eU, + 0x64U, 0x20U, 0x77U, 0x68U, 0x69U, 0x73U, 0x74U, 0x6cU, + 0x69U, 0x6eU, 0x67U, 0x20U, 0x64U, 0x6fU, 0x67U, 0x2eU, + 0x20U, 0x49U, 0x74U, 0x20U, 0x69U, 0x73U, 0x20U, 0x61U, + 0x62U, 0x6fU, 0x75U, 0x74U, 0x20U, 0x74U, 0x68U, 0x65U, + 0x20U, 0x73U, 0x69U, 0x7aU, 0x65U, 0x20U, 0x6fU, 0x66U, + 0x20U, 0x61U, 0x20U, 0x47U, 0x65U, 0x72U, 0x6dU, 0x61U, + 0x6eU, 0x20U, 0x73U, 0x68U, 0x65U, 0x70U, 0x68U, 0x65U, + 0x72U, 0x64U, 0x20U, 0x62U, 0x75U, 0x74U, 0x20U, 0x6cU, + 0x6fU, 0x6fU, 0x6bU, 0x73U, 0x20U, 0x6dU, 0x6fU, 0x72U, + 0x65U, 0x20U, 0x6cU, 0x69U, 0x6bU, 0x65U, 0x20U, 0x61U, + 0x20U, 0x6cU, 0x6fU, 0x6eU, 0x67U, 0x2dU, 0x6cU, 0x65U, + 0x67U, 0x67U, 0x65U, 0x64U, 0x20U, 0x66U, 0x6fU, 0x78U, + 0x2eU, 0x20U, 0x54U, 0x68U, 0x69U, 0x73U, 0x20U, 0x68U, + 0x69U, 0x67U, 0x68U, 0x6cU, 0x79U, 0x20U, 0x65U, 0x6cU, + 0x75U, 0x73U, 0x69U, 0x76U, 0x65U, 0x20U, 0x61U, 0x6eU, + 0x64U, 0x20U, 0x73U, 0x6bU, 0x69U, 0x6cU, 0x6cU, 0x65U, + 0x64U, 0x20U, 0x6aU, 0x75U, 0x6dU, 0x70U, 0x65U, 0x72U, + 0x20U, 0x69U, 0x73U, 0x20U, 0x63U, 0x6cU, 0x61U, 0x73U, + 0x73U, 0x69U, 0x66U, 0x69U, 0x65U, 0x64U, 0x20U, 0x77U, + 0x69U, 0x74U, 0x68U, 0x20U, 0x77U, 0x6fU, 0x6cU, 0x76U, + 0x65U, 0x73U, 0x2cU, 0x20U, 0x63U, 0x6fU, 0x79U, 0x6fU, + 0x74U, 0x65U, 0x73U, 0x2cU, 0x20U, 0x6aU, 0x61U, 0x63U, + 0x6bU, 0x61U, 0x6cU, 0x73U, 0x2cU, 0x20U, 0x61U, 0x6eU, + 0x64U, 0x20U, 0x66U, 0x6fU, 0x78U, 0x65U, 0x73U, 0x20U, + 0x69U, 0x6eU, 0x20U, 0x74U, 0x68U, 0x65U, 0x20U, 0x74U, + 0x61U, 0x78U, 0x6fU, 0x6eU, 0x6fU, 0x6dU, 0x69U, 0x63U, + 0x20U, 0x66U, 0x61U, 0x6dU, 0x69U, 0x6cU, 0x79U, 0x20U, + 0x43U, 0x61U, 0x6eU, 0x69U, 0x64U, 0x61U, 0x65U, 0x2eU, ) val expected = ubyteArrayOf( - 0x7dU, 0x0aU, 0x2eU, 0x6bU, 0x7fU, 0x7cU, 0x65U, 0xa2U, 0x36U, 0x54U, 0x26U, 0x30U, 0x29U, 0x4eU, 0x06U, 0x3bU, - 0x7aU, 0xb9U, 0xb5U, 0x55U, 0xa5U, 0xd5U, 0x14U, 0x9aU, 0xa2U, 0x1eU, 0x4aU, 0xe1U, 0xe4U, 0xfbU, 0xceU, 0x87U, - 0xecU, 0xc8U, 0xe0U, 0x8aU, 0x8bU, 0x5eU, 0x35U, 0x0aU, 0xbeU, 0x62U, 0x2bU, 0x2fU, 0xfaU, 0x61U, 0x7bU, 0x20U, - 0x2cU, 0xfaU, 0xd7U, 0x20U, 0x32U, 0xa3U, 0x03U, 0x7eU, 0x76U, 0xffU, 0xdcU, 0xdcU, 0x43U, 0x76U, 0xeeU, 0x05U, - 0x3aU, 0x19U, 0x0dU, 0x7eU, 0x46U, 0xcaU, 0x1dU, 0xe0U, 0x41U, 0x44U, 0x85U, 0x03U, 0x81U, 0xb9U, 0xcbU, 0x29U, - 0xf0U, 0x51U, 0x91U, 0x53U, 0x86U, 0xb8U, 0xa7U, 0x10U, 0xb8U, 0xacU, 0x4dU, 0x02U, 0x7bU, 0x8bU, 0x05U, 0x0fU, - 0x7cU, 0xbaU, 0x58U, 0x54U, 0xe0U, 0x28U, 0xd5U, 0x64U, 0xe4U, 0x53U, 0xb8U, 0xa9U, 0x68U, 0x82U, 0x41U, 0x73U, - 0xfcU, 0x16U, 0x48U, 0x8bU, 0x89U, 0x70U, 0xcaU, 0xc8U, 0x28U, 0xf1U, 0x1aU, 0xe5U, 0x3cU, 0xabU, 0xd2U, 0x01U, - 0x12U, 0xf8U, 0x71U, 0x07U, 0xdfU, 0x24U, 0xeeU, 0x61U, 0x83U, 0xd2U, 0x27U, 0x4fU, 0xe4U, 0xc8U, 0xb1U, 0x48U, - 0x55U, 0x34U, 0xefU, 0x2cU, 0x5fU, 0xbcU, 0x1eU, 0xc2U, 0x4bU, 0xfcU, 0x36U, 0x63U, 0xefU, 0xaaU, 0x08U, 0xbcU, - 0x04U, 0x7dU, 0x29U, 0xd2U, 0x50U, 0x43U, 0x53U, 0x2dU, 0xb8U, 0x39U, 0x1aU, 0x8aU, 0x3dU, 0x77U, 0x6bU, 0xf4U, - 0x37U, 0x2aU, 0x69U, 0x55U, 0x82U, 0x7cU, 0xcbU, 0x0cU, 0xddU, 0x4aU, 0xf4U, 0x03U, 0xa7U, 0xceU, 0x4cU, 0x63U, - 0xd5U, 0x95U, 0xc7U, 0x5aU, 0x43U, 0xe0U, 0x45U, 0xf0U, 0xccU, 0xe1U, 0xf2U, 0x9cU, 0x8bU, 0x93U, 0xbdU, 0x65U, - 0xafU, 0xc5U, 0x97U, 0x49U, 0x22U, 0xf2U, 0x14U, 0xa4U, 0x0bU, 0x7cU, 0x40U, 0x2cU, 0xdbU, 0x91U, 0xaeU, 0x73U, - 0xc0U, 0xb6U, 0x36U, 0x15U, 0xcdU, 0xadU, 0x04U, 0x80U, 0x68U, 0x0fU, 0x16U, 0x51U, 0x5aU, 0x7aU, 0xceU, 0x9dU, - 0x39U, 0x23U, 0x64U, 0x64U, 0x32U, 0x8aU, 0x37U, 0x74U, 0x3fU, 0xfcU, 0x28U, 0xf4U, 0xddU, 0xb3U, 0x24U, 0xf4U, - 0xd0U, 0xf5U, 0xbbU, 0xdcU, 0x27U, 0x0cU, 0x65U, 0xb1U, 0x74U, 0x9aU, 0x6eU, 0xffU, 0xf1U, 0xfbU, 0xaaU, 0x09U, - 0x53U, 0x61U, 0x75U, 0xccU, 0xd2U, 0x9fU, 0xb9U, 0xe6U, 0x05U, 0x7bU, 0x30U, 0x73U, 0x20U, 0xd3U, 0x16U, 0x83U, - 0x8aU, 0x9cU, 0x71U, 0xf7U, 0x0bU, 0x5bU, 0x59U, 0x07U, 0xa6U, 0x6fU, 0x7eU, 0xa4U, 0x9aU, 0xadU, 0xc4U, 0x09U, + 0x7dU, 0x0aU, 0x2eU, 0x6bU, 0x7fU, 0x7cU, 0x65U, 0xa2U, + 0x36U, 0x54U, 0x26U, 0x30U, 0x29U, 0x4eU, 0x06U, 0x3bU, + 0x7aU, 0xb9U, 0xb5U, 0x55U, 0xa5U, 0xd5U, 0x14U, 0x9aU, + 0xa2U, 0x1eU, 0x4aU, 0xe1U, 0xe4U, 0xfbU, 0xceU, 0x87U, + 0xecU, 0xc8U, 0xe0U, 0x8aU, 0x8bU, 0x5eU, 0x35U, 0x0aU, + 0xbeU, 0x62U, 0x2bU, 0x2fU, 0xfaU, 0x61U, 0x7bU, 0x20U, + 0x2cU, 0xfaU, 0xd7U, 0x20U, 0x32U, 0xa3U, 0x03U, 0x7eU, + 0x76U, 0xffU, 0xdcU, 0xdcU, 0x43U, 0x76U, 0xeeU, 0x05U, + 0x3aU, 0x19U, 0x0dU, 0x7eU, 0x46U, 0xcaU, 0x1dU, 0xe0U, + 0x41U, 0x44U, 0x85U, 0x03U, 0x81U, 0xb9U, 0xcbU, 0x29U, + 0xf0U, 0x51U, 0x91U, 0x53U, 0x86U, 0xb8U, 0xa7U, 0x10U, + 0xb8U, 0xacU, 0x4dU, 0x02U, 0x7bU, 0x8bU, 0x05U, 0x0fU, + 0x7cU, 0xbaU, 0x58U, 0x54U, 0xe0U, 0x28U, 0xd5U, 0x64U, + 0xe4U, 0x53U, 0xb8U, 0xa9U, 0x68U, 0x82U, 0x41U, 0x73U, + 0xfcU, 0x16U, 0x48U, 0x8bU, 0x89U, 0x70U, 0xcaU, 0xc8U, + 0x28U, 0xf1U, 0x1aU, 0xe5U, 0x3cU, 0xabU, 0xd2U, 0x01U, + 0x12U, 0xf8U, 0x71U, 0x07U, 0xdfU, 0x24U, 0xeeU, 0x61U, + 0x83U, 0xd2U, 0x27U, 0x4fU, 0xe4U, 0xc8U, 0xb1U, 0x48U, + 0x55U, 0x34U, 0xefU, 0x2cU, 0x5fU, 0xbcU, 0x1eU, 0xc2U, + 0x4bU, 0xfcU, 0x36U, 0x63U, 0xefU, 0xaaU, 0x08U, 0xbcU, + 0x04U, 0x7dU, 0x29U, 0xd2U, 0x50U, 0x43U, 0x53U, 0x2dU, + 0xb8U, 0x39U, 0x1aU, 0x8aU, 0x3dU, 0x77U, 0x6bU, 0xf4U, + 0x37U, 0x2aU, 0x69U, 0x55U, 0x82U, 0x7cU, 0xcbU, 0x0cU, + 0xddU, 0x4aU, 0xf4U, 0x03U, 0xa7U, 0xceU, 0x4cU, 0x63U, + 0xd5U, 0x95U, 0xc7U, 0x5aU, 0x43U, 0xe0U, 0x45U, 0xf0U, + 0xccU, 0xe1U, 0xf2U, 0x9cU, 0x8bU, 0x93U, 0xbdU, 0x65U, + 0xafU, 0xc5U, 0x97U, 0x49U, 0x22U, 0xf2U, 0x14U, 0xa4U, + 0x0bU, 0x7cU, 0x40U, 0x2cU, 0xdbU, 0x91U, 0xaeU, 0x73U, + 0xc0U, 0xb6U, 0x36U, 0x15U, 0xcdU, 0xadU, 0x04U, 0x80U, + 0x68U, 0x0fU, 0x16U, 0x51U, 0x5aU, 0x7aU, 0xceU, 0x9dU, + 0x39U, 0x23U, 0x64U, 0x64U, 0x32U, 0x8aU, 0x37U, 0x74U, + 0x3fU, 0xfcU, 0x28U, 0xf4U, 0xddU, 0xb3U, 0x24U, 0xf4U, + 0xd0U, 0xf5U, 0xbbU, 0xdcU, 0x27U, 0x0cU, 0x65U, 0xb1U, + 0x74U, 0x9aU, 0x6eU, 0xffU, 0xf1U, 0xfbU, 0xaaU, 0x09U, + 0x53U, 0x61U, 0x75U, 0xccU, 0xd2U, 0x9fU, 0xb9U, 0xe6U, + 0x05U, 0x7bU, 0x30U, 0x73U, 0x20U, 0xd3U, 0x16U, 0x83U, + 0x8aU, 0x9cU, 0x71U, 0xf7U, 0x0bU, 0x5bU, 0x59U, 0x07U, + 0xa6U, 0x6fU, 0x7eU, 0xa4U, 0x9aU, 0xadU, 0xc4U, 0x09U, ) @@ -98,4 +140,202 @@ class XChaCha20Test { } + @Test + fun testXChaCha20Updateable() { + val key = ubyteArrayOf( + 0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U, + 0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU, + 0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U, + 0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU + ) + val nonce = ubyteArrayOf( + 0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, + 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, + 0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x58U + ) + val message = ubyteArrayOf( + 0x54U, 0x68U, 0x65U, 0x20U, 0x64U, 0x68U, 0x6fU, 0x6cU, + 0x65U, 0x20U, 0x28U, 0x70U, 0x72U, 0x6fU, 0x6eU, 0x6fU, + 0x75U, 0x6eU, 0x63U, 0x65U, 0x64U, 0x20U, 0x22U, 0x64U, + 0x6fU, 0x6cU, 0x65U, 0x22U, 0x29U, 0x20U, 0x69U, 0x73U, + 0x20U, 0x61U, 0x6cU, 0x73U, 0x6fU, 0x20U, 0x6bU, 0x6eU, + 0x6fU, 0x77U, 0x6eU, 0x20U, 0x61U, 0x73U, 0x20U, 0x74U, + 0x68U, 0x65U, 0x20U, 0x41U, 0x73U, 0x69U, 0x61U, 0x74U, + 0x69U, 0x63U, 0x20U, 0x77U, 0x69U, 0x6cU, 0x64U, 0x20U, + 0x64U, 0x6fU, 0x67U, 0x2cU, 0x20U, 0x72U, 0x65U, 0x64U, + 0x20U, 0x64U, 0x6fU, 0x67U, 0x2cU, 0x20U, 0x61U, 0x6eU, + 0x64U, 0x20U, 0x77U, 0x68U, 0x69U, 0x73U, 0x74U, 0x6cU, + 0x69U, 0x6eU, 0x67U, 0x20U, 0x64U, 0x6fU, 0x67U, 0x2eU, + 0x20U, 0x49U, 0x74U, 0x20U, 0x69U, 0x73U, 0x20U, 0x61U, + 0x62U, 0x6fU, 0x75U, 0x74U, 0x20U, 0x74U, 0x68U, 0x65U, + 0x20U, 0x73U, 0x69U, 0x7aU, 0x65U, 0x20U, 0x6fU, 0x66U, + 0x20U, 0x61U, 0x20U, 0x47U, 0x65U, 0x72U, 0x6dU, 0x61U, + 0x6eU, 0x20U, 0x73U, 0x68U, 0x65U, 0x70U, 0x68U, 0x65U, + 0x72U, 0x64U, 0x20U, 0x62U, 0x75U, 0x74U, 0x20U, 0x6cU, + 0x6fU, 0x6fU, 0x6bU, 0x73U, 0x20U, 0x6dU, 0x6fU, 0x72U, + 0x65U, 0x20U, 0x6cU, 0x69U, 0x6bU, 0x65U, 0x20U, 0x61U, + 0x20U, 0x6cU, 0x6fU, 0x6eU, 0x67U, 0x2dU, 0x6cU, 0x65U, + 0x67U, 0x67U, 0x65U, 0x64U, 0x20U, 0x66U, 0x6fU, 0x78U, + 0x2eU, 0x20U, 0x54U, 0x68U, 0x69U, 0x73U, 0x20U, 0x68U, + 0x69U, 0x67U, 0x68U, 0x6cU, 0x79U, 0x20U, 0x65U, 0x6cU, + 0x75U, 0x73U, 0x69U, 0x76U, 0x65U, 0x20U, 0x61U, 0x6eU, + 0x64U, 0x20U, 0x73U, 0x6bU, 0x69U, 0x6cU, 0x6cU, 0x65U, + 0x64U, 0x20U, 0x6aU, 0x75U, 0x6dU, 0x70U, 0x65U, 0x72U, + 0x20U, 0x69U, 0x73U, 0x20U, 0x63U, 0x6cU, 0x61U, 0x73U, + 0x73U, 0x69U, 0x66U, 0x69U, 0x65U, 0x64U, 0x20U, 0x77U, + 0x69U, 0x74U, 0x68U, 0x20U, 0x77U, 0x6fU, 0x6cU, 0x76U, + 0x65U, 0x73U, 0x2cU, 0x20U, 0x63U, 0x6fU, 0x79U, 0x6fU, + 0x74U, 0x65U, 0x73U, 0x2cU, 0x20U, 0x6aU, 0x61U, 0x63U, + 0x6bU, 0x61U, 0x6cU, 0x73U, 0x2cU, 0x20U, 0x61U, 0x6eU, + 0x64U, 0x20U, 0x66U, 0x6fU, 0x78U, 0x65U, 0x73U, 0x20U, + 0x69U, 0x6eU, 0x20U, 0x74U, 0x68U, 0x65U, 0x20U, 0x74U, + 0x61U, 0x78U, 0x6fU, 0x6eU, 0x6fU, 0x6dU, 0x69U, 0x63U, + 0x20U, 0x66U, 0x61U, 0x6dU, 0x69U, 0x6cU, 0x79U, 0x20U, + 0x43U, 0x61U, 0x6eU, 0x69U, 0x64U, 0x61U, 0x65U, 0x2eU, + ) + + val expected = ubyteArrayOf( + 0x7dU, 0x0aU, 0x2eU, 0x6bU, 0x7fU, 0x7cU, 0x65U, 0xa2U, + 0x36U, 0x54U, 0x26U, 0x30U, 0x29U, 0x4eU, 0x06U, 0x3bU, + 0x7aU, 0xb9U, 0xb5U, 0x55U, 0xa5U, 0xd5U, 0x14U, 0x9aU, + 0xa2U, 0x1eU, 0x4aU, 0xe1U, 0xe4U, 0xfbU, 0xceU, 0x87U, + 0xecU, 0xc8U, 0xe0U, 0x8aU, 0x8bU, 0x5eU, 0x35U, 0x0aU, + 0xbeU, 0x62U, 0x2bU, 0x2fU, 0xfaU, 0x61U, 0x7bU, 0x20U, + 0x2cU, 0xfaU, 0xd7U, 0x20U, 0x32U, 0xa3U, 0x03U, 0x7eU, + 0x76U, 0xffU, 0xdcU, 0xdcU, 0x43U, 0x76U, 0xeeU, 0x05U, + 0x3aU, 0x19U, 0x0dU, 0x7eU, 0x46U, 0xcaU, 0x1dU, 0xe0U, + 0x41U, 0x44U, 0x85U, 0x03U, 0x81U, 0xb9U, 0xcbU, 0x29U, + 0xf0U, 0x51U, 0x91U, 0x53U, 0x86U, 0xb8U, 0xa7U, 0x10U, + 0xb8U, 0xacU, 0x4dU, 0x02U, 0x7bU, 0x8bU, 0x05U, 0x0fU, + 0x7cU, 0xbaU, 0x58U, 0x54U, 0xe0U, 0x28U, 0xd5U, 0x64U, + 0xe4U, 0x53U, 0xb8U, 0xa9U, 0x68U, 0x82U, 0x41U, 0x73U, + 0xfcU, 0x16U, 0x48U, 0x8bU, 0x89U, 0x70U, 0xcaU, 0xc8U, + 0x28U, 0xf1U, 0x1aU, 0xe5U, 0x3cU, 0xabU, 0xd2U, 0x01U, + 0x12U, 0xf8U, 0x71U, 0x07U, 0xdfU, 0x24U, 0xeeU, 0x61U, + 0x83U, 0xd2U, 0x27U, 0x4fU, 0xe4U, 0xc8U, 0xb1U, 0x48U, + 0x55U, 0x34U, 0xefU, 0x2cU, 0x5fU, 0xbcU, 0x1eU, 0xc2U, + 0x4bU, 0xfcU, 0x36U, 0x63U, 0xefU, 0xaaU, 0x08U, 0xbcU, + 0x04U, 0x7dU, 0x29U, 0xd2U, 0x50U, 0x43U, 0x53U, 0x2dU, + 0xb8U, 0x39U, 0x1aU, 0x8aU, 0x3dU, 0x77U, 0x6bU, 0xf4U, + 0x37U, 0x2aU, 0x69U, 0x55U, 0x82U, 0x7cU, 0xcbU, 0x0cU, + 0xddU, 0x4aU, 0xf4U, 0x03U, 0xa7U, 0xceU, 0x4cU, 0x63U, + 0xd5U, 0x95U, 0xc7U, 0x5aU, 0x43U, 0xe0U, 0x45U, 0xf0U, + 0xccU, 0xe1U, 0xf2U, 0x9cU, 0x8bU, 0x93U, 0xbdU, 0x65U, + 0xafU, 0xc5U, 0x97U, 0x49U, 0x22U, 0xf2U, 0x14U, 0xa4U, + 0x0bU, 0x7cU, 0x40U, 0x2cU, 0xdbU, 0x91U, 0xaeU, 0x73U, + 0xc0U, 0xb6U, 0x36U, 0x15U, 0xcdU, 0xadU, 0x04U, 0x80U, + 0x68U, 0x0fU, 0x16U, 0x51U, 0x5aU, 0x7aU, 0xceU, 0x9dU, + 0x39U, 0x23U, 0x64U, 0x64U, 0x32U, 0x8aU, 0x37U, 0x74U, + 0x3fU, 0xfcU, 0x28U, 0xf4U, 0xddU, 0xb3U, 0x24U, 0xf4U, + 0xd0U, 0xf5U, 0xbbU, 0xdcU, 0x27U, 0x0cU, 0x65U, 0xb1U, + 0x74U, 0x9aU, 0x6eU, 0xffU, 0xf1U, 0xfbU, 0xaaU, 0x09U, + 0x53U, 0x61U, 0x75U, 0xccU, 0xd2U, 0x9fU, 0xb9U, 0xe6U, + 0x05U, 0x7bU, 0x30U, 0x73U, 0x20U, 0xd3U, 0x16U, 0x83U, + 0x8aU, 0x9cU, 0x71U, 0xf7U, 0x0bU, 0x5bU, 0x59U, 0x07U, + 0xa6U, 0x6fU, 0x7eU, 0xa4U, 0x9aU, 0xadU, 0xc4U, 0x09U, + + ) + + val xChaCha = XChaCha20Pure(key, nonce, 1U) + val firstChunk = xChaCha.encryptPartialData(message.sliceArray(0 until 5)) + val secondChunk = xChaCha.encryptPartialData(message.sliceArray(5 until 90)) + val thirdChunk = xChaCha.encryptPartialData(message.sliceArray(90 until message.size)) + + assertTrue { + (firstChunk + secondChunk + thirdChunk).contentEquals(expected) + } + + } + + @Test + fun testXChaCha20UpdateableLonger() { + val key = ubyteArrayOf( + 0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U, + 0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU, + 0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U, + 0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU + ) + val nonce = ubyteArrayOf( + 0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, + 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, + 0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x58U + ) + val message = ("This is a longer message that should cover all cases in the updateable algorithm. This string is 112 bytes long." + + "This is a longer message that should cover all cases in the updateable algorithm. This string is 112 bytes long." + + "This is a longer message that should cover all cases in the updateable algorithm. This string is 112 bytes long." + + "This is a longer message that should cover all cases in the updateable algorithm. This string is 112 bytes long.").encodeToUByteArray() + + val expected = ubyteArrayOf( + 0x7DU, 0x0AU, 0x22U, 0x38U, 0x3BU, 0x7DU, 0x79U, 0xEEU, + 0x32U, 0x54U, 0x62U, 0x2FU, 0x35U, 0x46U, 0x0DU, 0x26U, + 0x2FU, 0xBAU, 0xB3U, 0x43U, 0xB2U, 0x94U, 0x51U, 0x9BU, + 0xEDU, 0x06U, 0x47U, 0xA2U, 0xB9U, 0xFBU, 0xD4U, 0x9CU, + 0xA3U, 0xDCU, 0xE0U, 0x9DU, 0xC4U, 0x1DU, 0x31U, 0x12U, + 0xB4U, 0x67U, 0x65U, 0x6EU, 0xF7U, 0x7EU, 0x7BU, 0x37U, + 0x25U, 0xECU, 0x92U, 0x12U, 0x61U, 0xA3U, 0x0CU, 0x2AU, + 0x6BU, 0xF4U, 0x99U, 0x8BU, 0x5FU, 0x6AU, 0xEEU, 0x44U, + 0x2AU, 0x13U, 0x0BU, 0x30U, 0x0AU, 0xDDU, 0x58U, 0xE5U, + 0x0DU, 0x47U, 0x85U, 0x16U, 0xC4U, 0xEDU, 0xC2U, 0x2AU, + 0xBAU, 0x51U, 0xB2U, 0x53U, 0x86U, 0xB8U, 0xF3U, 0x0FU, + 0xA5U, 0xB0U, 0x43U, 0x4CU, 0x78U, 0xC4U, 0x0BU, 0x52U, + 0x7CU, 0xC2U, 0x1DU, 0x46U, 0xA9U, 0x39U, 0x8CU, 0x71U, + 0xE3U, 0x4FU, 0xEDU, 0xB1U, 0x27U, 0x98U, 0x4EU, 0x38U, + 0x88U, 0x0DU, 0x48U, 0x82U, 0xCCU, 0x39U, 0xD6U, 0x8EU, + 0x69U, 0xB0U, 0x56U, 0xCDU, 0x37U, 0xBEU, 0xDAU, 0x12U, + 0x5CU, 0xB5U, 0x67U, 0x1CU, 0xC9U, 0x35U, 0xE1U, 0x61U, + 0xD1U, 0xC2U, 0x6FU, 0x4CU, 0xE5U, 0x9CU, 0xE2U, 0x4CU, + 0x55U, 0x2EU, 0xE8U, 0x3BU, 0x5FU, 0xB2U, 0x1EU, 0xC6U, + 0x4BU, 0xAEU, 0x7AU, 0x6BU, 0xE8U, 0xA3U, 0x08U, 0xBEU, + 0x45U, 0x62U, 0x23U, 0xCFU, 0x17U, 0x07U, 0x51U, 0x68U, + 0xABU, 0x36U, 0x1AU, 0xCEU, 0x68U, 0x61U, 0x60U, 0xEDU, + 0x6DU, 0x6FU, 0x5CU, 0x5FU, 0x87U, 0x6AU, 0xCBU, 0x05U, + 0xD8U, 0x4AU, 0xF3U, 0x1DU, 0xB7U, 0x9AU, 0x41U, 0x62U, + 0x8EU, 0xC6U, 0xFAU, 0x44U, 0x4FU, 0xB3U, 0x04U, 0xEDU, + 0xDCU, 0xB3U, 0xE8U, 0x99U, 0x85U, 0xDFU, 0xB8U, 0x73U, + 0xEBU, 0xD4U, 0xCCU, 0x0EU, 0x6FU, 0xE0U, 0x08U, 0xA2U, + 0x4EU, 0x66U, 0x13U, 0x60U, 0xD7U, 0x93U, 0xA8U, 0x2EU, + 0xE7U, 0xB7U, 0x39U, 0x0FU, 0x88U, 0xA0U, 0x57U, 0xD7U, + 0x60U, 0x5BU, 0x12U, 0x1EU, 0x43U, 0x72U, 0xC7U, 0x99U, + 0x7CU, 0x3DU, 0x2DU, 0x37U, 0x22U, 0x84U, 0x29U, 0x7EU, + 0x6BU, 0xEDU, 0x33U, 0xB9U, 0x89U, 0xF9U, 0x36U, 0xFFU, + 0xD4U, 0xE1U, 0xBBU, 0xCBU, 0x2BU, 0x4FU, 0x6BU, 0xA9U, + 0x75U, 0xC8U, 0x28U, 0xF1U, 0xE5U, 0xF2U, 0xF9U, 0x4AU, + 0x5BU, 0x7CU, 0x30U, 0xCBU, 0x9AU, 0x93U, 0xF7U, 0xB2U, + 0x10U, 0x6BU, 0x3AU, 0x3DU, 0x3AU, 0xCEU, 0x1BU, 0x81U, + 0xDEU, 0x9FU, 0x71U, 0xF8U, 0x0EU, 0x52U, 0x00U, 0x46U, + 0x89U, 0x69U, 0x7FU, 0xBFU, 0x97U, 0xB8U, 0xC9U, 0x4AU, + 0x3AU, 0x37U, 0x31U, 0x1EU, 0x88U, 0x68U, 0x35U, 0x98U, + 0x76U, 0x93U, 0xCDU, 0x91U, 0xF7U, 0x6AU, 0x59U, 0xE6U, + 0x82U, 0xB6U, 0x85U, 0x67U, 0x3FU, 0xF5U, 0x9EU, 0x82U, + 0x2DU, 0xFFU, 0x81U, 0x5EU, 0xEAU, 0x3BU, 0xCCU, 0xFBU, + 0x1BU, 0x87U, 0x4AU, 0x93U, 0x40U, 0x96U, 0x3CU, 0xB2U, + 0x8EU, 0xCCU, 0x38U, 0x00U, 0x3FU, 0xBAU, 0xCCU, 0x84U, + 0x88U, 0x2BU, 0xF0U, 0x11U, 0x09U, 0xD5U, 0xAAU, 0x54U, + 0x3AU, 0x5BU, 0x98U, 0xE6U, 0xADU, 0xC0U, 0xB9U, 0x95U, + 0x53U, 0xDFU, 0x9DU, 0x91U, 0x01U, 0x66U, 0x7CU, 0xB3U, + 0xD8U, 0x2BU, 0x2DU, 0xBCU, 0xE0U, 0x77U, 0x71U, 0x59U, + 0x36U, 0xACU, 0x6DU, 0x5EU, 0x55U, 0xC9U, 0x29U, 0x40U, + 0xD4U, 0xA2U, 0x5BU, 0xBDU, 0xC2U, 0xE2U, 0x98U, 0x3DU, + 0x8CU, 0x9FU, 0x07U, 0xE4U, 0x21U, 0x84U, 0x4CU, 0x12U, + 0x83U, 0x77U, 0x88U, 0x06U, 0xA4U, 0x6FU, 0xDFU, 0x9EU, + 0xF5U, 0xD3U, 0xE1U, 0xFCU, 0x49U, 0x66U, 0x36U, 0x96U, + 0x48U, 0xC7U, 0x32U, 0xBAU, 0x73U, 0xFFU, 0xEFU, 0xCCU, + 0x00U, 0xC2U, 0x56U, 0x9CU, 0xD0U, 0x70U, 0x2AU, 0x4FU, + 0x82U, 0xB4U, 0x0BU, 0x68U, 0xEAU, 0xC1U, 0x87U, 0xB3U, + + ) + + val xChaCha = XChaCha20Pure(key, nonce, 1U) + val firstChunk = xChaCha.encryptPartialData(message.sliceArray(0 until 50)) + val secondChunk = xChaCha.encryptPartialData(message.sliceArray(50 until 200)) + val thirdChunk = xChaCha.encryptPartialData(message.sliceArray(200 until message.size)) + val result = (firstChunk + secondChunk + thirdChunk) + assertTrue { + result.contentEquals(expected) + } + + + + } + } \ No newline at end of file