Merge pull request #25 from ionspin/fix-js-initalization

Fix js initalization
This commit is contained in:
Ugljesa Jovanovic 2022-03-25 16:42:41 +01:00 committed by GitHub
commit 87652f7014
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 45 additions and 52 deletions

View File

@ -2,6 +2,9 @@
(All dates are DD.MM.YYYY) (All dates are DD.MM.YYYY)
#### 0.8.6-SNAPSHOT #### 0.8.6-SNAPSHOT
- Bump to 1.6.20-RC2
- Fix for #23
- API change chacha20IetfXorIc now takes UInt initial counter parameter
#### 0.8.5 - 5.3.2022 #### 0.8.5 - 5.3.2022
- Libsodium updated to 7d67f1909bfa6e12254 (2022) - Libsodium updated to 7d67f1909bfa6e12254 (2022)

View File

@ -28,7 +28,7 @@ repositories {
} }
dependencies { dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10") implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.20-RC2")
implementation("com.android.tools.build:gradle:4.0.2") implementation("com.android.tools.build:gradle:4.0.2")
} }

View File

@ -16,7 +16,7 @@
object Versions { object Versions {
val kotlinCoroutines = "1.6.0-native-mt" val kotlinCoroutines = "1.6.0-native-mt"
val kotlin = "1.6.10" val kotlin = "1.6.20-RC2"
val kotlinSerialization = "1.3.2" val kotlinSerialization = "1.3.2"
val kotlinSerializationPlugin = kotlin val kotlinSerializationPlugin = kotlin
val atomicfu = "0.14.3-M2-2-SNAPSHOT" //NOTE: my linux arm32 and arm64 build val atomicfu = "0.14.3-M2-2-SNAPSHOT" //NOTE: my linux arm32 and arm64 build

View File

@ -21,7 +21,7 @@ expect object Stream {
fun chacha20XorIc(message : UByteArray, nonce: UByteArray, initialCounter: ULong, key: UByteArray) : UByteArray fun chacha20XorIc(message : UByteArray, nonce: UByteArray, initialCounter: ULong, key: UByteArray) : UByteArray
fun chacha20IetfXor(message : UByteArray, nonce: UByteArray, key: UByteArray) : UByteArray fun chacha20IetfXor(message : UByteArray, nonce: UByteArray, key: UByteArray) : UByteArray
fun chacha20IetfXorIc(message : UByteArray, nonce: UByteArray, initialCounter: ULong, key: UByteArray) : UByteArray fun chacha20IetfXorIc(message: UByteArray, nonce: UByteArray, initialCounter: UInt, key: UByteArray) : UByteArray
// fun xChacha20Keygen() : UByteArray // fun xChacha20Keygen() : UByteArray
// //

View File

@ -22,7 +22,7 @@ class SmokeTest {
val hashResult = GenericHash.genericHash("Hello".encodeToUByteArray(), 64) val hashResult = GenericHash.genericHash("Hello".encodeToUByteArray(), 64)
println("Smoke test: ${hashResult.toHexString()}") println("Smoke test: ${hashResult.toHexString()}")
assertTrue { assertTrue {
"EF15EAF92D5E335345A3E1D977BC7D8797C3D275717CC1B10AF79C93CDA01AEB2A0C59BC02E2BDF9380FD1B54EB9E1669026930CCC24BD49748E65F9A6B2EE68".toLowerCase() == hashResult.toHexString() "EF15EAF92D5E335345A3E1D977BC7D8797C3D275717CC1B10AF79C93CDA01AEB2A0C59BC02E2BDF9380FD1B54EB9E1669026930CCC24BD49748E65F9A6B2EE68".lowercase() == hashResult.toHexString().lowercase()
} }

View File

@ -64,4 +64,5 @@ class PasswordHashTest {
//TODO strNeedsRehash -1 case? //TODO strNeedsRehash -1 case?
} }
} }
} }

View File

@ -5,8 +5,6 @@ import com.ionspin.kotlin.crypto.util.LibsodiumRandom
import com.ionspin.kotlin.crypto.util.encodeToUByteArray import com.ionspin.kotlin.crypto.util.encodeToUByteArray
import com.ionspin.kotlin.crypto.util.randombytes_SEEDBYTES import com.ionspin.kotlin.crypto.util.randombytes_SEEDBYTES
import com.ionspin.kotlin.crypto.util.toHexString import com.ionspin.kotlin.crypto.util.toHexString
import kotlin.random.Random
import kotlin.random.nextUBytes
import com.ionspin.kotlin.crypto.util.runTest import com.ionspin.kotlin.crypto.util.runTest
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue

