From e6f560ba8ef082db10173b30a83078126673716d Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Sat, 27 Jun 2020 18:20:53 +0200 Subject: [PATCH] Working single shot xchacha20poly1305 encryption and decryption in delegated flavour --- .../ionspin/kotlin/crypto/util/CryptoUtil.kt | 4 +++- .../com/ionspin/kotlin/crypto/Crypto.kt | 5 +---- .../authenticated/XChaCha20Poly1305Test.kt | 21 +++++++++++-------- .../kotlin/crypto/JsSodiumInterface.kt | 3 ++- .../com/ionspin/kotlin/crypto/JsUtil.kt | 6 ++++-- .../XChaCha20Poly1305Delegated.kt | 15 ++++++++++--- .../XChaCha20Poly1305Delegated.kt | 7 +++---- .../com/ionspin/kotlin/crypto/Initializer.kt | 8 +++---- .../XChaCha20Poly1305Delegated.kt | 20 ++++++++++++++++-- .../kotlin/crypto/symmetric/XChaCha20Pure.kt | 1 - .../kotlin/crypto/symmetric/XChaCha20Test.kt | 5 +++-- .../ionspin/kotlin/crypto/sample/Sample.kt | 8 ++++--- .../ionspin/kotlin/crypto/sample/Runner.kt | 11 ---------- 13 files changed, 66 insertions(+), 48 deletions(-) diff --git a/multiplatform-crypto-api/src/commonMain/kotlin/com/ionspin/kotlin/crypto/util/CryptoUtil.kt b/multiplatform-crypto-api/src/commonMain/kotlin/com/ionspin/kotlin/crypto/util/CryptoUtil.kt index 2fe2d7c..6739eaa 100644 --- a/multiplatform-crypto-api/src/commonMain/kotlin/com/ionspin/kotlin/crypto/util/CryptoUtil.kt +++ b/multiplatform-crypto-api/src/commonMain/kotlin/com/ionspin/kotlin/crypto/util/CryptoUtil.kt @@ -5,6 +5,8 @@ package com.ionspin.kotlin.crypto.util * ugljesa.jovanovic@ionspin.com * on 22-Jun-2020 */ +val _emit = IntArray(0) + fun UByteArray.overwriteWithZeroes() { for (i in 0 until size) { this[i] = 0U @@ -15,4 +17,4 @@ fun UIntArray.overwriteWithZeroes() { for (i in 0 until size) { this[i] = 0U } -} \ No newline at end of file +} 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 cd5e701..82ccef8 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 @@ -15,19 +15,16 @@ import com.ionspin.kotlin.crypto.keyderivation.ArgonResult */ object CryptoInitializerDelegated : CryptoInitializer { - private var initialized = false override suspend fun initialize() { Initializer.initialize() - initialized = true } fun initializeWithCallback(done: () -> Unit) { - initialized = true Initializer.initializeWithCallback(done) } override fun isInitialized(): Boolean { - return initialized + return Initializer.isInitialized() } } 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 35513ae..b219259 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 @@ -2,6 +2,7 @@ package com.ionspin.kotlin.crypto.authenticated import com.ionspin.kotlin.crypto.CryptoInitializerDelegated import com.ionspin.kotlin.crypto.hash.encodeToUByteArray +import com.ionspin.kotlin.crypto.util.hexColumsPrint import com.ionspin.kotlin.crypto.util.testBlocking import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -18,10 +19,9 @@ class XChaCha20Poly1305Test { @Test - fun xChaCha20Poly1305() { - testBlocking { - CryptoInitializerDelegated.initialize() - } + fun xChaCha20Poly1305() = testBlocking { + CryptoInitializerDelegated.initialize() + assertTrue { 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() @@ -62,9 +62,12 @@ class XChaCha20Poly1305Test { 0xcfU, 0x49U ) val encrypted = XChaCha20Poly1305Delegated.encrypt(key, nonce, message, additionalData) -// val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, additionalData) - - encrypted.contentEquals(expected) // && decrypted.contentEquals(message) + encrypted.hexColumsPrint() + val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, additionalData) + println("Decrypted") + decrypted.hexColumsPrint() + println("----------") + encrypted.contentEquals(expected) && decrypted.contentEquals(message) } assertTrue { @@ -91,9 +94,9 @@ class XChaCha20Poly1305Test { 0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU ) val encrypted = XChaCha20Poly1305Delegated.encrypt(key, nonce, message, additionalData) -// val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, additionalData) + val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, additionalData) - encrypted.contentEquals(expected) // && decrypted.contentEquals(message) + encrypted.contentEquals(expected) && decrypted.contentEquals(message) } diff --git a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt index 0ddeb41..9254ce7 100644 --- a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt +++ b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt @@ -40,7 +40,8 @@ interface JsSodiumInterface { fun crypto_hash_sha512_final(state: dynamic): Uint8Array //XChaCha20Poly1305 - fun crypto_aead_xchacha20poly1305_ietf_encrypt(message: Uint8Array, additionalData: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array + fun crypto_aead_xchacha20poly1305_ietf_encrypt(message: Uint8Array, additionalData: Uint8Array, secretNonce: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array + fun crypto_aead_xchacha20poly1305_ietf_decrypt(secretNonce: Uint8Array, ciphertext: Uint8Array, additionalData: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array } diff --git a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsUtil.kt b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsUtil.kt index 958d1a5..ae4a065 100644 --- a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsUtil.kt +++ b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsUtil.kt @@ -8,10 +8,12 @@ import org.khronos.webgl.set * Created by Ugljesa Jovanovic * ugljesa.jovanovic@ionspin.com * on 25-Jun-2020 + * + * TODO investigate using unsafe cast */ fun UByteArray.toUInt8Array() : Uint8Array { val uint8Result = Uint8Array(toByteArray().toTypedArray()) - console.log("Uint8: $uint8Result") +// console.log("Uint8: $uint8Result") return uint8Result } @@ -21,7 +23,7 @@ fun Uint8Array.toUByteArray() : UByteArray { for (i in 0 until length) { result[i] = get(i).toUByte() } - console.log("UbyteArray: ${result.joinToString()}") +// console.log("UbyteArray: ${result.joinToString()}") return result } 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 1a79a25..4e99b5c 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 @@ -3,6 +3,7 @@ package com.ionspin.kotlin.crypto.authenticated import com.ionspin.kotlin.crypto.getSodium import ext.libsodium.com.ionspin.kotlin.crypto.toUByteArray import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array +import org.khronos.webgl.Uint8Array /** * Created by Ugljesa Jovanovic @@ -26,8 +27,9 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi val encrypted = getSodium().crypto_aead_xchacha20poly1305_ietf_encrypt( message.toUInt8Array(), additionalData.toUInt8Array(), - key.toUInt8Array(), - nonce.toUInt8Array() + Uint8Array(0), + nonce.toUInt8Array(), + key.toUInt8Array() ) return encrypted.toUByteArray() } @@ -38,7 +40,14 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi ciphertext: UByteArray, additionalData: UByteArray ): UByteArray { - TODO("not implemented yet") + val decrypted = getSodium().crypto_aead_xchacha20poly1305_ietf_decrypt( + Uint8Array(0), + ciphertext.toUInt8Array(), + additionalData.toUInt8Array(), + nonce.toUInt8Array(), + key.toUInt8Array() + ) + return decrypted.toUByteArray() } } 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 992de98..44f2873 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 @@ -38,16 +38,15 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi ciphertext: UByteArray, additionalData: UByteArray ): UByteArray { - val message = ByteArray(ciphertext.size - sodium.crypto_secretstream_xchacha20poly1305_abytes()) - SodiumJava().crypto_aead_xchacha20poly1305_ietf_encrypt( - + val message = ByteArray(ciphertext.size - 16) + SodiumJava().crypto_aead_xchacha20poly1305_ietf_decrypt( message, longArrayOf(ciphertext.size.toLong()), + null, ciphertext.toByteArray(), ciphertext.size.toLong(), additionalData.toByteArray(), additionalData.size.toLong(), - null, nonce.toByteArray(), key.toByteArray() diff --git a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/Initializer.kt b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/Initializer.kt index 7541afa..944c199 100644 --- a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/Initializer.kt +++ b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/Initializer.kt @@ -1,9 +1,7 @@ +@file:Suppress("VARIABLE_IN_SINGLETON_WITHOUT_THREAD_LOCAL") + package com.ionspin.kotlin.crypto -import kotlinx.atomicfu.AtomicBoolean -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import libsodium.sodium_init import kotlin.native.concurrent.AtomicInt @@ -29,4 +27,4 @@ actual object Initializer { actual fun isInitialized(): Boolean { return isPlatformInitialized.value != 0 } -} \ No newline at end of file +} 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 993d7f0..568f1aa 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 @@ -5,6 +5,7 @@ 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 /** @@ -25,7 +26,7 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi val ciphertextPinned = ciphertext.pin() crypto_aead_xchacha20poly1305_ietf_encrypt( ciphertextPinned.addressOf(0), - ciphertextLength.convert(), + ulongArrayOf(ciphertextLength.convert()).toCValues(), message.toCValues(), message.size.convert(), additionalData.toCValues(), @@ -44,7 +45,22 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi ciphertext: UByteArray, additionalData: UByteArray ): UByteArray { - TODO("not implemented yet") + val messageLength = ciphertext.size - crypto_aead_xchacha20poly1305_IETF_ABYTES.toInt() + val message = UByteArray(messageLength) + val messagePinned = message.pin() + crypto_aead_xchacha20poly1305_ietf_decrypt( + messagePinned.addressOf(0), + ulongArrayOf(messageLength.convert()).toCValues(), + null, + ciphertext.toCValues(), + ciphertext.size.convert(), + additionalData.toCValues(), + additionalData.size.convert(), + nonce.toCValues(), + key.toCValues() + ) + messagePinned.unpin() + return message } } 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 a7e0256..5631cbd 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 @@ -173,7 +173,6 @@ class XChaCha20Pure(key: UByteArray, nonce: UByteArray, initialCounter: UInt = 0 ) keystreamRemainingCounter = 64 - remainingBytes processedBytesSoFar += data.size - state.overwriteWithZeroes() return ciphertext } 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 dc3d9ed..53c9d2a 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,6 +1,7 @@ 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 @@ -239,9 +240,9 @@ class XChaCha20Test { val firstChunk = xChaCha.xorWithKeystream(message.sliceArray(0 until 5)) val secondChunk = xChaCha.xorWithKeystream(message.sliceArray(5 until 90)) val thirdChunk = xChaCha.xorWithKeystream(message.sliceArray(90 until message.size)) - + val result = firstChunk + secondChunk + thirdChunk assertTrue { - (firstChunk + secondChunk + thirdChunk).contentEquals(expected) + (result).contentEquals(expected) } } diff --git a/sample/src/commonMain/kotlin/com/ionspin/kotlin/crypto/sample/Sample.kt b/sample/src/commonMain/kotlin/com/ionspin/kotlin/crypto/sample/Sample.kt index ad3577d..76870f8 100644 --- a/sample/src/commonMain/kotlin/com/ionspin/kotlin/crypto/sample/Sample.kt +++ b/sample/src/commonMain/kotlin/com/ionspin/kotlin/crypto/sample/Sample.kt @@ -1,13 +1,15 @@ package com.ionspin.kotlin.crypto.sample import com.ionspin.kotlin.crypto.Crypto +import com.ionspin.kotlin.crypto.CryptoInitializerDelegated +import com.ionspin.kotlin.crypto.CryptoPrimitives import com.ionspin.kotlin.crypto.hash.encodeToUByteArray import com.ionspin.kotlin.crypto.util.toHexString object Sample { fun runSample() { println("Initializing crypto library") - Crypto.initializeWithCallback { + CryptoInitializerDelegated.initializeWithCallback { blake2b() } @@ -16,11 +18,11 @@ object Sample { fun blake2b() { println("Blake2b updateable") - val blake2bUpdateable = Crypto.Blake2b.updateable() + val blake2bUpdateable = CryptoPrimitives.Blake2b.updateable() blake2bUpdateable.update("test".encodeToUByteArray()) println(blake2bUpdateable.digest().toHexString()) println("Blake2b stateless") - val statelessResult = Crypto.Blake2b.stateless("test".encodeToByteArray().toUByteArray()) + val statelessResult = CryptoPrimitives.Blake2b.stateless("test".encodeToByteArray().toUByteArray()) println("Blake2b stateless: ${statelessResult.toHexString()}") } } diff --git a/sample/src/linuxArm64Main/kotlin/com/ionspin/kotlin/crypto/sample/Runner.kt b/sample/src/linuxArm64Main/kotlin/com/ionspin/kotlin/crypto/sample/Runner.kt index faab8b3..22b3ead 100644 --- a/sample/src/linuxArm64Main/kotlin/com/ionspin/kotlin/crypto/sample/Runner.kt +++ b/sample/src/linuxArm64Main/kotlin/com/ionspin/kotlin/crypto/sample/Runner.kt @@ -1,16 +1,5 @@ -import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bDelegated -import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bStateless import com.ionspin.kotlin.crypto.sample.Sample -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import platform.posix.pthread_self -import platform.posix.sleep -import kotlin.native.concurrent.TransferMode -import kotlin.native.concurrent.Worker import kotlin.time.ExperimentalTime -import kotlin.time.measureTime @ExperimentalTime