From ce7b27da98aaeeb3b0e64f7486bf38bec1e47312 Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Tue, 9 Jun 2020 22:13:21 +0200 Subject: [PATCH] Completed blake2b, sha256 and sha512 delegated implementations --- .../com/ionspin/kotlin/crypto/Crypto.kt | 14 ++++++ .../kotlin/crypto/hash/sha/Sha512Delegated.kt | 2 +- .../kotlin/crypto/hash/blake2b/Blake2bTest.kt | 45 +++++++++++++++++++ .../kotlin/crypto/hash/sha/Sha256Test.kt | 12 ++++- .../kotlin/crypto/hash/sha/Sha512Test.kt | 12 ++++- .../com/ionspin/kotlin/crypto/Initializer.kt | 10 +++++ .../kotlin/crypto/JsSodiumInterface.kt | 13 +++++- .../crypto/hash/blake2b/Blake2bDelegated.kt | 32 +++++++++---- .../kotlin/crypto/hash/sha/Sha256Delegated.kt | 5 +-- .../kotlin/crypto/hash/sha/Sha512Delegated.kt | 2 +- .../com/ionspin/kotlin/crypto/SRNGJsTest.kt | 16 +++---- .../crypto/hash/blake2b/Blake2bJsTest.kt | 27 ----------- .../com/ionspin/kotlin/crypto/Initializer.kt | 16 +++++++ .../crypto/hash/blake2b/Blake2bDelegated.kt | 19 ++++++-- .../kotlin/crypto/hash/sha/Sha256Delegated.kt | 41 +++++++++++++++++ .../hash/sha/Sha256StatelessDelegated.kt | 32 ------------- .../kotlin/crypto/hash/sha/Sha512Delegated.kt | 22 +++++++-- .../com/ionspin/kotlin/crypto/Initializer.kt | 20 +++++++-- .../kotlin/crypto/hash/sha/Sha256Delegated.kt | 2 +- .../kotlin/crypto/hash/sha/Sha512Delegated.kt | 2 +- .../crypto/hash/blake2b/Blake2bLinuxTest.kt | 40 ----------------- .../hash/blake2b/Sha512DelegatedLinuxTest.kt | 41 ----------------- 22 files changed, 244 insertions(+), 181 deletions(-) create mode 100644 multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bTest.kt delete mode 100644 multiplatform-crypto-delegated/src/jsTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bJsTest.kt create mode 100644 multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt delete mode 100644 multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256StatelessDelegated.kt delete mode 100644 multiplatform-crypto-delegated/src/nativeTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bLinuxTest.kt delete mode 100644 multiplatform-crypto-delegated/src/nativeTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Sha512DelegatedLinuxTest.kt 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 98e9ab3..0d4d849 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 @@ -23,34 +23,46 @@ object Crypto : CryptoProvider { object Blake2b { fun updateable(key: UByteArray? = null, hashLength: Int = Blake2bProperties.MAX_HASH_BYTES): com.ionspin.kotlin.crypto.hash.blake2b.Blake2b { + checkInitialization() return Blake2bDelegated(key, hashLength) } fun stateless(message: UByteArray, key: UByteArray = ubyteArrayOf(), hashLength: Int = Blake2bProperties.MAX_HASH_BYTES): UByteArray { + checkInitialization() return Blake2bDelegatedStateless.digest(message, key, hashLength) } } object Sha256 { fun updateable(): com.ionspin.kotlin.crypto.hash.sha.Sha256 { + checkInitialization() return Sha256Delegated() } fun stateless(message: UByteArray) : UByteArray{ + checkInitialization() return Sha256StatelessDelegated.digest(inputMessage = message) } } object Sha512 { fun updateable(): com.ionspin.kotlin.crypto.hash.sha.Sha512 { + checkInitialization() return Sha512Delegated() } fun stateless(message: UByteArray) : UByteArray { + checkInitialization() return Sha512StatelessDelegated.digest(inputMessage = message) } } + private fun checkInitialization() { + if (!Initializer.isInitialized()) { + throw RuntimeException("Platform library not initialized, check if you called Initializer.initialize()") + } + } + } @@ -62,6 +74,8 @@ object SimpleCrypto { } expect object Initializer { + fun isInitialized() : Boolean + suspend fun initialize() fun initializeWithCallback(done: () -> (Unit)) diff --git a/multiplatform-crypto-delegated/src/commonMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt b/multiplatform-crypto-delegated/src/commonMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt index 97aee12..13a809d 100644 --- a/multiplatform-crypto-delegated/src/commonMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt +++ b/multiplatform-crypto-delegated/src/commonMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt @@ -24,6 +24,6 @@ package com.ionspin.kotlin.crypto.hash.sha */ -expect class Sha512Delegated(key: UByteArray? = null, hashLength: Int = Sha512Properties.MAX_HASH_BYTES) : Sha512 +expect class Sha512Delegated() : Sha512 expect object Sha512StatelessDelegated : StatelessSha512 \ No newline at end of file diff --git a/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bTest.kt b/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bTest.kt new file mode 100644 index 0000000..6f98052 --- /dev/null +++ b/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bTest.kt @@ -0,0 +1,45 @@ +package com.ionspin.kotlin.crypto.hash.blake2b + +import com.ionspin.kotlin.crypto.Crypto +import com.ionspin.kotlin.crypto.Initializer +import com.ionspin.kotlin.crypto.hash.encodeToUByteArray +import com.ionspin.kotlin.crypto.util.testBlocking +import com.ionspin.kotlin.crypto.util.toHexString +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertTrue + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 09-Jun-2020 + */ +class Blake2bTest { + + + + @Test + fun statelessSimpleTest() = testBlocking { + Initializer.initialize() + val expected = "a71079d42853dea26e453004338670a53814b78137ffbed07603a41d76a483aa9bc33b582f77d30a65e6f29a89" + + "6c0411f38312e1d66e0bf16386c86a89bea572" + val result = Crypto.Blake2b.stateless("test".encodeToUByteArray()).toHexString() +// println("Result: $result") + assertTrue { result == expected } + } + + //This is a bad test since it's not larger than one block + //but for now I'm testing that the platform library is being correctly called + @Test + fun updateableSimpleTest() = testBlocking { + Initializer.initialize() + val expected = "a71079d42853dea26e453004338670a53814b78137ffbed07603a41d76a483aa9bc33b582f77d30a65e6f29a89" + + "6c0411f38312e1d66e0bf16386c86a89bea572" + val blake2b = Crypto.Blake2b.updateable() + blake2b.update("t".encodeToUByteArray()) + blake2b.update(("est".encodeToUByteArray())) + val result = blake2b.digest().toHexString() +// println("Result: $result") + assertTrue { result == expected } + } +} \ No newline at end of file diff --git a/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Test.kt b/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Test.kt index 5d5c733..4a73910 100644 --- a/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Test.kt +++ b/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Test.kt @@ -1,8 +1,11 @@ package com.ionspin.kotlin.crypto.hash.sha import com.ionspin.kotlin.crypto.Crypto +import com.ionspin.kotlin.crypto.Initializer import com.ionspin.kotlin.crypto.hash.encodeToUByteArray +import com.ionspin.kotlin.crypto.util.testBlocking import com.ionspin.kotlin.crypto.util.toHexString +import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertTrue @@ -12,11 +15,16 @@ import kotlin.test.assertTrue * on 07-Jun-2020 */ class Sha256Test { + @BeforeTest + fun beforeTest() = testBlocking { + Initializer.initialize() + } + @Test fun statelessSimpleTest() { val expected = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" val result = Crypto.Sha256.stateless("test".encodeToUByteArray()).toHexString() - println("Result: $result") +// println("Result: $result") assertTrue { result == expected } } @@ -29,7 +37,7 @@ class Sha256Test { sha256.update("t".encodeToUByteArray()) sha256.update(("est".encodeToUByteArray())) val result = sha256.digest().toHexString() - println("Result: $result") +// println("Result: $result") assertTrue { result == expected } } } \ No newline at end of file diff --git a/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Test.kt b/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Test.kt index 4357ebe..88ea916 100644 --- a/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Test.kt +++ b/multiplatform-crypto-delegated/src/commonTest/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Test.kt @@ -1,8 +1,11 @@ package com.ionspin.kotlin.crypto.hash.sha import com.ionspin.kotlin.crypto.Crypto +import com.ionspin.kotlin.crypto.Initializer import com.ionspin.kotlin.crypto.hash.encodeToUByteArray +import com.ionspin.kotlin.crypto.util.testBlocking import com.ionspin.kotlin.crypto.util.toHexString +import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertTrue @@ -12,12 +15,17 @@ import kotlin.test.assertTrue * on 07-Jun-2020 */ class Sha512Test { + @BeforeTest + fun beforeTest() = testBlocking { + Initializer.initialize() + } + @Test fun statelessSimpleTest() { val expected = "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67" + "b143732c304cc5fa9ad8e6f57f50028a8ff" val result = Crypto.Sha512.stateless("test".encodeToUByteArray()).toHexString() - println("Result: $result") +// println("Result: $result") assertTrue { result == expected } } @@ -31,7 +39,7 @@ class Sha512Test { sha512.update("t".encodeToUByteArray()) sha512.update(("est".encodeToUByteArray())) val result = sha512.digest().toHexString() - println("Result: $result") +// println("Result: $result") assertTrue { result == expected } } } \ No newline at end of file diff --git a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/Initializer.kt b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/Initializer.kt index f51094d..9567243 100644 --- a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/Initializer.kt +++ b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/Initializer.kt @@ -21,12 +21,22 @@ fun setSodiumLoaded(loaded: Boolean) { } actual object Initializer { + private var isPlatformInitialized = false + actual suspend fun initialize() { JsSodiumLoader.load() + isPlatformInitialized = true } actual fun initializeWithCallback(done: () -> Unit) { + JsSodiumLoader.loadWithCallback { + isPlatformInitialized = true + done() + } + } + actual fun isInitialized(): Boolean { + return isPlatformInitialized } 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 e23432d..9233b77 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 @@ -10,14 +10,23 @@ import org.khronos.webgl.Uint8Array */ interface JsSodiumInterface { - fun crypto_generichash(hashLength: Int, inputMessage: Uint8Array): Uint8Array - fun randombytes_buf(numberOfBytes: Int): Uint8Array + fun crypto_generichash(hashLength: Int, inputMessage: Uint8Array, key: Uint8Array,): Uint8Array + fun crypto_hash_sha256(message: Uint8Array): Uint8Array fun crypto_hash_sha512(message: Uint8Array): Uint8Array + //Updateable + + fun crypto_generichash_init(key : Uint8Array, hashLength: Int) : dynamic + + fun crypto_generichash_update(state: dynamic, inputMessage: Uint8Array) + + fun crypto_generichash_final(state: dynamic, hashLength: Int) : Uint8Array + + fun crypto_hash_sha256_init() : dynamic fun crypto_hash_sha256_update(state: dynamic, message: Uint8Array) diff --git a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bDelegated.kt b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bDelegated.kt index ce671a1..25eb586 100644 --- a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bDelegated.kt +++ b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bDelegated.kt @@ -1,6 +1,7 @@ package com.ionspin.kotlin.crypto.hash.blake2b import com.ionspin.kotlin.crypto.getSodium +import com.ionspin.kotlin.crypto.hash.sha.Sha256StatelessDelegated import com.ionspin.kotlin.crypto.util.toHexString import org.khronos.webgl.Uint8Array import org.khronos.webgl.get @@ -12,18 +13,30 @@ import org.khronos.webgl.get */ -actual class Blake2bDelegated actual constructor(key: UByteArray?, hashLength: Int) : Blake2b { +actual class Blake2bDelegated actual constructor(key: UByteArray?, val hashLength: Int) : Blake2b { override val MAX_HASH_BYTES: Int = 64 - override fun update(data: UByteArray) { - TODO("not implemented yet") + val state : dynamic + + init { + state = getSodium().crypto_generichash_init( + Uint8Array(key?.toByteArray()?.toTypedArray() ?: arrayOf()), + hashLength + ) } - + override fun update(data: UByteArray) { + getSodium().crypto_generichash_update(state, Uint8Array(data.toByteArray().toTypedArray())) + } override fun digest(): UByteArray { - TODO("not implemented yet") + val hashed = getSodium().crypto_generichash_final(state, hashLength) + val hash = UByteArray(hashLength) + for (i in 0 until hashLength) { + hash[i] = hashed[i].toUByte() + } + return hash } } @@ -34,9 +47,12 @@ actual object Blake2bDelegatedStateless : Blake2bStateless { override val MAX_HASH_BYTES: Int = 64 override fun digest(inputMessage: UByteArray, key: UByteArray, hashLength: Int): UByteArray { - val hashed = getSodium().crypto_generichash(64, Uint8Array(inputMessage.toByteArray().toTypedArray())) - val hash = UByteArray(MAX_HASH_BYTES) - for (i in 0 until MAX_HASH_BYTES) { + val hashed = getSodium().crypto_generichash(hashLength, + Uint8Array(inputMessage.toByteArray().toTypedArray()), + Uint8Array(key.toByteArray().toTypedArray()) + ) + val hash = UByteArray(hashLength) + for (i in 0 until hashLength) { hash[i] = hashed[i].toUByte() } return hash diff --git a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt index 455de8e..935e18a 100644 --- a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt +++ b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt @@ -1,9 +1,6 @@ package com.ionspin.kotlin.crypto.hash.sha import com.ionspin.kotlin.crypto.getSodium -import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bDelegatedStateless - -import ext.libsodium.crypto_hash_sha256_init import org.khronos.webgl.Uint8Array import org.khronos.webgl.get @@ -15,7 +12,7 @@ import org.khronos.webgl.get */ -actual class Sha256Delegated actual constructor() : Sha256 { +actual class Sha256Delegated : Sha256 { val state : dynamic diff --git a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt index d5edc24..4d68c4d 100644 --- a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt +++ b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt @@ -13,7 +13,7 @@ import org.khronos.webgl.get */ -actual class Sha512Delegated actual constructor(key: UByteArray?, hashLength: Int) : Sha512 { +actual class Sha512Delegated : Sha512 { val state : dynamic init { diff --git a/multiplatform-crypto-delegated/src/jsTest/kotlin/com/ionspin/kotlin/crypto/SRNGJsTest.kt b/multiplatform-crypto-delegated/src/jsTest/kotlin/com/ionspin/kotlin/crypto/SRNGJsTest.kt index c2b1d5f..9324d37 100644 --- a/multiplatform-crypto-delegated/src/jsTest/kotlin/com/ionspin/kotlin/crypto/SRNGJsTest.kt +++ b/multiplatform-crypto-delegated/src/jsTest/kotlin/com/ionspin/kotlin/crypto/SRNGJsTest.kt @@ -34,14 +34,14 @@ class SRNGJsTest { JsSodiumLoader.load() val bytes1 = SRNG.getRandomBytes(10) val bytes2 = SRNG.getRandomBytes(10) - println("BYTES1\n") - bytes1.forEach { - print(it.toString(16).padStart(2, '0')) - } - println("BYTES2\n") - bytes2.forEach { - print(it.toString(16).padStart(2, '0')) - } +// println("BYTES1\n") +// bytes1.forEach { +// print(it.toString(16).padStart(2, '0')) +// } +// println("BYTES2\n") +// bytes2.forEach { +// print(it.toString(16).padStart(2, '0')) +// } assertTrue { !bytes1.contentEquals(bytes2) && bytes1.size == 10 && diff --git a/multiplatform-crypto-delegated/src/jsTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bJsTest.kt b/multiplatform-crypto-delegated/src/jsTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bJsTest.kt deleted file mode 100644 index 460b578..0000000 --- a/multiplatform-crypto-delegated/src/jsTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bJsTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.ionspin.kotlin.crypto.hash.blake2b - -import com.ionspin.kotlin.crypto.Crypto -import com.ionspin.kotlin.crypto.hash.encodeToUByteArray -import com.ionspin.kotlin.crypto.util.testBlocking -import com.ionspin.kotlin.crypto.util.toHexString -import kotlin.test.Test -import kotlin.test.assertEquals - -/** - * Created by Ugljesa Jovanovic - * ugljesa.jovanovic@ionspin.com - * on 25-May-2020 - */ - - -class Blake2bJsTest { - - @Test - fun testBlake2BSodiumInterop() = testBlocking { - Crypto.initialize() - val hash = Blake2bDelegatedStateless.digest("test".encodeToUByteArray()) - assertEquals(hash.toHexString(), "a71079d42853dea26e453004338670a53814b78137ffbed07603a41d76a4" + - "83aa9bc33b582f77d30a65e6f29a896c0411f38312e1d66e0bf16386c86a89bea572") - } - -} \ No newline at end of file diff --git a/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/Initializer.kt b/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/Initializer.kt index a0fb818..082ea90 100644 --- a/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/Initializer.kt +++ b/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/Initializer.kt @@ -1,9 +1,25 @@ package com.ionspin.kotlin.crypto +import com.goterl.lazycode.lazysodium.SodiumJava + actual object Initializer { + private var isPlatformInitialized = false + + lateinit var sodium : SodiumJava actual suspend fun initialize() { + sodium = SodiumJava() + isPlatformInitialized = true } actual fun initializeWithCallback(done: () -> Unit) { + sodium = SodiumJava() + isPlatformInitialized = true + done() } + + actual fun isInitialized(): Boolean { + return isPlatformInitialized + } + + } \ No newline at end of file diff --git a/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bDelegated.kt b/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bDelegated.kt index 68f65ae..7ab8196 100644 --- a/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bDelegated.kt +++ b/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bDelegated.kt @@ -1,5 +1,6 @@ package com.ionspin.kotlin.crypto.hash.blake2b +import com.ionspin.kotlin.crypto.Initializer.sodium /** * Created by Ugljesa Jovanovic * ugljesa.jovanovic@ionspin.com @@ -7,14 +8,22 @@ package com.ionspin.kotlin.crypto.hash.blake2b */ -actual class Blake2bDelegated actual constructor(key: UByteArray?, hashLength: Int) : Blake2b { +actual class Blake2bDelegated actual constructor(key: UByteArray?, val hashLength: Int) : Blake2b { + + val state = ByteArray(sodium.crypto_generichash_statebytes()) + + init { + sodium.crypto_generichash_init(state,key?.toByteArray() ?: byteArrayOf(), key?.size ?: 0, hashLength) + } override fun update(data: UByteArray) { - TODO("not implemented yet") + sodium.crypto_generichash_update(state, data.toByteArray(), data.size.toLong()) } override fun digest(): UByteArray { - TODO("not implemented yet") + val hashed = ByteArray(hashLength) + sodium.crypto_generichash_final(state, hashed, hashLength) + return hashed.toUByteArray() } } @@ -23,7 +32,9 @@ actual object Blake2bDelegatedStateless : Blake2bStateless { override fun digest(inputMessage: UByteArray, key: UByteArray, hashLength: Int): UByteArray { - TODO("not implemented yet") + val hashed = ByteArray(hashLength) + sodium.crypto_generichash(hashed, hashed.size, inputMessage.toByteArray(), inputMessage.size.toLong(), key.toByteArray(), key.size) + return hashed.toUByteArray() } } \ No newline at end of file diff --git a/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt b/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt new file mode 100644 index 0000000..8849dbd --- /dev/null +++ b/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt @@ -0,0 +1,41 @@ +package com.ionspin.kotlin.crypto.hash.sha + +import com.goterl.lazycode.lazysodium.interfaces.Hash +import com.ionspin.kotlin.crypto.Initializer.sodium + + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 17-Jul-2019 + */ + + +actual class Sha256Delegated actual constructor() : Sha256 { + + val state = Hash.State256() + + init { + sodium.crypto_hash_sha256_init(state) + } + + override fun update(data: UByteArray) { + sodium.crypto_hash_sha256_update(state, data.toByteArray(), data.size.toLong()) + } + + override fun digest(): UByteArray { + val hashed = ByteArray(Sha256Properties.MAX_HASH_BYTES) + sodium.crypto_hash_sha256_final(state, hashed) + return hashed.toUByteArray() + } + +} + +actual object Sha256StatelessDelegated : StatelessSha256 { + + override fun digest(inputMessage: UByteArray): UByteArray { + val hashed = ByteArray(Sha256Properties.MAX_HASH_BYTES) + sodium.crypto_hash_sha256(hashed, inputMessage.toByteArray(), inputMessage.size.toLong()) + return hashed.toUByteArray() + } +} \ No newline at end of file diff --git a/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256StatelessDelegated.kt b/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256StatelessDelegated.kt deleted file mode 100644 index 24be6d4..0000000 --- a/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256StatelessDelegated.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.ionspin.kotlin.crypto.hash.sha - -import java.security.MessageDigest - - -/** - * Created by Ugljesa Jovanovic - * ugljesa.jovanovic@ionspin.com - * on 17-Jul-2019 - */ - - -actual class Sha256Delegated actual constructor(key: UByteArray?, hashLength: Int) : Sha256 { - - override fun update(data: UByteArray) { - TODO("not implemented yet") - } - - override fun digest(): UByteArray { - TODO("not implemented yet") - } - -} - -actual object Sha256StatelessDelegated : StatelessSha256 { - - override fun digest(inputMessage: UByteArray): UByteArray { - val messageDigest = MessageDigest.getInstance("SHA-256") - messageDigest.update(inputMessage.toByteArray()) - return messageDigest.digest().toUByteArray() - } -} \ No newline at end of file diff --git a/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt b/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt index 8ee0645..ca00e48 100644 --- a/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt +++ b/multiplatform-crypto-delegated/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt @@ -1,5 +1,8 @@ package com.ionspin.kotlin.crypto.hash.sha +import com.goterl.lazycode.lazysodium.interfaces.Hash +import com.ionspin.kotlin.crypto.Initializer + /** * Created by Ugljesa Jovanovic * ugljesa.jovanovic@ionspin.com @@ -7,13 +10,22 @@ package com.ionspin.kotlin.crypto.hash.sha */ -actual class Sha512Delegated actual constructor(key: UByteArray?, hashLength: Int) : Sha512 { +actual class Sha512Delegated : Sha512 { + + val state = Hash.State512() + + init { + Initializer.sodium.crypto_hash_sha512_init(state) + } + override fun update(data: UByteArray) { - TODO("not implemented yet") + Initializer.sodium.crypto_hash_sha512_update(state, data.toByteArray(), data.size.toLong()) } override fun digest(): UByteArray { - TODO("not implemented yet") + val hashed = ByteArray(Sha512Properties.MAX_HASH_BYTES) + Initializer.sodium.crypto_hash_sha512_final(state, hashed) + return hashed.toUByteArray() } } @@ -21,6 +33,8 @@ actual class Sha512Delegated actual constructor(key: UByteArray?, hashLength: In actual object Sha512StatelessDelegated : StatelessSha512 { override fun digest(inputMessage: UByteArray): UByteArray { - TODO("not implemented yet") + val hashed = ByteArray(Sha512Properties.MAX_HASH_BYTES) + Initializer.sodium.crypto_hash_sha512(hashed, inputMessage.toByteArray(), inputMessage.size.toLong()) + return hashed.toUByteArray() } } \ No newline at end of file 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 c537533..882605a 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,19 +1,33 @@ 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 actual object Initializer { + + private var isPlatformInitialized : AtomicInt = AtomicInt(0) + actual suspend fun initialize() { - GlobalScope.launch { - sodium_init() + GlobalScope.launch() { + if (isPlatformInitialized.compareAndSet(0, 1)) { + sodium_init() + } } } actual fun initializeWithCallback(done: () -> Unit) { - sodium_init() + if (isPlatformInitialized.compareAndSet(0, 1)) { + sodium_init() + } done() } + + 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/hash/sha/Sha256Delegated.kt b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt index b0e5f38..b7d31a1 100644 --- a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt +++ b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha256Delegated.kt @@ -13,7 +13,7 @@ import platform.posix.malloc */ -actual class Sha256Delegated actual constructor() : Sha256 { +actual class Sha256Delegated : Sha256 { val state : crypto_hash_sha256_state diff --git a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt index b37c6e3..7e5991e 100644 --- a/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt +++ b/multiplatform-crypto-delegated/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/hash/sha/Sha512Delegated.kt @@ -12,7 +12,7 @@ import platform.posix.malloc */ -actual class Sha512Delegated actual constructor(key: UByteArray?, hashLength: Int) : Sha512 { +actual class Sha512Delegated : Sha512 { val state : crypto_hash_sha512_state init { diff --git a/multiplatform-crypto-delegated/src/nativeTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bLinuxTest.kt b/multiplatform-crypto-delegated/src/nativeTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bLinuxTest.kt deleted file mode 100644 index f50ecbf..0000000 --- a/multiplatform-crypto-delegated/src/nativeTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Blake2bLinuxTest.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.ionspin.kotlin.crypto.hash.blake2b - -/** - * Created by Ugljesa Jovanovic - * ugljesa.jovanovic@ionspin.com - * on 24-May-2020 - */ - -import com.ionspin.kotlin.crypto.Crypto -import com.ionspin.kotlin.crypto.hash.encodeToUByteArray -import com.ionspin.kotlin.crypto.util.testBlocking -import com.ionspin.kotlin.crypto.util.toHexString -import kotlinx.coroutines.runBlocking - -import kotlin.test.Test -import kotlin.test.assertTrue - -class Blake2bLinuxTest { - - @Test - fun testCinterop() { - runBlocking { - Crypto.initialize() - } - } - - @Test - fun testBlake2bUpdateable() = testBlocking { - val blake2b = Crypto.Blake2b.updateable() - blake2b.update("test".encodeToUByteArray()) - val result = blake2b.digest().toHexString() - println(result) - assertTrue { result.length > 2 } - } - - @Test - fun testBlake2BStateless() = testBlocking { - Blake2bDelegatedStateless.digest("test".encodeToUByteArray()) - } -} \ No newline at end of file diff --git a/multiplatform-crypto-delegated/src/nativeTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Sha512DelegatedLinuxTest.kt b/multiplatform-crypto-delegated/src/nativeTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Sha512DelegatedLinuxTest.kt deleted file mode 100644 index 685af96..0000000 --- a/multiplatform-crypto-delegated/src/nativeTest/kotlin/com/ionspin/kotlin/crypto/hash/blake2b/Sha512DelegatedLinuxTest.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.ionspin.kotlin.crypto.hash.blake2b - -/** - * Created by Ugljesa Jovanovic - * ugljesa.jovanovic@ionspin.com - * on 24-May-2020 - */ - -import com.ionspin.kotlin.crypto.Crypto -import com.ionspin.kotlin.crypto.hash.encodeToUByteArray -import com.ionspin.kotlin.crypto.util.testBlocking -import com.ionspin.kotlin.crypto.util.toHexString -import kotlinx.coroutines.runBlocking - -import kotlin.test.Test -import kotlin.test.assertTrue - -class Sha512DelegatedLinuxTest { - - @Test - fun testCinterop() { - runBlocking { - Crypto.initialize() - } - } - - @Test - fun testBlake2bUpdateable() = testBlocking { - val blake2b = Crypto.Blake2b.updateable() - blake2b.update("test".encodeToUByteArray()) - val result = blake2b.digest().toHexString() - println(result) - assertTrue { result.length > 2 } - } - - @Test - fun testBlake2BStateless() = testBlocking { - val result = Blake2bDelegatedStateless.digest("test".encodeToUByteArray()) - println(result.toHexString()) - } -} \ No newline at end of file