View File

@ -9,10 +9,10 @@ import org.khronos.webgl.Uint8Array
* ugljesa.jovanovic@ionspin.com * ugljesa.jovanovic@ionspin.com
* on 27-May-2020 * on 27-May-2020
*/ */
interface JsSodiumInterface { @JsModule("libsodium-wrappers-sumo")
@JsNonModule
external object JsSodiumInterface {
@JsName("sodium_init")
fun sodium_init() : Int
@JsName("crypto_generichash") @JsName("crypto_generichash")
fun crypto_generichash(hashLength: Int, inputMessage: Uint8Array, key: Uint8Array): Uint8Array fun crypto_generichash(hashLength: Int, inputMessage: Uint8Array, key: Uint8Array): Uint8Array

View File

@ -1,11 +1,7 @@
package ext.libsodium.com.ionspin.kotlin.crypto package ext.libsodium.com.ionspin.kotlin.crypto
import com.ionspin.kotlin.crypto.getSodiumLoaded import com.ionspin.kotlin.crypto.*
import com.ionspin.kotlin.crypto.setSodiumPointer
import com.ionspin.kotlin.crypto.sodiumLoaded
import com.ionspin.kotlin.crypto.sodiumPointer
import ext.libsodium.* import ext.libsodium.*
import kotlin.coroutines.Continuation
import kotlin.coroutines.suspendCoroutine import kotlin.coroutines.suspendCoroutine
/** /**
@ -25,18 +21,14 @@ object JsSodiumLoader {
} }
fun storeSodium(promisedSodium: dynamic, continuation: Continuation<Unit>) {
setSodiumPointer(promisedSodium)
sodiumLoaded = true
continuation.resumeWith(Result.success(Unit))
}
suspend fun load() = suspendCoroutine<Unit> { continuation -> suspend fun load() = suspendCoroutine<Unit> { continuation ->
console.log(getSodiumLoaded())
if (!getSodiumLoaded()) { if (!getSodiumLoaded()) {
val libsodiumModule = js("\$module\$libsodium_wrappers_sumo")
_libsodiumPromise.then<dynamic> { _libsodiumPromise.then<dynamic> {
storeSodium(libsodiumModule, continuation) sodium_init()
sodiumLoaded = true
continuation.resumeWith(Result.success(Unit))
}.catch { e ->
continuation.resumeWith(Result.failure(e))
} }
} else { } else {
continuation.resumeWith(Result.success(Unit)) continuation.resumeWith(Result.success(Unit))
@ -44,12 +36,9 @@ object JsSodiumLoader {
} }
fun loadWithCallback(doneCallback: () -> (Unit)) { fun loadWithCallback(doneCallback: () -> (Unit)) {
console.log(getSodiumLoaded())
if (!getSodiumLoaded()) { if (!getSodiumLoaded()) {
val libsodiumModule = js("\$module\$libsodium_wrappers_sumo")
_libsodiumPromise.then<dynamic> { _libsodiumPromise.then<dynamic> {
setSodiumPointer(libsodiumModule) sodium_init()
sodiumPointer.sodium_init()
sodiumLoaded = true sodiumLoaded = true
doneCallback.invoke() doneCallback.invoke()
} }

View File

@ -2,22 +2,15 @@ package com.ionspin.kotlin.crypto
import ext.libsodium.com.ionspin.kotlin.crypto.JsSodiumInterface import ext.libsodium.com.ionspin.kotlin.crypto.JsSodiumInterface
import ext.libsodium.com.ionspin.kotlin.crypto.JsSodiumLoader import ext.libsodium.com.ionspin.kotlin.crypto.JsSodiumLoader
/* 1.4-M1 has some weirdness with static/objects, or I'm misusing something, not sure */
lateinit var sodiumPointer : JsSodiumInterface
var sodiumLoaded: Boolean = false var sodiumLoaded: Boolean = false
fun getSodium() : JsSodiumInterface = sodiumPointer fun getSodium() : JsSodiumInterface = JsSodiumInterface
//fun getSodiumAdvanced() : JsSodiumAdvancedInterface = js("sodiumPointer.libsodium")
fun setSodiumPointer(jsSodiumInterface: JsSodiumInterface) {
js("sodiumPointer = jsSodiumInterface")
}
fun getSodiumLoaded() : Boolean = sodiumLoaded fun getSodiumLoaded() : Boolean = sodiumLoaded
fun setSodiumLoaded(loaded: Boolean) { fun setSodiumLoaded(loaded: Boolean) {
js("sodiumLoaded = loaded") sodiumLoaded = loaded
} }
actual object LibsodiumInitializer { actual object LibsodiumInitializer {

View File

@ -22,6 +22,9 @@ actual object PasswordHash {
memLimit: Int, memLimit: Int,
algorithm: Int algorithm: Int
): UByteArray { ): UByteArray {
if (opsLimit > UInt.MAX_VALUE) {
throw RuntimeException("Javascript doesnt support more than ${UInt.MAX_VALUE} for opslimit")
}
return getSodium().crypto_pwhash( return getSodium().crypto_pwhash(
outputLength.toUInt(), outputLength.toUInt(),
password.encodeToUByteArray().toUInt8Array(), password.encodeToUByteArray().toUInt8Array(),
@ -43,6 +46,9 @@ actual object PasswordHash {
* The function returns 0 on success and -1 if it didn't complete successfully. * The function returns 0 on success and -1 if it didn't complete successfully.
*/ */
actual fun str(password: String, opslimit: ULong, memlimit: Int): UByteArray { actual fun str(password: String, opslimit: ULong, memlimit: Int): UByteArray {
if (opslimit > UInt.MAX_VALUE) {
throw RuntimeException("Javascript doesnt support more than ${UInt.MAX_VALUE} for opslimit")
}
return getSodium().crypto_pwhash_str( return getSodium().crypto_pwhash_str(
password.encodeToUByteArray().toUInt8Array(), password.encodeToUByteArray().toUInt8Array(),
opslimit.toUInt(), opslimit.toUInt(),
@ -61,6 +67,9 @@ actual object PasswordHash {
opslimit: ULong, opslimit: ULong,
memlimit: Int memlimit: Int
): Int { ): Int {
if (opslimit > UInt.MAX_VALUE) {
throw RuntimeException("Javascript doesnt support more than ${UInt.MAX_VALUE} for opslimit")
}
return if ( return if (
getSodium().crypto_pwhash_str_needs_rehash( getSodium().crypto_pwhash_str_needs_rehash(
passwordHash.asByteArray().decodeToString(), passwordHash.asByteArray().decodeToString(),

View File

@ -29,14 +29,13 @@ actual object Stream {
actual fun chacha20IetfXorIc( actual fun chacha20IetfXorIc(
message: UByteArray, message: UByteArray,
nonce: UByteArray, nonce: UByteArray,
initialCounter: ULong, initialCounter: UInt,
key: UByteArray key: UByteArray
): UByteArray { ): UByteArray {
val result = getSodium().crypto_stream_chacha20_ietf_xor_ic( val result = getSodium().crypto_stream_chacha20_ietf_xor_ic(
message.toUInt8Array(), message.toUInt8Array(),
nonce.toUInt8Array(), nonce.toUInt8Array(),
initialCounter.toUInt(), initialCounter,
key.toUInt8Array() key.toUInt8Array()
) )
@ -69,6 +68,9 @@ actual object Stream {
initialCounter: ULong, initialCounter: ULong,
key: UByteArray key: UByteArray
): UByteArray { ): UByteArray {
if (initialCounter > UInt.MAX_VALUE) {
throw RuntimeException("Javascript doesnt support more than ${UInt.MAX_VALUE} for initial counter")
}
val result = getSodium().crypto_stream_chacha20_xor_ic( val result = getSodium().crypto_stream_chacha20_xor_ic(
message.toUInt8Array(), message.toUInt8Array(),
nonce.toUInt8Array(), nonce.toUInt8Array(),

View File

@ -1,4 +1,4 @@
@file:JsModule("libsodium-wrappers-sumo") @file:JsModule("libsodium-sumo")
@file:JsNonModule @file:JsNonModule
package ext.libsodium package ext.libsodium
@ -15,6 +15,9 @@ import kotlin.js.Promise
@JsName("ready") @JsName("ready")
external val _libsodiumPromise : Promise<dynamic> external val _libsodiumPromise : Promise<dynamic>
@JsName("_sodium_init")
external fun sodium_init() : Int
external fun crypto_generichash(hashLength: Int, inputMessage: Uint8Array) : Uint8Array external fun crypto_generichash(hashLength: Int, inputMessage: Uint8Array) : Uint8Array
external fun crypto_hash_sha256(message: Uint8Array) : Uint8Array external fun crypto_hash_sha256(message: Uint8Array) : Uint8Array

View File

@ -1236,7 +1236,7 @@ interface JnaLibsodiumInterface : Library {
message: ByteArray, message: ByteArray,
messageLength: Long, messageLength: Long,
nonce: ByteArray, nonce: ByteArray,
initialCounter : Long, initialCounter : Int,
key: ByteArray key: ByteArray
) : Int ) : Int

View File

@ -32,7 +32,7 @@ actual object Stream {
actual fun chacha20IetfXorIc( actual fun chacha20IetfXorIc(
message: UByteArray, message: UByteArray,
nonce: UByteArray, nonce: UByteArray,
initialCounter: ULong, initialCounter: UInt,
key: UByteArray key: UByteArray
): UByteArray { ): UByteArray {
val result = UByteArray(message.size) val result = UByteArray(message.size)
@ -42,7 +42,7 @@ actual object Stream {
message.asByteArray(), message.asByteArray(),
message.size.toLong(), message.size.toLong(),
nonce.asByteArray(), nonce.asByteArray(),
initialCounter.toLong(), initialCounter.toInt(),
key.asByteArray() key.asByteArray()
) )

View File

@ -60,7 +60,7 @@ actual object Stream {
actual fun chacha20IetfXorIc( actual fun chacha20IetfXorIc(
message: UByteArray, message: UByteArray,
nonce: UByteArray, nonce: UByteArray,
initialCounter: ULong, initialCounter: UInt,
key: UByteArray key: UByteArray
): UByteArray { ): UByteArray {
val result = UByteArray(message.size) val result = UByteArray(message.size)

View File

@ -185,6 +185,7 @@ kotlin {
implementation(kotlin(Deps.Common.test)) implementation(kotlin(Deps.Common.test))
implementation(Deps.Common.serialization) implementation(Deps.Common.serialization)
api(project(":multiplatform-crypto-libsodium-bindings")) api(project(":multiplatform-crypto-libsodium-bindings"))
implementation(Deps.Common.coroutines)
} }
} }
val commonTest by getting { val commonTest by getting {
@ -203,7 +204,6 @@ kotlin {
implementation("androidx.constraintlayout:constraintlayout:2.0.2") implementation("androidx.constraintlayout:constraintlayout:2.0.2")
implementation("com.google.android.material:material:1.3.0-alpha03") implementation("com.google.android.material:material:1.3.0-alpha03")
implementation(Deps.Android.coroutines)
implementation(Deps.Android.timber) implementation(Deps.Android.timber)
// implementation("androidx.compose:compose-runtime:$composeDevVersion") // implementation("androidx.compose:compose-runtime:$composeDevVersion")
} }
@ -212,9 +212,7 @@ kotlin {
dependencies { dependencies {
implementation(kotlin(Deps.Jvm.test)) implementation(kotlin(Deps.Jvm.test))
implementation(kotlin(Deps.Jvm.testJUnit)) implementation(kotlin(Deps.Jvm.testJUnit))
implementation(Deps.Jvm.coroutinesTest)
implementation(kotlin(Deps.Jvm.reflection)) implementation(kotlin(Deps.Jvm.reflection))
implementation(Deps.Jvm.coroutinesCore)
} }
} }
@ -255,7 +253,6 @@ kotlin {
val nativeTest by getting { val nativeTest by getting {
dependsOn(commonTest) dependsOn(commonTest)
dependencies { dependencies {
implementation(Deps.Native.coroutines)
} }
} }
nativeTest nativeTest
@ -263,7 +260,6 @@ kotlin {
val nativeTest by creating { val nativeTest by creating {
dependsOn(commonTest) dependsOn(commonTest)
dependencies { dependencies {
implementation(Deps.Native.coroutines)
} }
} }
nativeTest nativeTest
@ -281,14 +277,13 @@ kotlin {
dependencies { dependencies {
implementation(kotlin(Deps.Jvm.test)) implementation(kotlin(Deps.Jvm.test))
implementation(kotlin(Deps.Jvm.testJUnit)) implementation(kotlin(Deps.Jvm.testJUnit))
implementation(Deps.Jvm.coroutinesTest)
implementation(kotlin(Deps.Jvm.reflection)) implementation(kotlin(Deps.Jvm.reflection))
} }
} }
val jsMain by getting { val jsMain by getting {
dependencies { dependencies {
implementation(kotlin(Deps.Js.stdLib)) implementation(kotlin(Deps.Js.stdLib))
implementation(Deps.Js.coroutines)
} }
} }
val jsTest by getting { val jsTest by getting {