diff --git a/multiplatform-crypto-delegated/src/commonMain/kotlin/com/ionspin/kotlin/crypto/Crypto.kt b/multiplatform-crypto-delegated/src/commonMain/kotlin/com/ionspin/kotlin/crypto/Crypto.kt index 82ccef8..7d162f7 100644 --- a/multiplatform-crypto-delegated/src/commonMain/kotlin/com/ionspin/kotlin/crypto/Crypto.kt +++ b/multiplatform-crypto-delegated/src/commonMain/kotlin/com/ionspin/kotlin/crypto/Crypto.kt @@ -55,7 +55,7 @@ object CryptoPrimitives : PrimitivesApi { } object Sha512 { - fun updateable(): com.ionspin.kotlin.crypto.hash.sha.Sha512Multipart { + fun updateable(): Sha512Multipart { checkInitialization() return Sha512Delegated() } diff --git a/multiplatform-crypto-delegated/src/commonMain/kotlin/com/ionspin/kotlin/crypto/authenticated/DelegatedXChaCha20Poly1305.kt b/multiplatform-crypto-delegated/src/commonMain/kotlin/com/ionspin/kotlin/crypto/authenticated/DelegatedXChaCha20Poly1305.kt index 6e007a7..1c6405e 100644 --- a/multiplatform-crypto-delegated/src/commonMain/kotlin/com/ionspin/kotlin/crypto/authenticated/DelegatedXChaCha20Poly1305.kt +++ b/multiplatform-crypto-delegated/src/commonMain/kotlin/com/ionspin/kotlin/crypto/authenticated/DelegatedXChaCha20Poly1305.kt @@ -7,6 +7,7 @@ package com.ionspin.kotlin.crypto.authenticated * on 14-Jun-2020 */ expect class XChaCha20Poly1305Delegated constructor(key: UByteArray, additionalData: UByteArray) { + internal constructor(key: UByteArray, additionalData: UByteArray, testState : UByteArray, testHeader: UByteArray) companion object { fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, additionalData: UByteArray) : UByteArray fun decrypt(key: UByteArray, nonce: UByteArray, ciphertext: UByteArray, additionalData: UByteArray) : UByteArray diff --git a/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Test.kt b/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Test.kt index b219259..da9a406 100644 --- a/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Test.kt +++ b/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Test.kt @@ -184,4 +184,32 @@ class XChaCha20Poly1305Test { } + + @Test + fun testStreamingImpl() { + val key = UByteArray(32) { 0U} + val state = ubyteArrayOf( + 0x2DU, 0xDBU, 0xC7U, 0xB2U, 0x03U, 0xBCU, 0xC3U, 0x22U, 0xBDU, 0x0CU, 0xBAU, 0x82U, 0xADU, 0x77U, 0x79U, 0x44U, + 0xE6U, 0x8FU, 0xA9U, 0x94U, 0x89U, 0xB1U, 0xDFU, 0xBEU, 0x00U, 0x9FU, 0x69U, 0xECU, 0x21U, 0x88U, 0x47U, 0x55U, + 0x01U, 0x00U, 0x00U, 0x00U, 0xC5U, 0x55U, 0x06U, 0x38U, 0xEBU, 0xA3U, 0x12U, 0x7BU, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, + ) + val header = ubyteArrayOf( + 0x49U, 0x62U, 0x22U, 0x03U, 0xB7U, 0x46U, 0x11U, 0x97U, 0x8FU, 0x46U, 0x4AU, 0x3BU, 0x2FU, 0x2AU, 0x81U, 0x03U, + 0xC5U, 0x55U, 0x06U, 0x38U, 0xEBU, 0xA3U, 0x12U, 0x7BU, + ) + val expected = ubyteArrayOf( + 0xAFU, 0xD3U, 0x2DU, 0x59U, 0xB8U, 0xC4U, 0x66U, 0x2EU, 0x47U, 0x29U, 0xC6U, 0xF9U, 0x93U, 0x4BU, 0x09U, 0x27U, + 0x24U, 0xDDU, 0xF3U, 0x05U, 0x48U, 0x94U, 0x67U, 0x10U, 0x00U, 0x21U, 0x85U, 0x22U, 0x96U, 0x3CU, 0xCEU, 0x8EU, + 0xB7U, 0x53U, 0x9DU, 0x46U, 0xF5U, 0x3CU, 0x5EU, 0x48U, 0x9BU, 0x8CU, 0x13U, 0xB7U, 0x28U, 0x6BU, 0xB3U, 0x6CU, + 0x3AU, 0x04U, 0xB7U, 0x25U, 0xB9U, 0x50U, 0x45U, 0x08U, 0x0BU, 0x89U, 0xA2U, 0x0FU, 0x70U, 0xCCU, 0x60U, 0x1BU, + 0xC3U, 0x17U, 0x35U, 0x9FU, 0xAEU, 0x82U, 0x51U, 0x43U, 0x1BU, 0x9DU, 0x53U, 0x9EU, 0xE2U, 0xAFU, 0x20U, 0x1FU, + 0xFDU, 0x03U, 0x59U, 0x11U, 0x51U, 0x9EU, 0xACU, 0x83U, 0xCDU, 0x78U, 0xD1U, 0xD0U, 0xE5U, 0xD7U, 0x0EU, 0x41U, + 0xDEU, 0xFBU, 0x5CU, 0x7FU, 0x1CU, 0x26U, 0x32U, 0x2CU, 0x51U, 0xF6U, 0xEFU, 0xC6U, 0x34U, 0xC4U, 0xACU, 0x6CU, + 0xE8U, 0xF9U, 0x4BU, 0xABU, 0xA3U, + ) + val xcha = XChaCha20Poly1305Delegated(key, ubyteArrayOf(), state, header) + val data = UByteArray(100) { 0U } + xcha.encryptPartialData(data) + } } diff --git a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt index 4e99b5c..5ed2c5d 100644 --- a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt +++ b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt @@ -51,6 +51,10 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi } } + internal actual constructor(key: UByteArray, additionalData: UByteArray, testState : UByteArray, testHeader: UByteArray) { + + } + actual fun encryptPartialData(data: UByteArray): UByteArray { TODO("not implemented yet") } diff --git a/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt b/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt index 44f2873..16f2f90 100644 --- a/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt +++ b/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt @@ -55,6 +55,10 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi } } + internal actual constructor(key: UByteArray, additionalData: UByteArray, testState : UByteArray, testHeader: UByteArray) { + + } + actual fun encryptPartialData(data: UByteArray): UByteArray { TODO("not implemented yet") } diff --git a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt index 568f1aa..59d2c70 100644 --- a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt +++ b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Delegated.kt @@ -1,19 +1,16 @@ package com.ionspin.kotlin.crypto.authenticated -import kotlinx.cinterop.addressOf -import kotlinx.cinterop.convert -import kotlinx.cinterop.pin -import kotlinx.cinterop.toCValues -import libsodium.crypto_aead_xchacha20poly1305_IETF_ABYTES -import libsodium.crypto_aead_xchacha20poly1305_ietf_decrypt -import libsodium.crypto_aead_xchacha20poly1305_ietf_encrypt +import com.ionspin.kotlin.bignum.integer.util.hexColumsPrint +import kotlinx.cinterop.* +import libsodium.* +import platform.posix.malloc /** * Created by Ugljesa Jovanovic * ugljesa.jovanovic@ionspin.com * on 14-Jun-2020 */ -actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, additionalData: UByteArray) { +actual class XChaCha20Poly1305Delegated actual constructor(val key: UByteArray,val additionalData: UByteArray) { actual companion object { actual fun encrypt( key: UByteArray, @@ -64,8 +61,58 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi } } + + actual internal constructor(key: UByteArray, additionalData: UByteArray, testState : UByteArray, testHeader: UByteArray) : this(key, additionalData) { + val pointer = state.ptr.reinterpret() + for (i in 0 until crypto_secretstream_xchacha20poly1305_state.size.toInt()) { + pointer[i] = testState[i] + } + println("state after setting-----------") + state.ptr.readBytes(crypto_secretstream_xchacha20poly1305_state.size.toInt()).toUByteArray().hexColumsPrint() + println("state after setting-----------") + println("header after setting-----------") + testHeader.copyInto(header) + header.hexColumsPrint() + println("header after setting-----------") + } + + var state = + malloc(crypto_secretstream_xchacha20poly1305_state.size.convert())!! + .reinterpret() + .pointed + + val header = UByteArray(crypto_secretstream_xchacha20poly1305_HEADERBYTES.toInt()) { 0U } + + init { + val pinnedHeader = header.pin() + crypto_secretstream_xchacha20poly1305_init_push(state.ptr, pinnedHeader.addressOf(0), key.toCValues()) + println("state-----------") + state.ptr.readBytes(crypto_secretstream_xchacha20poly1305_state.size.toInt()).toUByteArray().hexColumsPrint() + println("state-----------") + println("--------header-----------") + header.hexColumsPrint() + println("--------header-----------") + + } + actual fun encryptPartialData(data: UByteArray): UByteArray { - TODO("not implemented yet") + val ciphertextWithTag = UByteArray(data.size + crypto_secretstream_xchacha20poly1305_ABYTES.toInt()) + val ciphertextWithTagPinned = ciphertextWithTag.pin() + crypto_secretstream_xchacha20poly1305_push( + state.ptr, + ciphertextWithTagPinned.addressOf(0), + null, + data.toCValues(), + data.size.convert(), + null, + 0U, + 0U, + ) + println("Encrypt partial") + ciphertextWithTag.hexColumsPrint() + println("Encrypt partial end") + ciphertextWithTagPinned.unpin() + return ciphertextWithTag } actual fun verifyPartialData(data: UByteArray) { 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 0d379bf..3c6d6ef 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 @@ -2,9 +2,7 @@ package com.ionspin.kotlin.crypto.authenticated 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 /** @@ -38,7 +36,7 @@ internal class ChaCha20Poly1305Pure { } } val oneTimeKey = ChaCha20Pure.hash(state).sliceArray(0 until 32) - val cipherText = ChaCha20Pure.encrypt(key, nonce, message, 1U) + val cipherText = ChaCha20Pure.xorWithKeystream(key, nonce, message, 1U) val additionalDataPad = UByteArray(16 - additionalData.size % 16) { 0U } val cipherTextPad = UByteArray(16 - cipherText.size % 16) { 0U } val macData = additionalData + additionalDataPad + @@ -49,4 +47,4 @@ internal class ChaCha20Poly1305Pure { return cipherText + tag } } -} \ No newline at end of file +} 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 f96bbbf..3a3830b 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 @@ -2,11 +2,11 @@ package com.ionspin.kotlin.crypto.authenticated import com.ionspin.kotlin.crypto.AuthenticatedEncryption import com.ionspin.kotlin.crypto.InvalidTagException -import com.ionspin.kotlin.crypto.MultipartAuthenticatedDecryption -import com.ionspin.kotlin.crypto.SRNG 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.hexColumsPrint +import com.ionspin.kotlin.crypto.util.overwriteWithZeroes import com.ionspin.kotlin.crypto.util.toLittleEndianUByteArray /** @@ -14,13 +14,13 @@ import com.ionspin.kotlin.crypto.util.toLittleEndianUByteArray * ugljesa.jovanovic@ionspin.com * on 17-Jun-2020 */ -class XChaCha20Poly1305Pure(val key: UByteArray, val additionalData: UByteArray) { +class XChaCha20Poly1305Pure(val key: UByteArray, val nonce: UByteArray) { companion object : AuthenticatedEncryption { override fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, additionalData: UByteArray) : UByteArray { val subKey = XChaCha20Pure.hChacha(key, nonce) val authKey = - ChaCha20Pure.encrypt( + ChaCha20Pure.xorWithKeystream( subKey.toLittleEndianUByteArray(), ubyteArrayOf(0U, 0U, 0U, 0U) + nonce.sliceArray(16 until 24), UByteArray(64) { 0U }, @@ -43,7 +43,7 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val additionalData: UByteArray) override fun decrypt(key: UByteArray, nonce: UByteArray, cipherText: UByteArray, additionalData: UByteArray) : UByteArray { val subKey = XChaCha20Pure.hChacha(key, nonce) val authKey = - ChaCha20Pure.encrypt( + ChaCha20Pure.xorWithKeystream( subKey.toLittleEndianUByteArray(), ubyteArrayOf(0U, 0U, 0U, 0U) + nonce.sliceArray(16 until 24), UByteArray(64) { 0U }, @@ -69,8 +69,6 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val additionalData: UByteArray) } - internal val nonce = SRNG.getRandomBytes(24) - private val updateableEncryptionPrimitive = XChaCha20Pure(key, nonce, initialCounter = 1U) private val updateableMacPrimitive : Poly1305 @@ -82,7 +80,7 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val additionalData: UByteArray) init { val subKey = XChaCha20Pure.hChacha(key, nonce) val authKey = - ChaCha20Pure.encrypt( + ChaCha20Pure.xorWithKeystream( subKey.toLittleEndianUByteArray(), ubyteArrayOf(0U, 0U, 0U, 0U) + nonce.sliceArray(16 until 24), UByteArray(64) { 0U }, @@ -92,17 +90,88 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val additionalData: UByteArray) // at org.jetbrains.kotlin.ir.backend.js.lower.ConstTransformer.lowerConst(ConstLowering.kt:38) ) updateableMacPrimitive = Poly1305(authKey) - val additionalDataPad = UByteArray(16 - additionalData.size % 16) { 0U } - processPolyBytes(additionalData + additionalDataPad) +// val additionalDataPad = UByteArray(16 - additionalData.size % 16) { 0U } +// processPolyBytes(additionalData + additionalDataPad) } + // Sketch libsodium stream cipher with chachapoly, because my two pass approach to multipart encryption is + // inneficient, to put it mildly. + + // libsodium-like state + // key, 32 Bytes + // nonce, 12 Bytes + // pad, 8 bytes + + //libsodium like header + //random header bytes 24 and put that into out + //then hchacha20 of key and random bytes (out) to generate state key + //the reset counter to 1 + //then copy to state->NONCE, HCHACHAINPUTBYTES (16B) from out, length of INONCE_BYTES which is 8, which uses up all random from previous step + //Pad state with 8B of zeroes + + //header is a 24byte nonce + + internal val calcKey : UByteArray = UByteArray(32) + internal val calcNonce : UByteArray = UByteArray(12) + + init { + val calc = XChaCha20Pure.hChacha(key, nonce).toLittleEndianUByteArray() + calc.sliceArray(0 until 32).copyInto(calcKey) + nonce.sliceArray(16 until 24).copyInto(calcNonce, 4) + calcNonce[0] = 1U + calcNonce[1] = 0U + calcNonce[2] = 0U + calcNonce[3] = 0U + println("Calckey-------=") + calcKey.hexColumsPrint() + println("Calckey-------=") + println("Calcnonce---------") + calcNonce.hexColumsPrint() + println("Calcnonce---------") + } + + fun encryptPartial(data: UByteArray, additionalData: UByteArray = ubyteArrayOf(), tag : UByte = 0U) : UByteArray { + val result = UByteArray(1 + data.size + 16) //Tag marker, ciphertext, mac + //get encryption state + val block = UByteArray(64) { 0U } + ChaCha20Pure.xorWithKeystream(calcKey, calcNonce, block, 0U).copyInto(block) // This is equivalent to the first 64 bytes of keystream + val poly1305 = Poly1305(block) + block.overwriteWithZeroes() + val additionalDataPadded = additionalData + UByteArray(16 - additionalData.size % 16) { 0U } + poly1305.updateMac(additionalDataPadded) + block[0] = tag + ChaCha20Pure.xorWithKeystream(calcKey, calcNonce, block, 1U).copyInto(block) // This just xors block[0] with keystream + poly1305.updateMac(block) // but updates the mac with the full block! + // In libsodium c code, it now sets the first byte to be a tag, we'll just save it for now + val encryptedTag = block[0] + //And then encrypt the rest of the message + val ciphertext = ChaCha20Pure.xorWithKeystream(calcKey, calcNonce, data, 2U) // With appropriate counter + println("ciphertext-----") + ciphertext.hexColumsPrint() + println("ciphertext-----") + poly1305.updateMac(ciphertext + UByteArray(16 - data.size % 16) { 0U } ) //TODO this is inefficient as it creates a new array and copies data + val finalMac = additionalData.size.toULong().toLittleEndianUByteArray() + ciphertext.size.toULong().toLittleEndianUByteArray() + val mac = poly1305.finalizeMac(finalMac) + + return ubyteArrayOf(encryptedTag) + ciphertext + mac + } + + // Sketch end fun encryptPartialData(data: UByteArray) : UByteArray { processedBytes += data.size val encrypted = updateableEncryptionPrimitive.xorWithKeystream(data) processPolyBytes(encrypted) - return encrypted + + val cipherTextPad = UByteArray(16 - processedBytes % 16) { 0U } + val macData = cipherTextPad + +// additionalData.size.toULong().toLittleEndianUByteArray() + + processedBytes.toULong().toLittleEndianUByteArray() + processPolyBytes(macData) + val tag = updateableMacPrimitive.finalizeMac() + + return encrypted + tag } fun verifyPartialData(data: UByteArray) { @@ -112,7 +181,7 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val additionalData: UByteArray) fun checkTag(expectedTag: UByteArray) { val cipherTextPad = UByteArray(16 - processedBytes % 16) { 0U } val macData = cipherTextPad + - additionalData.size.toULong().toLittleEndianUByteArray() + +// additionalData.size.toULong().toLittleEndianUByteArray() + processedBytes.toULong().toLittleEndianUByteArray() processPolyBytes(macData) val tag = updateableMacPrimitive.finalizeMac() @@ -173,7 +242,7 @@ class XChaCha20Poly1305Pure(val key: UByteArray, val additionalData: UByteArray) val cipherTextPad = UByteArray(16 - processedBytes % 16) { 0U } val macData = cipherTextPad + - additionalData.size.toULong().toLittleEndianUByteArray() + +// additionalData.size.toULong().toLittleEndianUByteArray() + processedBytes.toULong().toLittleEndianUByteArray() processPolyBytes(macData) val tag = updateableMacPrimitive.finalizeMac() 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 c328fb2..4a231a2 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 @@ -80,7 +80,6 @@ class Poly1305(key: UByteArray) { var accumulator = BigInteger.ZERO fun updateMac(data : UByteArray) { - data.hexColumsPrint() val blockAsInt = BigInteger.fromUByteArray(data, Endianness.LITTLE) + powersOfTwo[128] accumulator += blockAsInt accumulator *= rAsBigInt @@ -89,7 +88,6 @@ class Poly1305(key: UByteArray) { fun finalizeMac(data: UByteArray = ubyteArrayOf()) : UByteArray{ if (data.size != 0) { - data.hexColumsPrint() val blockAsInt = BigInteger.fromUByteArray(data, Endianness.LITTLE) + powersOfTwo[data.size * 8] accumulator += blockAsInt accumulator *= rAsBigInt 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 8e11511..d475395 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): UByteArray { + fun xorWithKeystream(key: UByteArray, nonce: UByteArray, message: UByteArray, initialCounter: UInt): UByteArray { val ciphertext = UByteArray(message.size) val state = UIntArray(16) { when (it) { @@ -96,4 +96,4 @@ internal class ChaCha20Pure { return ciphertext } } -} \ No newline at end of file +} diff --git a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Test.kt b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Test.kt index 7c2b6d4..7ba0ef7 100644 --- a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Test.kt +++ b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/authenticated/XChaCha20Poly1305Test.kt @@ -1,6 +1,7 @@ package com.ionspin.kotlin.crypto.authenticated import com.ionspin.kotlin.crypto.hash.encodeToUByteArray +import com.ionspin.kotlin.crypto.util.hexColumsPrint import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertTrue @@ -173,4 +174,39 @@ class XChaCha20Poly1305Test { } + + @Test + fun multipartXChaCha20Poly1305() { + val key = UByteArray(32) { 0U} + + val state = ubyteArrayOf( + 0x2DU, 0xDBU, 0xC7U, 0xB2U, 0x03U, 0xBCU, 0xC3U, 0x22U, 0xBDU, 0x0CU, 0xBAU, 0x82U, 0xADU, 0x77U, 0x79U, 0x44U, + 0xE6U, 0x8FU, 0xA9U, 0x94U, 0x89U, 0xB1U, 0xDFU, 0xBEU, 0x00U, 0x9FU, 0x69U, 0xECU, 0x21U, 0x88U, 0x47U, 0x55U, + 0x01U, 0x00U, 0x00U, 0x00U, 0xC5U, 0x55U, 0x06U, 0x38U, 0xEBU, 0xA3U, 0x12U, 0x7BU, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, + ) + val header = ubyteArrayOf( + 0x49U, 0x62U, 0x22U, 0x03U, 0xB7U, 0x46U, 0x11U, 0x97U, 0x8FU, 0x46U, 0x4AU, 0x3BU, 0x2FU, 0x2AU, 0x81U, 0x03U, + 0xC5U, 0x55U, 0x06U, 0x38U, 0xEBU, 0xA3U, 0x12U, 0x7BU, + ) + val expected = ubyteArrayOf( + 0xAFU, 0xD3U, 0x2DU, 0x59U, 0xB8U, 0xC4U, 0x66U, 0x2EU, 0x47U, 0x29U, 0xC6U, 0xF9U, 0x93U, 0x4BU, 0x09U, 0x27U, + 0x24U, 0xDDU, 0xF3U, 0x05U, 0x48U, 0x94U, 0x67U, 0x10U, 0x00U, 0x21U, 0x85U, 0x22U, 0x96U, 0x3CU, 0xCEU, 0x8EU, + 0xB7U, 0x53U, 0x9DU, 0x46U, 0xF5U, 0x3CU, 0x5EU, 0x48U, 0x9BU, 0x8CU, 0x13U, 0xB7U, 0x28U, 0x6BU, 0xB3U, 0x6CU, + 0x3AU, 0x04U, 0xB7U, 0x25U, 0xB9U, 0x50U, 0x45U, 0x08U, 0x0BU, 0x89U, 0xA2U, 0x0FU, 0x70U, 0xCCU, 0x60U, 0x1BU, + 0xC3U, 0x17U, 0x35U, 0x9FU, 0xAEU, 0x82U, 0x51U, 0x43U, 0x1BU, 0x9DU, 0x53U, 0x9EU, 0xE2U, 0xAFU, 0x20U, 0x1FU, + 0xFDU, 0x03U, 0x59U, 0x11U, 0x51U, 0x9EU, 0xACU, 0x83U, 0xCDU, 0x78U, 0xD1U, 0xD0U, 0xE5U, 0xD7U, 0x0EU, 0x41U, + 0xDEU, 0xFBU, 0x5CU, 0x7FU, 0x1CU, 0x26U, 0x32U, 0x2CU, 0x51U, 0xF6U, 0xEFU, 0xC6U, 0x34U, 0xC4U, 0xACU, 0x6CU, + 0xE8U, 0xF9U, 0x4BU, 0xABU, 0xA3U, + ) + + val xcha = XChaCha20Poly1305Pure(key, header) + //Verify the state is correctly created + assertTrue { + xcha.calcKey.contentEquals(state.sliceArray(0 until 32)) + xcha.calcNonce.contentEquals(state.sliceArray(32 until 44)) + } + val data = UByteArray(100) { 0U } + xcha.encryptPartial(data).hexColumsPrint() + } } diff --git a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/mac/Poly1305Test.kt b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/mac/Poly1305Test.kt index adfa978..b24c72e 100644 --- a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/mac/Poly1305Test.kt +++ b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/mac/Poly1305Test.kt @@ -75,7 +75,7 @@ class Poly1305Test { 0x59U, 0xf0U, 0x88U, 0x71U, 0x29U, 0xccU, 0x2eU, 0xe7U, ) val message = ubyteArrayOf( - + ) val expected = ubyteArrayOf( 0xddU, 0x3fU, 0xabU, 0x22U, 0x51U, 0xf1U, 0x1aU, 0xc7U, @@ -221,4 +221,4 @@ class Poly1305Test { expected.contentEquals(result) } } -} \ No newline at end of file +} diff --git a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/ChaCha20Test.kt b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/ChaCha20Test.kt index 850ac5f..4687643 100644 --- a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/ChaCha20Test.kt +++ b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/ChaCha20Test.kt @@ -1,8 +1,6 @@ package com.ionspin.kotlin.crypto.symmetric import com.ionspin.kotlin.crypto.hash.encodeToUByteArray -import com.ionspin.kotlin.crypto.util.hexColumsPrint -import com.ionspin.kotlin.crypto.util.toHexString import kotlin.test.Test import kotlin.test.assertTrue @@ -80,7 +78,7 @@ class ChaCha20Test { 0x5aU, 0xf9U, 0x0bU, 0xbfU, 0x74U, 0xa3U, 0x5bU, 0xe6U, 0xb4U, 0x0bU, 0x8eU, 0xedU, 0xf2U, 0x78U, 0x5eU, 0x42U, 0x87U, 0x4dU, ) - val result = ChaCha20Pure.encrypt(key, nonce, message, 1U) + val result = ChaCha20Pure.xorWithKeystream(key, nonce, message, 1U) assertTrue { expected.contentEquals(result) } @@ -89,4 +87,4 @@ class ChaCha20Test { } -} \ No newline at end of file +}