Adding xchacha20 updateable, and tests

This commit is contained in:
Ugljesa Jovanovic 2020-06-21 19:51:21 +02:00 committed by Ugljesa Jovanovic
parent 1a4fc90922
commit 6fae2fd061
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
9 changed files with 468 additions and 152 deletions

View File

@ -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 {

View File

@ -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
}
}

View File

@ -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 {
//
// }
}

View File

@ -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

View File

@ -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) {

View File

@ -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
}
}

View File

@ -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<UByteArray>.flattenToUByteArray(): UByteArray {
val result = UByteArray(sumBy { it.size })

View File

@ -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)
// }
//
// }
//
//
//}
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)
}
}
}

View File

@ -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)
}
}
}